Medien-App-Architektur – Übersicht

In diesem Abschnitt wird erläutert, wie eine Mediaplayer-App in einen Mediacontroller (für die UI) und eine Mediensitzung (für den eigentlichen Player) aufgeteilt wird. Es werden zwei Architekturen von Medienanwendungen beschrieben: ein Client/Server-Design, das sich gut für Audio-Apps eignet, und ein Design mit einer einzigen Aktivität für Videoplayer. Außerdem erfahren Sie, wie Medien-Apps auf Hardwaresteuerelemente reagieren und mit anderen Apps zusammenarbeiten, die den Audioausgabestream verwenden.

Player und Benutzeroberfläche

Eine Multimedia-Anwendung, die Audio- oder Videoinhalte abspielt, besteht normalerweise aus zwei Teilen:

  • Ein Player, der digitale Medien aufnimmt und als Video- und/oder Audio-
  • Eine Benutzeroberfläche mit Transportsteuerelementen zum Ausführen des Players und optional zur Anzeige seines Status

UI und Player

In Android können Sie Ihren eigenen Player von Grund auf neu erstellen, oder Sie können eine der folgenden Optionen wählen:

  • Die Klasse MediaPlayer bietet die grundlegenden Funktionen für einen einfachen Player, der die gängigsten Audio-/Videoformate und Datenquellen unterstützt.
  • ExoPlayer ist eine Open-Source-Bibliothek, die auf untergeordneten Media-Framework-Komponenten wie MediaCodec und AudioTrack aufbaut. ExoPlayer unterstützt leistungsstarke Funktionen wie DASH, die in MediaPlayer nicht verfügbar sind. Der ExoPlayer-Code lässt sich anpassen, um neue Komponenten ganz einfach hinzuzufügen. ExoPlayer kann nur mit der Android-Version 4.1 und höher verwendet werden.

Mediensitzung und Mediensteuerung

Während die APIs für die Benutzeroberfläche und den Player beliebig sein können, ist die Art der Interaktion zwischen den beiden Teilen im Grunde für alle Mediaplayer-Apps gleich. Das Android-Framework definiert zwei Klassen, eine Mediensitzung und einen Medien-Controller,die eine klar definierte Struktur zum Erstellen einer Mediaplayer-App bieten.

Die Mediensitzung und der Mediencontroller kommunizieren über vordefinierte Callbacks, die den standardmäßigen Playeraktionen (Wiedergabe, Pause, Stopp usw.) entsprechen, sowie über erweiterbare benutzerdefinierte Aufrufe, mit denen Sie spezielle Verhaltensweisen definieren können, die für Ihre App spezifisch sind.

Controller-und-Sitzung

Mediensitzung

Eine Mediensitzung ist für die gesamte Kommunikation mit dem Player verantwortlich. Die API des Players wird dadurch für den Rest der App ausgeblendet. Er wird nur in der Mediensitzung aufgerufen, die ihn steuert.

Die Sitzung enthält eine Darstellung des Player-Status (wird wiedergegeben/pausiert) und Informationen darüber, was gerade läuft. Eine Sitzung kann Callbacks von einem oder mehreren Mediencontrollern erhalten. So kann Ihr Player sowohl über die Benutzeroberfläche Ihrer App als auch über Begleitgeräte mit Wear OS und Android Auto gesteuert werden. Die Logik, die auf Rückrufe reagiert, muss einheitlich sein. Die Antwort auf einen MediaSession-Callback sollte immer gleich sein, unabhängig davon, von welcher Client-App der Callback initiiert wurde.

Mediencontroller

Ein Mediencontroller isoliert Ihre Benutzeroberfläche. Der UI-Code kommuniziert nur mit dem Mediencontroller, nicht mit dem Player selbst. Der Mediencontroller wandelt Transportsteuerungsaktionen in Callbacks für die Mediensitzung um. Außerdem erhält es immer dann Callbacks von der Mediensitzung, wenn sich der Sitzungsstatus ändert. Dadurch wird ein Mechanismus zur automatischen Aktualisierung der zugehörigen UI bereitgestellt. Ein Medien-Controller kann jeweils nur mit einer Mediensitzung verbunden sein.

Wenn Sie einen Mediencontroller und eine Mediensitzung verwenden, können Sie zur Laufzeit verschiedene Schnittstellen und/oder Player bereitstellen. Sie können das Aussehen und/oder die Leistung Ihrer App unabhängig von den Funktionen des Geräts ändern, auf dem sie ausgeführt wird.

Video-Apps und Audio-Apps im Vergleich

Wenn du ein Video abspielst, sind sowohl deine Augen als auch deine Ohren verbunden. Bei der Audiowiedergabe hören Sie zu, können aber auch gleichzeitig mit einer anderen App arbeiten. Für jeden Anwendungsfall gibt es ein anderes Design.

Video-App

