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 sowohl clientseitig als auch serverseitig 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:
Kotlin
implementation("androidx.media3:media3-exoplayer:1.10.1")
implementation("androidx.media3:media3-ui:1.10.1")
implementation("androidx.media3:media3-common:1.10.1")
Groovy
implementation "androidx.media3:media3-exoplayer:1.10.1"
implementation "androidx.media3:media3-ui:1.10.1"
implementation "androidx.media3:media3-common:1.10.1"
Je nach Anwendungsfall benötigen Sie möglicherweise auch zusätzliche Module von Media3, z. B. exoplayer-dash, um Streams im DASH-Format abzuspielen.
Ersetzen Sie 1.10.1 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 onCreate()-Methode des Lebenszyklus 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(), um die Audiofokusverwaltung zu konfigurierensetHandleAudioBecomingNoisy(), um das Wiedergabeverhalten zu konfigurieren, wenn ein Audioausgabegerät getrennt wirdsetTrackSelector(), um Titelauswahl zu konfigurieren
Media3 bietet eine PlayerView-UI-Komponente, die Sie in die Layoutdatei Ihrer App einfügen können. Diese Komponente kapselt eine PlayerControlView für die Wiedergabesteuerung, eine SubtitleView für die Anzeige von Untertiteln und eine Surface für die Videowiedergabe.
Player vorbereiten
Fügen Sie einer Playlist mit Methoden wie
setMediaItem() und addMediaItem() Medienelemente für die Wiedergabe hinzu. Rufen Sie dann prepare() auf, um
Medien zu laden 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 das, dass Sie den Player in der onStart()-Methode des Lebenszyklus auf API-Ebene 24 und höher oder in der onResume()-Methode des Lebenszyklus auf API-Ebene 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 Methoden des Lebenszyklus finden Sie im ExoPlayer-Codelab.
Player steuern
Nachdem der Player vorbereitet wurde, können Sie die Wiedergabe steuern, indem Sie Methoden wie die folgenden aufrufen:
play()undpause(), um die Wiedergabe zu starten und zu pausierenseekTo(), um zu einer bestimmten Position im aktuellen Medienelement zu springenseekToNextMediaItem()undseekToPreviousMediaItem(), um in der Playlist zu navigieren
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() für Ihren 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 onStop()-Methode des Lebenszyklus auf API-Ebene 24 und höher oder in der onPause()-Methode auf API-Ebene 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 Methoden des Lebenszyklus 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 Mediensteuerung des Systems zu integrieren auf Mobilgeräten und Geräten mit großem Bildschirm.
Wenn Sie Media Sessions verwenden möchten, fügen Sie eine Abhängigkeit vom Media3 Session-Modul hinzu:
Kotlin
implementation("androidx.media3:media3-session:1.10.1")
Groovy
implementation "androidx.media3:media3-session:1.10.1"
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. Das funktioniert mit jeder Player Implementierung, einschließlich
ExoPlayer, CastPlayer oder einer benutzerdefinierten Implementierung.
Anderen Clients die Kontrolle überlassen
Client-Apps können eine Mediensteuerung 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 herstellen möchte, wird die onConnect()
Methode aufgerufen. Mit der bereitgestellten ControllerInfo können Sie entscheiden, ob
Sie die Anfrage annehmen oder ablehnen möchten. 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 verarbeiten und die Playlist ändern. Diese Callbacks enthalten ebenfalls
ein ControllerInfo-Objekt, sodass Sie die Zugriffssteuerung für jede
Anfrage einzeln 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 dafür die MediaSessionService-Schnittstelle.
MediaSessionService implementieren
Erstellen Sie eine Klasse, die MediaSessionService erweitert, und instanziieren Sie Ihre
MediaSession in der onCreate()-Methode des Lebenszyklus.
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();
}
}
Deklarieren Sie in Ihrem Manifest Ihre Service Klasse mit einem MediaSessionService
Intent-Filter 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 UI Ihres Players befindet, können Sie sie mit einem MediaController verknüpfen. Erstellen Sie in der onStart()-Methode 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. Rufen Sie dazu in der onStop() Methode des Lebenszyklus einer Activity die Methode
MediaController.releaseFuture() auf.
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 mit
DefaultMediaNotificationProvider.Builder einen MediaNotification.Provider oder erstellen Sie eine benutzerdefinierte
Implementierung der Provider-Schnittstelle. Fügen Sie Ihrer
MediaSession mit setMediaNotificationProvider einen Provider 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 ein
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 Inhalte durchsuchen kann, die von Ihrem Bibliotheksdienst angeboten werden.
Ä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 MediaItem als Stamm bereitstellen. Jedes MediaItem im Baum kann eine beliebige Anzahl von untergeordneten 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 einem Client zurückgeben, der nach einer Liste empfohlener Medienelemente sucht, möglicherweise nur das Stamm-MediaItem und eine einzelne Ebene untergeordneter MediaItem-Knoten. Der Baum, den Sie einer anderen 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(), wenn ein Client das Stamm-MediaItemeines Inhaltsbaums anfordertonGetChildren(), wenn ein Client die untergeordneten Elemente einesMediaItemim Inhaltsbaum anfordertonGetSearchResult(), wenn ein Client Suchergebnisse aus dem Inhaltsbaum für eine bestimmte Anfrage anfordert
Relevante Callback-Methoden enthalten ein LibraryParams-Objekt mit
zusätzlichen Signalen zum Typ des Inhaltsbaums, an dem eine Client-App
interessiert ist.