Mediensitzungen bieten eine universelle Möglichkeit, mit einem Audio- oder Videoplayer zu interagieren. In Media3 ist der Standardplayer die Klasse ExoPlayer
, die die Schnittstelle Player
implementiert. Durch die Verbindung der Mediensitzung mit dem Player kann eine App die Medienwiedergabe extern bewerben und Wiedergabebefehle von externen Quellen empfangen.
Befehle können von physischen Tasten stammen, z. B. von der Wiedergabetaste auf einem Headset oder einer TV-Fernbedienung. Sie können auch von Client-Apps mit einem Media-Controller stammen, z. B. wenn Google Assistant angewiesen wird, die Wiedergabe zu pausieren. In der Mediensitzung werden diese Befehle an den Player der Media-App delegiert.
Wann sollte eine Mediensitzung verwendet werden?
Wenn Sie MediaSession
implementieren, können Nutzer die Wiedergabe steuern:
- Über ihre Kopfhörer. Oft gibt es Tasten oder Touch-Interaktionen, die Nutzer auf ihren Kopfhörern ausführen können, um Medien wiederzugeben oder zu pausieren oder zum nächsten oder vorherigen Titel zu wechseln.
- Mit Google Assistant sprechen Ein häufiges Muster ist, „OK Google, pausiere“ zu sagen, um die Wiedergabe von Medien zu pausieren, die gerade auf dem Gerät wiedergegeben werden.
- Über ihre Wear OS-Smartwatch. So können Nutzer während der Wiedergabe auf dem Smartphone einfacher auf die gängigsten Wiedergabesteuerelemente zugreifen.
- Über die Mediensteuerung. In diesem Karussell werden Steuerelemente für jede laufende Mediensitzung angezeigt.
- Auf TV Ermöglicht Aktionen mit physischen Wiedergabetasten, die Steuerung der Plattformwiedergabe und die Energieverwaltung (z. B. wenn der Fernseher, die Soundbar oder der A/V‑Receiver ausgeschaltet oder der Eingang gewechselt wird, sollte die Wiedergabe in der App beendet werden).
- Über die Android Auto-Mediensteuerung. So kann die Wiedergabe während der Fahrt sicher gesteuert werden.
- Und alle anderen externen Prozesse, die die Wiedergabe beeinflussen müssen.
Das ist für viele Anwendungsfälle ideal. Insbesondere sollten Sie MediaSession
in folgenden Fällen in Betracht ziehen:
- Du streamst Videoinhalte im Langformat, z. B. Filme oder Live-TV.
- Du streamst Audioinhalte im Langformat, z. B. Podcasts oder Musik-Playlists.
- Sie entwickeln eine TV-App.
Allerdings sind nicht alle Anwendungsfälle für die MediaSession
geeignet. Möglicherweise möchten Sie nur die Player
in den folgenden Fällen verwenden:
- Sie zeigen Kurzinhalte, für die keine externe Steuerung oder Hintergrundwiedergabe erforderlich ist.
- Es gibt kein einzelnes aktives Video, z. B. wenn der Nutzer durch eine Liste scrollt und mehrere Videos gleichzeitig auf dem Bildschirm angezeigt werden.
- Sie spielen ein einmaliges Einführungs- oder Erklärvideo ab, das sich der Nutzer aktiv ansehen soll, ohne dass externe Wiedergabesteuerelemente erforderlich sind.
- Ihre Inhalte sind datenschutzrelevant und Sie möchten nicht, dass externe Prozesse auf die Media-Metadaten zugreifen (z. B. im Inkognitomodus eines Browsers).
Wenn Ihr Anwendungsfall nicht zu den oben aufgeführten passt, sollten Sie überlegen, ob Sie damit einverstanden sind, dass die Wiedergabe in Ihrer App fortgesetzt wird, wenn der Nutzer nicht aktiv mit den Inhalten interagiert. Wenn die Antwort „Ja“ lautet, sollten Sie wahrscheinlich MediaSession
auswählen. Wenn die Antwort „Nein“ lautet, sollten Sie wahrscheinlich stattdessen Player
verwenden.
Mediensitzung erstellen
Eine Mediensitzung wird zusammen mit dem Player ausgeführt, den sie verwaltet. Sie können eine Mediensitzung mit einem Context
- und einem Player
-Objekt erstellen. Sie sollten eine Media-Sitzung erstellen und initialisieren, wenn sie benötigt wird, z. B. in der onStart()
- oder onResume()
-Lifecycle-Methode von Activity
oder Fragment
oder in der onCreate()
-Methode von Service
, die die Media-Sitzung und den zugehörigen Player enthält.
Um eine Mediensitzung zu erstellen, initialisieren Sie ein Player
und übergeben Sie es so an MediaSession.Builder
:
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();
Automatische Statusverwaltung
Die Media3-Bibliothek aktualisiert die Mediensitzung automatisch anhand des Status des Players. Sie müssen die Zuordnung von Spieler zu Sitzung also nicht manuell verarbeiten.
Das unterscheidet sich von der Media-Sitzung der Plattform, bei der Sie unabhängig vom Player selbst ein PlaybackState
erstellen und verwalten mussten, um beispielsweise Fehler anzugeben.
Eindeutige Sitzungs-ID
Standardmäßig erstellt MediaSession.Builder
eine Sitzung mit einem leeren String als Sitzungs-ID. Das ist ausreichend, wenn eine App nur eine einzelne Sitzungsinstanz erstellen soll. Das ist der häufigste Fall.
Wenn eine App mehrere Sitzungsinstanzen gleichzeitig verwalten möchte, muss sie dafür sorgen, dass die Sitzungs-ID jeder Sitzung eindeutig ist. Die Sitzungs-ID kann beim Erstellen der Sitzung mit MediaSession.Builder.setId(String id)
festgelegt werden.
Wenn IllegalStateException
Ihre App mit der Fehlermeldung IllegalStateException: Session ID must be unique. ID=
zum Absturz bringt, wurde wahrscheinlich eine Sitzung unerwartet erstellt, bevor eine zuvor erstellte Instanz mit derselben ID freigegeben wurde. Um zu verhindern, dass Sitzungen durch einen Programmierfehler offengelegt werden, werden solche Fälle erkannt und durch Auslösen einer Ausnahme gemeldet.
Anderen Kunden die Kontrolle überlassen
Die Mediensitzung ist der Schlüssel zur Steuerung der Wiedergabe. So können Sie Befehle von externen Quellen an den Player weiterleiten, der Ihre Medien wiedergibt. Dabei kann es sich um physische Tasten wie die Wiedergabetaste auf einem Headset oder einer TV-Fernbedienung oder um indirekte Befehle wie „Pause“ für Google Assistant handeln. Möglicherweise möchten Sie auch Zugriff auf das Android-System gewähren, um Benachrichtigungen und Steuerelemente auf dem Sperrbildschirm zu ermöglichen, oder auf eine Wear OS-Smartwatch, damit Sie die Wiedergabe über das Zifferblatt steuern können. Externe Clients können mit einem Media-Controller Wiedergabebefehle an Ihre Media-App senden. Diese werden von Ihrer Media-Session empfangen, die Befehle letztendlich an den Mediaplayer weiterleitet.

