Jetpack Media3 definiert eine Player-Schnittstelle, die grundlegende Funktionen für die Wiedergabe von Video- und Audiodateien beschreibt. ExoPlayer ist die Standardimplementierung dieser Schnittstelle in Media3. Wir empfehlen die Verwendung von ExoPlayer, da er eine umfassende Reihe von Funktionen bietet, die die meisten Wiedergabeanwendungsfälle abdecken, und an alle zusätzlichen Anwendungsfälle angepasst werden kann. ExoPlayer abstrahiert auch die Geräte- und Betriebssystemfragmentierung, sodass Ihr Code im gesamten Android-Ökosystem einheitlich funktioniert. ExoPlayer umfasst:
- Unterstützung für Playlists
- Unterstützung für eine Vielzahl von progressiven und adaptiven Streaming Formaten
- Unterstützung für die Anzeigenbereitstellung auf Client- und Serverseite ad insertion
- Unterstützung für die Wiedergabe von DRM-geschützten Inhalten
Auf dieser Seite werden einige der wichtigsten Schritte zum Erstellen einer Wiedergabe App beschrieben. Weitere Informationen finden Sie in unseren vollständigen Leitfäden zu Media3 ExoPlayer.
Erste Schritte
Fügen Sie zuerst eine Abhängigkeit von den ExoPlayer-, UI- und Common-Modulen von Jetpack Media3 hinzu:
implementation "androidx.media3:media3-exoplayer:1.10.0" implementation "androidx.media3:media3-ui:1.10.0" implementation "androidx.media3:media3-common:1.10.0"
Je nach Anwendungsfall benötigen Sie möglicherweise auch zusätzliche Module von Media3, z. B. exoplayer-dash zum Abspielen von Streams im DASH-Format.
Ersetzen Sie 1.10.0 durch die gewünschte Version der Bibliothek. Die neueste Version finden Sie in den Versionshinweisen.
Mediaplayer erstellen
Mit Media3 können Sie entweder die enthaltene Implementierung der Player
Schnittstelle, ExoPlayer, verwenden oder eine eigene benutzerdefinierte Implementierung erstellen.
ExoPlayer erstellen
Die einfachste Methode zum Erstellen einer ExoPlayer-Instanz ist folgende:
Kotlin
val player = ExoPlayer.Builder(context).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build();
Sie können Ihren Mediaplayer in der Lebenszyklusmethode onCreate() der Activity, des Fragment oder des Service erstellen, in dem er sich befindet.
Der Builder enthält
eine Reihe von Anpassungsoptionen, die für Sie interessant sein könnten, z. B.:
setAudioAttributes()zum Konfigurieren der Audiofokus-VerwaltungsetHandleAudioBecomingNoisy()zum Konfigurieren des Wiedergabeverhaltens, wenn ein Audioausgabegerät getrennt wirdsetTrackSelector()zum Konfigurieren der Titelauswahl
Media3 bietet eine UI-Komponente PlayerView, die Sie in die Layoutdatei Ihrer App einfügen können. Diese Komponente kapselt eine PlayerControlView für die Wiedergabesteuerung, eine SubtitleView zum Anzeigen von Untertiteln und eine Surface zum Rendern von Videos.
Player vorbereiten
Fügen Sie einer Playlist Medienelemente zur
Wiedergabe mit Methoden wie
setMediaItem()
und addMediaItem() hinzu.
Rufen Sie dann prepare() auf, um
das Laden von Medien zu starten und die erforderlichen Ressourcen abzurufen.
Diese Schritte sollten erst ausgeführt werden, wenn sich die App im Vordergrund befindet. Wenn sich Ihr Player in einer Activity oder einem Fragment befindet, bedeutet dies, dass Sie den Player in der Lebenszyklusmethode onStart() auf API-Level 24 und höher oder in der Lebenszyklusmethode onResume() auf API-Level 23 und niedriger vorbereiten müssen. Bei einem Player, der sich in einem Service befindet, können Sie ihn in onCreate() vorbereiten. Ein Beispiel für die Implementierung von Lebenszyklusmethoden finden Sie im ExoPlayer-Codelab.
Player steuern
Nachdem der Player vorbereitet wurde, können Sie die Wiedergabe steuern, indem Sie Methoden auf dem Player aufrufen, z. B.:
play()undpause()zum Starten und Pausieren der WiedergabeseekTo()zum Suchen einer Position im aktuellen MedienelementseekToNextMediaItem()undseekToPreviousMediaItem()zum Navigieren in der Playlist
UI-Komponenten wie PlayerView oder PlayerControlView werden entsprechend aktualisiert, wenn sie an einen Player gebunden sind.
Player freigeben
Für die Wiedergabe sind möglicherweise Ressourcen erforderlich, die nur begrenzt verfügbar sind, z. B. Video
decoder. Daher ist es wichtig, release()
auf Ihrem Player aufzurufen, um Ressourcen freizugeben, wenn der Player nicht mehr benötigt wird.
Wenn sich Ihr Player in einer Activity oder einem Fragment befindet, geben Sie den Player in der Lebenszyklusmethode onStop() auf API-Level 24 und höher oder in der Methode onPause() auf API-Level 23 und niedriger frei. Bei einem Player, der sich in einem Service befindet, können Sie ihn in onDestroy() freigeben. Ein Beispiel für die Implementierung von Lebenszyklusmethoden finden Sie im ExoPlayer-Codelab.
Wiedergabe mit einer Media Session verwalten
In Android bieten Media Sessions eine standardisierte Möglichkeit, über Prozessgrenzen hinweg mit einem Mediaplayer zu interagieren. Wenn Sie eine Media Session mit Ihrem Player verbinden können Sie die Medienwiedergabe extern bewerben und Wiedergabebefehle von externen Quellen empfangen, z. B. um sie in die Systemmediensteuerung auf Mobilgeräten und Geräten mit großem Bildschirm zu integrieren.
Wenn Sie Media Sessions verwenden möchten, fügen Sie eine Abhängigkeit vom Media3 Session-Modul hinzu:
implementation "androidx.media3:media3-session:1.10.0"
Media Session erstellen
Sie können eine MediaSession erstellen, nachdem Sie einen Player wie folgt initialisiert haben:
Kotlin
val player = ExoPlayer.Builder(context).build() val mediaSession = MediaSession.Builder(context, player).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build(); MediaSession mediaSession = new MediaSession.Builder(context, player).build();
Media3 synchronisiert den Status des Player automatisch mit dem Status der MediaSession. Dies funktioniert mit jeder Player Implementierung, einschließlich
ExoPlayer, CastPlayer oder einer
benutzerdefinierten Implementierung.
Anderen Clients die Kontrolle überlassen
Client-Apps können einen Media Controller
implementieren, um die Wiedergabe Ihrer Media Session zu steuern. Wenn Sie diese Anfragen empfangen möchten, legen Sie beim
Erstellen Ihrer MediaSession ein
Callback-Objekt fest.
Wenn ein Controller eine Verbindung zu Ihrer Media Session herstellt, wird die
onConnect()
Methode aufgerufen. Anhand der bereitgestellten ControllerInfo
können Sie entscheiden, ob Sie die Anfrage annehmen
oder ablehnen. Ein Beispiel dafür finden Sie in der Media3 Session-Demo-App.
Nachdem eine Verbindung hergestellt wurde, kann ein Controller Wiedergabebefehle an die Session senden. Die Session leitet diese Befehle dann an den Player weiter. Wiedergabe- und Playlist-Befehle, die in der Player-Schnittstelle definiert sind, werden automatisch von der Session verarbeitet.
Mit anderen Callback-Methoden können Sie beispielsweise Anfragen für
benutzerdefinierte Wiedergabebefehle
und das Ändern der Playlistverarbeiten. Diese Callbacks enthalten ebenfalls ein ControllerInfo-Objekt, sodass Sie die Zugriffssteuerung auf Anfragebasis festlegen können.
Medien im Hintergrund abspielen
Wenn Sie Medien weiter abspielen möchten, wenn sich Ihre App nicht im Vordergrund befindet, z. B.
um Musik, Hörbücher oder Podcasts abzuspielen, auch wenn der Nutzer Ihre App
nicht geöffnet hat, sollten Player und MediaSession in einem
Dienst im Vordergrund gekapselt sein. Media3 bietet hierfür die MediaSessionService-Schnittstelle.
MediaSessionService implementieren
Erstellen Sie eine Klasse, die MediaSessionService erweitert, und instanziieren Sie Ihre
MediaSession in der onCreate() Lebenszyklusmethode.
Kotlin
class PlaybackService : MediaSessionService() { private var mediaSession: MediaSession? = null // Create your Player and MediaSession in the onCreate lifecycle event override fun onCreate() { super.onCreate() val player = ExoPlayer.Builder(this).build() mediaSession = MediaSession.Builder(this, player).build() } // Remember to release the player and media session in onDestroy override fun onDestroy() { mediaSession?.run { player.release() release() mediaSession = null } super.onDestroy() } }
Java
public class PlaybackService extends MediaSessionService { private MediaSession mediaSession = null; @Override public void onCreate() { super.onCreate(); ExoPlayer player = new ExoPlayer.Builder(this).build(); mediaSession = new MediaSession.Builder(this, player).build(); } @Override public void onDestroy() { mediaSession.getPlayer().release(); mediaSession.release(); mediaSession = null; super.onDestroy(); } }
Fügen Sie in Ihrem Manifest Ihre Service Klasse mit einem MediaSessionService Intent
Filter hinzu und fordern Sie die Berechtigung FOREGROUND_SERVICE an, um einen Dienst im Vordergrund
auszuführen:
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaSessionService"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Überschreiben Sie schließlich in der von Ihnen erstellten Klasse die Methode onGetSession(), um den Clientzugriff auf Ihre Media Session zu steuern. Geben Sie eine MediaSession zurück, um die Verbindungsanfrage anzunehmen, oder geben Sie null zurück, um die Anfrage abzulehnen.
Kotlin
// This example always accepts the connection request override fun onGetSession( controllerInfo: MediaSession.ControllerInfo ): MediaSession? = mediaSession
Java
@Override public MediaSession onGetSession(MediaSession.ControllerInfo controllerInfo) { // This example always accepts the connection request return mediaSession; }
Verbindung zur UI herstellen
Da sich Ihre Media Session jetzt in einem Service befindet, der von der Activity oder dem Fragment getrennt ist, in dem sich die Player-UI befindet, können Sie sie mit einem MediaController verknüpfen. Erstellen Sie in der Methode onStart() der Activity oder des Fragment mit Ihrer UI ein SessionToken für Ihre MediaSession und verwenden Sie dann das SessionToken, um einen MediaController zu erstellen. Das Erstellen eines MediaController erfolgt asynchron.
Kotlin
override fun onStart() { val sessionToken = SessionToken(this, ComponentName(this, PlaybackService::class.java)) val controllerFuture = MediaController.Builder(this, sessionToken).buildAsync() controllerFuture.addListener( { // Call controllerFuture.get() to retrieve the MediaController. // MediaController implements the Player interface, so it can be // attached to the PlayerView UI component. playerView.setPlayer(controllerFuture.get()) }, MoreExecutors.directExecutor() ) }
Java
@Override public void onStart() { SessionToken sessionToken = new SessionToken(this, new ComponentName(this, PlaybackService.class)); ListenableFuture<MediaController> controllerFuture = new MediaController.Builder(this, sessionToken).buildAsync(); controllerFuture.addListener(() -> { // Call controllerFuture.get() to retrieve the MediaController. // MediaController implements the Player interface, so it can be // attached to the PlayerView UI component. playerView.setPlayer(controllerFuture.get()); }, MoreExecutors.directExecutor()) }
MediaController implementiert die Player-Schnittstelle, sodass Sie dieselben Methoden wie play() und pause() verwenden können, um die Wiedergabe zu steuern. Ähnlich wie bei anderen
Komponenten müssen Sie den MediaController freigeben, wenn er nicht mehr
benötigt wird, z. B. in der onStop() Lebenszyklusmethode einer Activity, indem Sie
MediaController.releaseFuture() aufrufen.
Benachrichtigung veröffentlichen
Dienste im Vordergrund müssen eine Benachrichtigung veröffentlichen, während sie aktiv sind. A
MediaSessionService erstellt automatisch eine
MediaStyle Benachrichtigung für
Sie in Form einer MediaNotification.
Wenn Sie eine benutzerdefinierte Benachrichtigung bereitstellen möchten, erstellen Sie ein
MediaNotification.Provider
mit DefaultMediaNotificationProvider.Builder
oder indem Sie eine benutzerdefinierte Implementierung der Provider-Schnittstelle erstellen. Fügen Sie Ihren
Provider zu Ihrer MediaSession mit
setMediaNotificationProvider hinzu.
Inhaltsbibliothek bewerben
Ein MediaLibraryService baut auf einem MediaSessionService auf und ermöglicht es Client
Apps, die von Ihrer App bereitgestellten Medieninhalte zu durchsuchen. Client-Apps implementieren einen
MediaBrowser, um mit Ihrem MediaLibraryService zu interagieren.
Die Implementierung eines MediaLibraryService ähnelt der Implementierung eines
MediaSessionService. Der Unterschied besteht darin, dass Sie in onGetSession() eine
MediaLibrarySession anstelle einer MediaSession zurückgeben sollten. Im Vergleich zu einem MediaSession.Callback enthält der MediaLibrarySession.Callback zusätzliche Methoden, mit denen ein Browserclient die von Ihrem Bibliotheksdienst angebotenen Inhalte durchsuchen kann.
Ähnlich wie beim MediaSessionService deklarieren Sie den MediaLibraryService in Ihrem Manifest und fordern Sie die Berechtigung FOREGROUND_SERVICE an, um einen Dienst im Vordergrund auszuführen:
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaLibraryService"/>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Das obige Beispiel enthält einen Intent-Filter für den MediaLibraryService und aus Gründen der Abwärtskompatibilität auch für den älteren MediaBrowserService. Der zusätzliche Intent-Filter ermöglicht es Client-Apps, die die MediaBrowserCompat-API verwenden, Ihren Service zu erkennen.
Mit einer MediaLibrarySession können Sie Ihre Inhaltsbibliothek in einer Baumstruktur mit einem einzelnen Stamm-MediaItem bereitstellen. Jedes MediaItem im Baum kann eine beliebige Anzahl untergeordneter MediaItem-Knoten haben. Sie können je nach Anfrage der Client-App einen anderen Stamm oder einen anderen Baum bereitstellen. Beispielsweise enthält der Baum, den Sie an einen Client zurückgeben, der nach einer Liste empfohlener Medienelemente sucht, möglicherweise nur den Stamm-MediaItem und eine einzelne Ebene untergeordneter MediaItem-Knoten. Der Baum, den Sie an eine andere Client-App zurückgeben, kann jedoch eine vollständigere Inhaltsbibliothek darstellen.
MediaLibrarySession erstellen
Eine MediaLibrarySession
erweitert die MediaSession-API um APIs zum Durchsuchen von Inhalten. Im Vergleich zum
MediaSession Callback,
fügt der MediaLibrarySession Callback
Methoden wie die folgenden hinzu:
onGetLibraryRoot()für den Fall, dass ein Client das Stamm-MediaItemeines Inhaltsbaums anfordertonGetChildren()für den Fall, dass ein Client die untergeordneten Elemente einesMediaItemim Inhaltsbaum anfordertonGetSearchResult()für den Fall, dass ein Client Suchergebnisse aus dem Inhaltsbaum für eine bestimmte Abfrage anfordert
Relevante Callback-Methoden enthalten ein LibraryParams
Objekt mit zusätzlichen Signalen zum Typ des Inhaltsbaums, an dem eine Client-App
interessiert ist.