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 konsistent 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 clientseitige und serverseitige 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 Modulen „ExoPlayer“, „UI“ und „Common“ von Jetpack Media3 hinzu:
Kotlin
implementation("androidx.media3:media3-exoplayer:1.11.0")
implementation("androidx.media3:media3-ui:1.11.0")
implementation("androidx.media3:media3-common:1.11.0")
Groovy
implementation "androidx.media3:media3-exoplayer:1.11.0"
implementation "androidx.media3:media3-ui:1.11.0"
implementation "androidx.media3:media3-common:1.11.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.11.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 Möglichkeit, eine ExoPlayer-Instanz zu erstellen, 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 mit Methoden wie
setMediaItem() und addMediaItem() Medienelemente zur Wiedergabe 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 das, dass Sie den Player in der Lebenszyklusmethode onStart() auf API-Ebene 24 und höher oder in der Lebenszyklusmethode onResume() 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 Lebenszyklusmethoden 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()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() 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 Lebenszyklusmethode onStop() auf API-Ebene 24 und höher oder in der Methode onPause() 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 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 System-Medien steuerung 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:
Kotlin
implementation("androidx.media3:media3-session:1.11.0")
Groovy
implementation "androidx.media3:media3-session:1.11.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. 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 herstellt, wird die onConnect()
Methode aufgerufen. Mit 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 Playlist verarbeiten. 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 Schnittstelle MediaSessionService.
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();
}
}
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 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 in der onStop() Lebenszyklusmethode einer Activity nicht mehr
benötigt wird. Rufen Sie dazu
MediaController.releaseFuture() auf.
Benachrichtigung veröffentlichen
Dienste im Vordergrund müssen während der Aktivität eine Benachrichtigung veröffentlichen. A
MediaSessionService erstellt automatisch eine MediaStyle Benachrichtigung
für Sie in Form einer MediaNotification. Wenn Sie eine benutzerdefinierte
Benachrichtigung bereitstellen möchten, erstellen Sie einen MediaNotification.Provider mit
DefaultMediaNotificationProvider.Builder oder indem Sie eine benutzerdefinierte
Implementierung der Provider-Schnittstelle erstellen. Fügen Sie Ihren Provider zu Ihrem
MediaSession mit setMediaNotificationProvider hinzu.
Inhaltsbibliothek bewerben
Ein MediaLibraryService baut auf einem MediaSessionService auf, indem er Client
Apps das Durchsuchen der von Ihrer App bereitgestellten Medieninhalte ermöglicht. Client-Apps implementieren einen
MediaBrowser, um mit Ihrem MediaLibraryService zu interagieren.
Die Implementierung eines MediaLibraryService ähnelt der Implementierung eines
MediaSessionService. Mit dem Unterschied, 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. Der Baum, den Sie beispielsweise an einen Client zurückgeben, der nach einer Liste empfohlener Medienelemente sucht, enthält 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 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 ein Client
interessiert ist.