Wenn ein Controller eine Verbindung zu Ihrer Mediensitzung herstellt, wird die Methode onConnect()
aufgerufen. Anhand der bereitgestellten ControllerInfo
können Sie entscheiden, ob Sie die Anfrage annehmen oder ablehnen. Ein Beispiel für das Annehmen einer Verbindungsanfrage finden Sie im Abschnitt Benutzerdefinierte Befehle deklarieren.
Nachdem eine Verbindung hergestellt wurde, kann ein Controller Wiedergabebefehle an die Sitzung senden. Die Sitzung delegiert diese Befehle dann an den Player. Wiedergabe- und Playlist-Befehle, die in der Player
-Schnittstelle definiert sind, werden automatisch von der Sitzung verarbeitet.
Mit anderen Callback-Methoden können Sie beispielsweise Anfragen für benutzerdefinierte Befehle und Änderungen an der Playlist verarbeiten. Diese Callbacks enthalten ebenfalls ein ControllerInfo
-Objekt, sodass Sie die Reaktion auf jede Anfrage controllerbasiert anpassen können.
Playlist bearbeiten
In einer Media-Sitzung kann die Playlist des Players direkt geändert werden, wie im ExoPlayer-Leitfaden für Playlists beschrieben.
Controller können die Playlist auch ändern, wenn entweder COMMAND_SET_MEDIA_ITEM
oder COMMAND_CHANGE_MEDIA_ITEMS
für den Controller verfügbar ist.
Wenn Sie der Playlist neue Elemente hinzufügen, benötigt der Player in der Regel MediaItem
Instanzen mit einem definierten URI, damit sie wiedergegeben werden können. Standardmäßig werden neu hinzugefügte Elemente automatisch an Player-Methoden wie player.addMediaItem
weitergeleitet, wenn sie einen URI haben.
Wenn Sie die dem Player hinzugefügten MediaItem
-Instanzen anpassen möchten, können Sie onAddMediaItems()
überschreiben.
Dieser Schritt ist erforderlich, wenn Sie Controller unterstützen möchten, die Medien ohne definierten URI anfordern. Stattdessen sind im MediaItem
in der Regel eines oder mehrere der folgenden Felder festgelegt, um die angeforderten Media zu beschreiben:
MediaItem.id
: Eine generische ID zur Identifizierung der Media.MediaItem.RequestMetadata.mediaUri
: Ein Anfrage-URI, der ein benutzerdefiniertes Schema verwenden kann und nicht unbedingt direkt vom Player wiedergegeben werden kann.MediaItem.RequestMetadata.searchQuery
: Eine textbasierte Suchanfrage, z. B. von Google Assistant.MediaItem.MediaMetadata
: Strukturierte Metadaten wie „Titel“ oder „Künstler“.
Wenn Sie weitere Anpassungsoptionen für völlig neue Playlists benötigen, können Sie zusätzlich onSetMediaItems()
überschreiben, um das Startelement und die Position in der Playlist zu definieren. So kannst du beispielsweise einen einzelnen angeforderten Titel zu einer ganzen Playlist erweitern und den Player anweisen, mit dem Index des ursprünglich angeforderten Titels zu beginnen. Eine Beispielimplementierung von onSetMediaItems()
mit dieser Funktion finden Sie in der Demo-App für Sitzungen.
Einstellungen für die Schaltfläche „Medien“ verwalten
Jeder Controller, z. B. System-UI, Android Auto oder Wear OS, kann selbst entscheiden, welche Schaltflächen dem Nutzer angezeigt werden. Wenn Sie angeben möchten, welche Wiedergabesteuerelemente dem Nutzer angezeigt werden sollen, können Sie im MediaSession
Einstellungen für Medientasten festlegen. Diese Einstellungen bestehen aus einer geordneten Liste von CommandButton
-Instanzen, die jeweils eine Einstellung für eine Schaltfläche in der Benutzeroberfläche definieren.
Befehlsschaltflächen definieren
CommandButton
-Instanzen werden verwendet, um Einstellungen für Medientasten zu definieren. Jede Schaltfläche definiert drei Aspekte des gewünschten UI-Elements:
- Das Symbol, das die visuelle Darstellung definiert. Das Symbol muss beim Erstellen eines
CommandButton.Builder
auf eine der vordefinierten Konstanten festgelegt werden. Dabei handelt es sich nicht um eine tatsächliche Bitmap- oder Bildressource. Eine generische Konstante hilft Controllern, eine geeignete Ressource für ein einheitliches Erscheinungsbild in der eigenen Benutzeroberfläche auszuwählen. Wenn keine der vordefinierten Symbolkonstanten für Ihren Anwendungsfall geeignet ist, können Sie stattdessensetCustomIconResId
verwenden. - Der Befehl, der die Aktion definiert, die ausgelöst wird, wenn der Nutzer mit der Schaltfläche interagiert. Sie können
setPlayerCommand
für einePlayer.Command
odersetSessionCommand
für eine vordefinierte oder benutzerdefinierteSessionCommand
verwenden. - Der Slot definiert, wo die Schaltfläche in der Controller-Benutzeroberfläche platziert werden soll. Dieses Feld ist optional und wird automatisch anhand von Symbol und Befehl festgelegt. So kann beispielsweise festgelegt werden, dass eine Schaltfläche im Navigationsbereich „Vorwärts“ der Benutzeroberfläche anstelle des Standardbereichs „Überlauf“ angezeigt werden soll.
Kotlin
val button = CommandButton.Builder(CommandButton.ICON_SKIP_FORWARD_15) .setSessionCommand(SessionCommand(CUSTOM_ACTION_ID, Bundle.EMPTY)) .setSlots(CommandButton.SLOT_FORWARD) .build()
Java
CommandButton button = new CommandButton.Builder(CommandButton.ICON_SKIP_FORWARD_15) .setSessionCommand(new SessionCommand(CUSTOM_ACTION_ID, Bundle.EMPTY)) .setSlots(CommandButton.SLOT_FORWARD) .build();
Wenn die Einstellungen für die Media-Schaltfläche aufgelöst werden, wird der folgende Algorithmus angewendet:
- Platzieren Sie für jedes
CommandButton
in den Einstellungen für Media-Schaltflächen die Schaltfläche im ersten verfügbaren und zulässigen Slot. - Wenn einer der zentralen, Vorwärts- und Rückwärts-Slots nicht mit einer Schaltfläche gefüllt ist, fügen Sie Standardschaltflächen für diesen Slot hinzu.
Mit CommandButton.DisplayConstraints
können Sie eine Vorschau davon generieren, wie die Einstellungen für die Media-Schaltfläche je nach Einschränkungen der Benutzeroberfläche aufgelöst werden.
Einstellungen für die Schaltfläche „Medien“ festlegen
Am einfachsten ist es, die Einstellungen für die Media-Schaltfläche beim Erstellen von MediaSession
zu definieren. Alternativ können Sie MediaSession.Callback.onConnect
überschreiben, um die Einstellungen für die Medientaste für jeden verbundenen Controller anzupassen.
Kotlin
val mediaSession = MediaSession.Builder(context, player) .setMediaButtonPreferences(ImmutableList.of(likeButton, favoriteButton)) .build()
Java
MediaSession mediaSession = new MediaSession.Builder(context, player) .setMediaButtonPreferences(ImmutableList.of(likeButton, favoriteButton)) .build();
Einstellungen für die Media-Schaltfläche nach einer Nutzerinteraktion aktualisieren
Nachdem Sie eine Interaktion mit dem Player verarbeitet haben, möchten Sie möglicherweise die in der Controller-Benutzeroberfläche angezeigten Schaltflächen aktualisieren. Ein typisches Beispiel ist eine Umschaltfläche, deren Symbol und Aktion sich ändern, nachdem die mit dieser Schaltfläche verknüpfte Aktion ausgelöst wurde. Wenn du die Einstellungen für die Medientaste aktualisieren möchtest, kannst du MediaSession.setMediaButtonPreferences
verwenden, um die Einstellungen für alle Controller oder einen bestimmten Controller zu aktualisieren:
Kotlin
// Handle "favoritesButton" action, replace by opposite button mediaSession.setMediaButtonPreferences( ImmutableList.of(likeButton, removeFromFavoritesButton))
Java
// Handle "favoritesButton" action, replace by opposite button mediaSession.setMediaButtonPreferences( ImmutableList.of(likeButton, removeFromFavoritesButton));
Benutzerdefinierte Befehle hinzufügen und Standardverhalten anpassen
Die verfügbaren Player-Befehle können durch benutzerdefinierte Befehle erweitert werden. Außerdem ist es möglich, eingehende Player-Befehle und Media-Schaltflächen abzufangen, um das Standardverhalten zu ändern.
Benutzerdefinierte Befehle deklarieren und verarbeiten
Media-Apps können benutzerdefinierte Befehle definieren, die beispielsweise in den Einstellungen für die Media-Schaltfläche verwendet werden können. Sie können beispielsweise Schaltflächen implementieren, mit denen der Nutzer ein Media-Element in einer Liste mit Favoriten speichern kann. Mit MediaController
werden benutzerdefinierte Befehle gesendet und mit MediaSession.Callback
werden sie empfangen.
Wenn Sie benutzerdefinierte Befehle definieren möchten, müssen Sie MediaSession.Callback.onConnect()
überschreiben, um die verfügbaren benutzerdefinierten Befehle für jeden verbundenen Controller festzulegen.
Kotlin
private class CustomMediaSessionCallback: MediaSession.Callback { // Configure commands available to the controller in onConnect() override fun onConnect( session: MediaSession, controller: MediaSession.ControllerInfo ): MediaSession.ConnectionResult { val sessionCommands = ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon() .add(SessionCommand(SAVE_TO_FAVORITES, Bundle.EMPTY)) .build() return AcceptedResultBuilder(session) .setAvailableSessionCommands(sessionCommands) .build() } }
Java
class CustomMediaSessionCallback implements MediaSession.Callback { // Configure commands available to the controller in onConnect() @Override public ConnectionResult onConnect( MediaSession session, ControllerInfo controller) { SessionCommands sessionCommands = ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon() .add(new SessionCommand(SAVE_TO_FAVORITES, new Bundle())) .build(); return new AcceptedResultBuilder(session) .setAvailableSessionCommands(sessionCommands) .build(); } }
Wenn Sie benutzerdefinierte Befehlsanfragen von einem MediaController
erhalten möchten, überschreiben Sie die Methode onCustomCommand()
im Callback
.
Kotlin
private class CustomMediaSessionCallback: MediaSession.Callback { ... override fun onCustomCommand( session: MediaSession, controller: MediaSession.ControllerInfo, customCommand: SessionCommand, args: Bundle ): ListenableFuture<SessionResult> { if (customCommand.customAction == SAVE_TO_FAVORITES) { // Do custom logic here saveToFavorites(session.player.currentMediaItem) return Futures.immediateFuture( SessionResult(SessionResult.RESULT_SUCCESS) ) } ... } }
Java
class CustomMediaSessionCallback implements MediaSession.Callback { ... @Override public ListenableFuture<SessionResult> onCustomCommand( MediaSession session, ControllerInfo controller, SessionCommand customCommand, Bundle args ) { if(customCommand.customAction.equals(SAVE_TO_FAVORITES)) { // Do custom logic here saveToFavorites(session.getPlayer().getCurrentMediaItem()); return Futures.immediateFuture( new SessionResult(SessionResult.RESULT_SUCCESS) ); } ... } }
Sie können nachvollziehen, welcher Media-Controller eine Anfrage stellt, indem Sie die packageName
-Property des MediaSession.ControllerInfo
-Objekts verwenden, das an Callback
-Methoden übergeben wird. So können Sie das Verhalten Ihrer App anpassen, wenn ein bestimmter Befehl vom System, von Ihrer eigenen App oder von anderen Client-Apps stammt.
Standardmäßige Playerbefehle anpassen
Alle Standardbefehle und die Statusverwaltung werden an die Player
auf der MediaSession
delegiert. Wenn Sie das Verhalten eines Befehls anpassen möchten, der in der Player
-Schnittstelle definiert ist, z. B. play()
oder seekToNext()
, umschließen Sie Ihre Player
mit einem ForwardingSimpleBasePlayer
, bevor Sie sie an MediaSession
übergeben:
Kotlin
val player = (logic to build a Player instance) val forwardingPlayer = object : ForwardingSimpleBasePlayer(player) { // Customizations } val mediaSession = MediaSession.Builder(context, forwardingPlayer).build()
Java
ExoPlayer player = (logic to build a Player instance) ForwardingSimpleBasePlayer forwardingPlayer = new ForwardingSimpleBasePlayer(player) { // Customizations }; MediaSession mediaSession = new MediaSession.Builder(context, forwardingPlayer).build();
Weitere Informationen zu ForwardingSimpleBasePlayer
finden Sie im ExoPlayer-Leitfaden unter Anpassung.
Anfordernden Controller eines Player-Befehls ermitteln
Wenn ein Aufruf einer Player
-Methode von einem MediaController
stammt, können Sie die Quelle mit MediaSession.controllerForCurrentRequest
identifizieren und die ControllerInfo
für die aktuelle Anfrage abrufen:
Kotlin
class CallerAwarePlayer(player: Player) : ForwardingSimpleBasePlayer(player) { override fun handleSeek( mediaItemIndex: Int, positionMs: Long, seekCommand: Int, ): ListenableFuture<*> { Log.d( "caller", "seek operation from package ${session.controllerForCurrentRequest?.packageName}", ) return super.handleSeek(mediaItemIndex, positionMs, seekCommand) } }
Java
public class CallerAwarePlayer extends ForwardingSimpleBasePlayer { public CallerAwarePlayer(Player player) { super(player); } @Override protected ListenableFuture<?> handleSeek( int mediaItemIndex, long positionMs, int seekCommand) { Log.d( "caller", "seek operation from package: " + session.getControllerForCurrentRequest().getPackageName()); return super.handleSeek(mediaItemIndex, positionMs, seekCommand); } }
Umgang mit Medientasten anpassen
Media-Schaltflächen sind Hardware-Schaltflächen auf Android-Geräten und anderen Peripheriegeräten, z. B. die Wiedergabe-/Pausetaste auf einem Bluetooth-Headset. Media3 verarbeitet Media-Schaltflächenereignisse für dich, wenn sie in der Sitzung eintreffen, und ruft die entsprechende Player
-Methode für den Sitzungsplayer auf.
Es wird empfohlen, alle eingehenden Media-Schaltflächenereignisse in der entsprechenden Player
-Methode zu verarbeiten. Bei komplexeren Anwendungsfällen können die Ereignisse der Medientaste in MediaSession.Callback.onMediaButtonEvent(Intent)
abgefangen werden.
Fehlerbehandlung und ‑berichte
Es gibt zwei Arten von Fehlern, die von einer Sitzung ausgegeben und an Controller gemeldet werden. Schwerwiegende Fehler weisen auf einen technischen Wiedergabefehler des Sitzungsplayers hin, der die Wiedergabe unterbricht. Schwerwiegende Fehler werden dem Controller automatisch gemeldet, wenn sie auftreten. Nicht schwerwiegende Fehler sind nicht technischer Natur oder Richtlinienfehler, die die Wiedergabe nicht unterbrechen und manuell von der Anwendung an Controller gesendet werden.
Schwerwiegende Wiedergabefehler
Ein schwerwiegender Wiedergabefehler wird vom Player an die Sitzung und dann an die Controller gemeldet, um Player.Listener.onPlayerError(PlaybackException)
und Player.Listener.onPlayerErrorChanged(@Nullable PlaybackException)
aufzurufen.
In diesem Fall wird der Wiedergabestatus in STATE_IDLE
geändert und MediaController.getPlaybackError()
gibt den PlaybackException
zurück, der die Änderung verursacht hat. Ein Controller kann PlayerException.errorCode
prüfen, um Informationen zum Grund für den Fehler zu erhalten.
Zur Interoperabilität wird ein schwerwiegender Fehler in der Plattformsitzung repliziert, indem der Status in STATE_ERROR
geändert und der Fehlercode und die Meldung gemäß PlaybackException
festgelegt werden.
Schwerwiegende Fehler anpassen
Um dem Nutzer lokalisierte und aussagekräftige Informationen zu geben, können der Fehlercode, die Fehlermeldung und die zusätzlichen Fehlerinformationen eines schwerwiegenden Wiedergabefehlers mithilfe von ForwardingPlayer
beim Erstellen der Sitzung angepasst werden:
Kotlin
val forwardingPlayer = ErrorForwardingPlayer(player) val session = MediaSession.Builder(context, forwardingPlayer).build()
Java
Player forwardingPlayer = new ErrorForwardingPlayer(player); MediaSession session = new MediaSession.Builder(context, forwardingPlayer).build();
Der Weiterleitungsplayer kann ForwardingSimpleBasePlayer
verwenden, um den Fehler abzufangen und den Fehlercode, die Meldung oder die Extras anzupassen. Auf dieselbe Weise können Sie auch neue Fehler generieren, die im ursprünglichen Player nicht vorhanden sind:
Kotlin
class ErrorForwardingPlayer (private val context: Context, player: Player) : ForwardingSimpleBasePlayer(player) { override fun getState(): State { var state = super.getState() if (state.playerError != null) { state = state.buildUpon() .setPlayerError(customizePlaybackException(state.playerError!!)) .build() } return state } fun customizePlaybackException(error: PlaybackException): PlaybackException { val buttonLabel: String val errorMessage: String when (error.errorCode) { PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW -> { buttonLabel = context.getString(R.string.err_button_label_restart_stream) errorMessage = context.getString(R.string.err_msg_behind_live_window) } else -> { buttonLabel = context.getString(R.string.err_button_label_ok) errorMessage = context.getString(R.string.err_message_default) } } val extras = Bundle() extras.putString("button_label", buttonLabel) return PlaybackException(errorMessage, error.cause, error.errorCode, extras) } }
Java
class ErrorForwardingPlayer extends ForwardingSimpleBasePlayer { private final Context context; public ErrorForwardingPlayer(Context context, Player player) { super(player); this.context = context; } @Override protected State getState() { State state = super.getState(); if (state.playerError != null) { state = state.buildUpon() .setPlayerError(customizePlaybackException(state.playerError)) .build(); } return state; } private PlaybackException customizePlaybackException(PlaybackException error) { String buttonLabel; String errorMessage; switch (error.errorCode) { case PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW: buttonLabel = context.getString(R.string.err_button_label_restart_stream); errorMessage = context.getString(R.string.err_msg_behind_live_window); break; default: buttonLabel = context.getString(R.string.err_button_label_ok); errorMessage = context.getString(R.string.err_message_default); break; } Bundle extras = new Bundle(); extras.putString("button_label", buttonLabel); return new PlaybackException(errorMessage, error.getCause(), error.errorCode, extras); } }
Nicht schwerwiegende Fehler
Nicht schwerwiegende Fehler, die nicht auf einer technischen Ausnahme beruhen, können von einer App an alle oder an einen bestimmten Controller gesendet werden:
Kotlin
val sessionError = SessionError( SessionError.ERROR_SESSION_AUTHENTICATION_EXPIRED, context.getString(R.string.error_message_authentication_expired), ) // Option 1: Sending a nonfatal error to all controllers. mediaSession.sendError(sessionError) // Option 2: Sending a nonfatal error to the media notification controller only // to set the error code and error message in the playback state of the platform // media session. mediaSession.mediaNotificationControllerInfo?.let { mediaSession.sendError(it, sessionError) }
Java
SessionError sessionError = new SessionError( SessionError.ERROR_SESSION_AUTHENTICATION_EXPIRED, context.getString(R.string.error_message_authentication_expired)); // Option 1: Sending a nonfatal error to all controllers. mediaSession.sendError(sessionError); // Option 2: Sending a nonfatal error to the media notification controller only // to set the error code and error message in the playback state of the platform // media session. ControllerInfo mediaNotificationControllerInfo = mediaSession.getMediaNotificationControllerInfo(); if (mediaNotificationControllerInfo != null) { mediaSession.sendError(mediaNotificationControllerInfo, sessionError); }
Wenn ein nicht schwerwiegender Fehler an den Media Notification Controller gesendet wird, werden der Fehlercode und die Fehlermeldung in die Media-Sitzung der Plattform repliziert, während PlaybackState.state
nicht in STATE_ERROR
geändert wird.
Nicht schwerwiegende Fehler erhalten
Ein MediaController
erhält einen nicht schwerwiegenden Fehler durch die Implementierung von MediaController.Listener.onError
:
Kotlin
val future = MediaController.Builder(context, sessionToken) .setListener(object : MediaController.Listener { override fun onError(controller: MediaController, sessionError: SessionError) { // Handle nonfatal error. } }) .buildAsync()
Java
MediaController.Builder future = new MediaController.Builder(context, sessionToken) .setListener( new MediaController.Listener() { @Override public void onError(MediaController controller, SessionError sessionError) { // Handle nonfatal error. } });