Media Sessions 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 Media Session 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 an einem Headset oder auf 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 Media Session werden diese Befehle an den Player der Medien-App delegiert.
Wann sollte eine Media Session verwendet werden?
Wenn Sie MediaSession
implementieren, können Nutzer die Wiedergabe auf die folgenden Arten steuern:
- Über ihre Kopfhörer: Bei vielen Kopfhörern können Tasten oder Touch-Interaktionen genutzt werden, um die Medienwiedergabe zu starten oder zu pausieren oder um zum nächsten bzw. zum vorherigen Titel zu springen.
- Per Sprachbefehl an Google Assistant: Ein häufiges Muster ist, „OK Google, pausiere“ zu sagen, um die Wiedergabe von Medien zu pausieren.
- Ü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 Media Session angezeigt.
- Auf ihrem Fernseher: Ermöglicht Aktionen mit physischen Wiedergabetasten, die Plattform-Player-Steuerung und die Energieverwaltung (z. B. wenn sich der Fernseher, die Soundbar oder der A/V‑Receiver ausschaltet oder der Eingang gewechselt wird, sollte die Wiedergabe in der App beendet werden).
- Über die Android Auto-Mediensteuerung. Das ermöglicht eine sichere Wiedergabesteuerung während der Fahrt.
- Und alle anderen externen Prozesse, die Einfluss auf die Wiedergabe benötigen.
Das ist für viele Anwendungsfälle ideal. Insbesondere sollten Sie MediaSession
in folgenden Fällen in Betracht ziehen:
- Sie streamen Videoinhalte im Langformat, z. B. Filme oder Live-TV.
- Sie streamen Audioinhalte im Langformat, z. B. Podcasts oder Musik-Playlists.
- Sie entwickeln eine TV-App.
Allerdings passt MediaSession
nicht zu allen Anwendungsfällen. In den folgenden Fällen empfiehlt es sich, nur Player
zu verwenden:
- Sie zeigen Inhalte im Kurzformat, für die keine externe Kontrollgruppe 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 Medien-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. Lautet sie „Nein“, ist wahrscheinlich Player
die bessere Wahl.
Media Session erstellen
Eine Media Session wird zusammen mit dem Player ausgeführt, den sie verwaltet. Sie können eine Media Session mit einem Context
- und einem Player
-Objekt erstellen. Sie sollten eine Media Session 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 Session und den zugehörigen Player enthält.
Um eine Media Session zu erstellen, initialisieren Sie ein Player
-Objekt und übergeben Sie es wie folgt 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 Media Session automatisch anhand des Status des Players. Sie müssen also keine manuelle Zuordnung von Player und Session vornehmen.
Das unterscheidet sich von der Plattform-Media-Session, bei der Sie unabhängig vom Player selbst ein PlaybackState
-Objekt erstellen und verwalten mussten, um beispielsweise Fehler anzugeben.
Eindeutige Session-ID
Standardmäßig erstellt MediaSession.Builder
eine Session mit einem leeren String als Session-ID. Das ist ausreichend, wenn eine App nur eine einzelne Session-Instanz erstellen soll. Das ist der häufigste Fall.
Wenn eine App mehrere Session-Instanzen gleichzeitig verwalten möchte, muss sie dafür sorgen, dass die Session-ID jeder Session eindeutig ist. Die Session-ID kann beim Erstellen der Session 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 Session unerwartet erstellt, bevor eine zuvor erstellte Instanz mit derselben ID freigegeben wurde. Um zu verhindern, dass Sessions durch einen Programmierfehler offengelegt werden, werden solche Fälle erkannt und durch Auslösen einer Ausnahme gemeldet.
Anderen Clients die Kontrolle überlassen
Die Media Session ist der Schlüssel zur Steuerung der Wiedergabe. Mit ihrer Hilfe können Sie Befehle von externen Quellen an den Player weiterleiten, der Ihre Medien wiedergibt. Bei diesen Quellen kann es sich um physische Tasten wie die Wiedergabetaste an einem Headset oder auf einer TV-Fernbedienung oder um indirekte Befehle wie der an Google Assistant gerichtete Sprachbefehl „Pausieren“ 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 von dort aus steuern können. Externe Clients können einen Media Controller verwenden, um Wiedergabebefehle an Ihre Medien-App zu senden. Diese werden von Ihrer Media Session empfangen, die Befehle letztendlich an den Mediaplayer weiterleitet.