Eine Video-App benötigt ein Fenster, in dem Inhalte angezeigt werden können. Aus diesem Grund wird eine Video-App normalerweise als einzelne Android-Aktivität implementiert. Der Bildschirm, auf dem das Video angezeigt wird, ist Teil der Aktivität.

Videoplayer-Aktivität

Audio-App

Die Benutzeroberfläche eines Audioplayers muss nicht immer sichtbar sein. Sobald die Audiowiedergabe beginnt, kann der Player als Hintergrundaufgabe ausgeführt werden. Der Nutzer kann zu einer anderen App wechseln und weiterarbeiten.

Um dieses Design in Android zu implementieren, kannst du eine Audio-App mit zwei Komponenten erstellen: einer Aktivität für die Benutzeroberfläche und einem Dienst für den Player. Wenn der Nutzer zu einer anderen App wechselt, kann der Dienst im Hintergrund ausgeführt werden. Wenn die beiden Teile einer Audio-App in separate Komponenten unterteilt werden, kann jede einzeln effizienter ausgeführt werden. Eine UI ist im Vergleich zu einem Player, der lange Zeit ohne UI ausgeführt werden kann, in der Regel kurzlebig.

Audioaktivitäten und BrowserService

Die Supportbibliothek bietet zwei Klassen zur Implementierung dieses Client/Server-Ansatzes: MediaBrowserService und MediaBrowser. Die Dienstkomponente wird als abgeleitete Klasse von MediaBrowserService implementiert, die die Mediensitzung und ihren Player enthält. Die Aktivität mit der Benutzeroberfläche und dem Mediencontroller sollte ein MediaBrowser enthalten, das mit der MediaBrowserService kommuniziert.

Mit MediaBrowserService ist es für Begleitgeräte wie Android Auto und Wear ganz einfach, deine App zu finden, eine Verbindung zu ihr herzustellen, nach Inhalten zu suchen und die Wiedergabe zu steuern, ohne auf die UI-Aktivitäten deiner App zugreifen zu müssen. Tatsächlich können mehrere Anwendungen gleichzeitig mit derselben MediaBrowserService verbunden sein, wobei jede Anwendung eine eigene MediaController hat. Eine Anwendung, die eine MediaBrowserService anbietet, sollte mehrere gleichzeitige Verbindungen verarbeiten können.

Medien-Apps und die Android-Audioinfrastruktur

Eine gut konzipierte Medien-App sollte mit anderen Apps, die Audio wiedergeben, "gut zusammen funktionieren". Dieser sollte für die gemeinsame Nutzung des Telefons und die Zusammenarbeit mit anderen Audio-Apps auf dem Gerät bereit sein. Es sollte auch auf Hardware-Steuerelemente des Geräts reagieren.

Spielt mit anderen

All dieses Verhalten wird unter Audioausgabe steuern beschrieben.

Mediacompat-Bibliothek

Die media-compat-Bibliothek enthält Klassen, die beim Erstellen von Apps zur Wiedergabe von Audio- und Videoinhalten hilfreich sind. Diese Klassen sind mit Geräten mit Android 2.3 (API-Level 9) und höher kompatibel. Sie funktionieren auch mit anderen Android-Funktionen und schaffen so eine angenehme, vertraute Android-Umgebung.

Die empfohlene Implementierung von Mediensitzungen und Mediencontrollern sind die Klassen MediaSessionCompat und MediaControllerCompat, die in der media-compat-Supportbibliothek definiert sind. Sie ersetzen frühere Versionen der Klassen MediaSession und MediaController, die in Android 5.0 (API-Level 21) eingeführt wurden. Die Compat-Klassen bieten die gleiche Funktionalität, erleichtern Ihnen aber die Entwicklung Ihrer Anwendung, da Sie nur in eine API schreiben müssen. Die Bibliothek sorgt für die Abwärtskompatibilität, indem Mediensitzungsmethoden in die entsprechenden Methoden von älteren Plattformversionen (sofern verfügbar) übersetzt werden.

Wenn Sie bereits eine funktionierende App haben, die die älteren Klassen verwendet, empfehlen wir, auf die Compat-Klassen zu aktualisieren. Wenn Sie die kompatiblen Versionen verwenden, können Sie alle Aufrufe von registerMediaButtonReceiver() und alle Methoden aus RemoteControlClient entfernen.

Leistungsmessung

In Android 8.0 (API-Level 26) und höher ist die Methode getMetrics() für einige Medienklassen verfügbar. Sie gibt ein PersistableBundle-Objekt mit Konfigurations- und Leistungsinformationen zurück, die als Zuordnung von Attributen und Werten ausgedrückt werden. Die Methode getMetrics() ist für diese Medienklassen definiert:

Messwerte werden für jede Instanz separat erfasst und bleiben für die Lebensdauer der Instanz bestehen. Wenn keine Messwerte verfügbar sind, gibt die Methode null zurück. Die tatsächlich zurückgegebenen Messwerte hängen von der Klasse ab.