Wenn ein Controller eine Verbindung zu Ihrer Media Session 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 und verarbeiten.
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 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 Session 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 Medien zu beschreiben:
MediaItem.id
: Eine generische ID zur Identifizierung der Medien.MediaItem.RequestMetadata.mediaUri
: Ein Anfrage-URI, der ein benutzerdefiniertes Schema verwenden kann und nicht unbedingt direkt vom Player wiedergegeben werden können muss.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 können Sie 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 Session-Demo-App.
Einstellungen für Medientasten verwalten
Jeder Controller, z. B. System-UI, Android Auto oder Wear OS, kann selbst entscheiden, welche Schaltflächen zur Wiedergabesteuerung („Medientasten“) dem Nutzer angezeigt werden. Zur Festlegung der anzuzeigenden Wiedergabesteuerelemente stehen Ihnen die MediaSession
Einstellungen für Medientasten zur Verfügung. Diese Einstellungen bestehen aus einer geordneten Liste von CommandButton
-Instanzen, die jeweils eine Einstellung für eine Schaltfläche (Medientaste) in der Benutzeroberfläche definieren.
Befehlsschaltflächen definieren
Zum Definieren der Einstellungen für Medientasten werden CommandButton
-Instanzen verwendet. In jeder Definition werden drei Aspekte des gewünschten UI-Elements festgelegt:
- Das Symbol, das die visuelle Darstellung definiert: Das Symbol muss beim Erstellen einer
CommandButton.Builder
-Klasse auf eine der vordefinierten Konstanten festgelegt werden. Zu beachten ist, dass es sich nicht um eine tatsächliche Bitmap- oder Bildressource handelt. 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. - Den Befehl, der die Aktion definiert, die bei einer Nutzerinteraktion mit der Schaltfläche ausgelöst wird: Für einen Befehl des Typs
Player.Command
können SiesetPlayerCommand
und für einen vordefinierten oder benutzerdefinierten Befehl des TypsSessionCommand
können SiesetSessionCommand
verwenden. - Den Slot, der definiert, wo in der Controller-Benutzeroberfläche die Schaltflä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 nicht im standardmäßigen „Überlauf“-Bereich der Benutzeroberfläche, sondern im „Vorwärts“-Navigationsbereich 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();
Bei der Anwendung der Einstellungen für Medientasten kommt der folgende Algorithmus zum Einsatz:
- Platziere für jeden Befehl des Typs
CommandButton
in den Einstellungen für Medientasten 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üge Standardschaltflächen für diesen Slot hinzu.
Mit CommandButton.DisplayConstraints
können Sie eine Vorschau davon generieren, wie die Einstellungen für Medientasten je nach Einschränkungen der Benutzeroberfläche angewendet werden.
Einstellungen für Medientasten festlegen
Am einfachsten ist es, die Einstellungen für Medientasten beim Erstellen von MediaSession
zu definieren. Alternativ können Sie MediaSession.Callback.onConnect
überschreiben, um die Einstellungen für Medientasten 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 Medientasten 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 Ein/Aus-Schaltfläche, deren Symbol und Aktion sich ändern, nachdem die mit dieser Schaltfläche verknüpfte Aktion ausgelöst wurde. Wenn Sie die Einstellungen für Medientasten aktualisieren möchten, können Sie 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 Medientasten abzufangen, um das Standardverhalten zu ändern.
Benutzerdefinierte Befehle deklarieren und verarbeiten
Medienanwendungen können benutzerdefinierte Befehle definieren, die beispielsweise in den Einstellungen für Medientasten verwendet werden können. Sie können beispielsweise Schaltflächen implementieren, mit denen der Nutzer eine Mediendatei in einer Favoritenliste speichern kann. MediaController
sendet benutzerdefinierte Befehle und MediaSession.Callback
empfängt sie.
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 es möglich sein soll, von einem MediaController
Anfragen zu benutzerdefinierten Befehlen zu empfangen, überschreiben Sie die Methode onCustomCommand()
im Objekt 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 daran anpassen, ob 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 den Player
auf der MediaSession
weitergeleitet. Wenn Sie das Verhalten eines Befehls anpassen möchten, der in der Player
-Schnittstelle definiert ist, z. B. play()
oder seekToNext()
, verpacken Sie Ihren Player
in einen ForwardingSimpleBasePlayer
, bevor Sie ihn 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 mit MediaSession.controllerForCurrentRequest
dessen Quelle 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
Medientasten sind Hardwaretasten an Android-Geräten und anderen Peripheriegeräten, z. B. die Wiedergabe-/Pausetaste auf einem Bluetooth-Headset. Media3 übernimmt die Verarbeitung von in der Session eintreffenden Medientastenereignissen für Sie und ruft die entsprechende Player
-Methode für den Session-Player auf.
Es wird empfohlen, alle eingehenden Medientastenereignisse in der entsprechenden Player
-Methode zu verarbeiten. Bei komplexeren Anwendungsfällen können die Medientastenereignisse in MediaSession.Callback.onMediaButtonEvent(Intent)
abgefangen werden.
Fehlerbehandlung und ‑berichte
Es gibt zwei Arten von Fehlern, die von einer Session ausgegeben und an Controller gemeldet werden. Schwerwiegende Fehler weisen auf einen technischen Wiedergabefehler des Session-Players 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 Session und dann an die Controller gemeldet, um die Fehler Player.Listener.onPlayerError(PlaybackException)
und Player.Listener.onPlayerErrorChanged(@Nullable PlaybackException)
zu melden.
In diesem Fall wird der Wiedergabestatus in STATE_IDLE
geändert und MediaController.getPlaybackError()
gibt den Fehler PlaybackException
zurück, die die Änderung verursacht hat. Ein Controller kann PlayerException.errorCode
prüfen, um Informationen zum Grund für den Fehler zu erhalten.
Benutzerdefinierten Playerfehler festlegen
Zusätzlich zu schwerwiegenden Fehlern, die vom Player gemeldet werden, kann eine Anwendung mit MediaSession.setPlaybackException(PlaybackException)
einen benutzerdefinierten PlaybackException
-Fehler auf MediaSession-Ebene festlegen. Dadurch kann die Anwendung einen Fehlerstatus an verbundene Controller signalisieren. Die Ausnahme kann für alle verbundenen Controller oder für eine bestimmte ControllerInfo
festgelegt werden.
Wenn eine App mit dieser API eine PlaybackException
festlegt, passiert Folgendes:
Verbundene
MediaController
-Instanzen werden benachrichtigt. Die CallbacksListener.onPlayerError(PlaybackException)
undListener.onPlayerErrorChanged(@Nullable PlaybackException)
auf dem Controller werden mit der bereitgestellten Ausnahme aufgerufen.Die
MediaController.getPlayerError()
-Methode gibt die von der Anwendung festgelegtePlaybackException
zurück.Der Wiedergabestatus für die betroffenen Controller ändert sich in
Player.STATE_IDLE
.Verfügbare Befehle werden entfernt und nur Lesebefehle wie
COMMAND_GET_TIMELINE
bleiben erhalten, sofern bereits entsprechende Rechte erteilt wurden. So wird beispielsweise der Status vonTimeline
auf den Status eingefroren, der galt, als die Ausnahme auf den Controller angewendet wurde. Befehle, mit denen versucht wird, den Status des Players zu ändern, z. B.COMMAND_PLAY
, werden entfernt, bis die Wiedergabeausnahme für den jeweiligen Controller von der App entfernt wird.
Wenn eine App eine zuvor festgelegte benutzerdefinierte PlaybackException
löschen und die normale Berichterstellung zum Playerstatus wiederherstellen möchte, kann sie MediaSession.setPlaybackException(/* playbackException= */ null)
oder MediaSession.setPlaybackException(ControllerInfo,
/* playbackException= */ null)
aufrufen.
Meldungen über schwerwiegende Fehler anpassen
Um dem Nutzer lokalisierte und aussagekräftige Informationen zu geben, können Sie den Fehlercode, die Fehlermeldung und die zusätzlichen Fehlerinformationen eines vom eigentlichen Player ausgegebenen schwerwiegenden Wiedergabefehlers anpassen. Verwenden Sie dazu beim Erstellen der Session einen ForwardingPlayer
-Adapter verwenden:
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 zusätzlichen Fehlerinformationen 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 Plattform-Media-Session repliziert, während PlaybackState.state
nicht in STATE_ERROR
geändert wird.
Nicht schwerwiegende Fehler erhalten
Ein MediaController
erhält durch die Implementierung von MediaController.Listener.onError
einen nicht schwerwiegenden Fehler:
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. } });