Mediensitzungen bieten eine universelle Möglichkeit, mit einem Audio oder Video zu interagieren.
Player. In Media3 ist der Standardplayer die Klasse ExoPlayer
, mit der
der Player
-Schnittstelle. Wenn die Mediensitzung mit dem Player verbunden wird, kann eine App
um die Medienwiedergabe extern zu bewerben und Befehle zur Wiedergabe von
externen Quellen.
Befehle können sich auf physische Schaltflächen wie die Wiedergabeschaltfläche auf einem Headset oder der Fernbedienung des Fernsehers. Sie können auch von Client-Apps stammen, Mediencontroller (z. B. zum Pausieren) mit Google Assistant. Die Medien -Sitzung delegiert diese Befehle an den Player der Medien-App.
Wann sollte eine Mediensitzung ausgewählt werden?
Wenn du MediaSession
implementierst, erlaubst du Nutzern, die Wiedergabe zu steuern:
- Über ihre Kopfhörer Oft werden Schaltflächen oder Berührungen können Nutzer Medien über ihre Kopfhörer abspielen oder pausieren oder zum nächsten oder dem vorherigen Titel.
- Durch Sprechen mit Google Assistant Ein gängiges Muster ist: "OK Google, Pause", um alle Medien zu pausieren, die gerade auf dem Gerät abgespielt werden.
- Über die Wear OS-Smartwatch. Dies ermöglicht einen einfachen Zugriff auf die wichtigsten die gängigen Wiedergabesteuerungen bei der Wiedergabe auf dem Smartphone.
- Über die Mediensteuerung Dieses Karussell zeigt Steuerelemente für jede die laufende Mediensitzung.
- Auf Fernsehern. Ermöglicht Aktionen mit physischen Wiedergabeschaltflächen und der Plattformwiedergabe Steuerung und Energieverwaltung (z. B. wenn der Fernseher, die Soundbar oder der AV-Receiver ausgeschaltet oder der Eingang gewechselt wird, sollte die Wiedergabe in der App beendet werden.
- Und alle anderen externen Prozesse, die die Wiedergabe beeinflussen müssen.
Dies eignet sich für viele Anwendungsfälle. Sie sollten sich insbesondere
Verwendung von MediaSession
in folgenden Fällen:
- Sie streamen Videos im Langformat, z. B. Filme oder Live-TV.
- Sie streamen Audioinhalte im Langformat wie Podcasts oder Musik. Playlists.
- Sie erstellen eine TV-App.
Allerdings eignen sich nicht alle Anwendungsfälle für MediaSession
. Vielleicht möchten Sie
Verwenden Sie in den folgenden Fällen nur das Player
:
- Sie präsentieren Kurzinhalte mit Nutzerinteraktionen und -interaktionen. ist entscheidend.
- Es ist kein einzelnes aktives Video vorhanden, z. B. wenn der Nutzer durch eine Liste scrollt. und mehrere Videos gleichzeitig angezeigt werden.
- Sie spielen ein einmaliges Einführungs- oder Erklärungsvideo ab, das dass sich die Nutzer aktiv Videos ansehen.
- Bei deinen Inhalten wird der Datenschutz berücksichtigt und du möchtest nicht, dass externe Prozesse Auf Medienmetadaten zugreifen (z. B. Inkognitomodus in einem Browser)
Wenn Ihr Anwendungsfall keinem der oben genannten Punkte entspricht, überlegen Sie,
Die Wiedergabe wird fortgesetzt, wenn der Nutzer nicht aktiv mit der App interagiert.
mit den Inhalten. Wenn die Antwort „Ja“ lautet, wählen Sie
MediaSession
Wenn die Antwort „nein“ lautet, sollten Sie Player
verwenden.
.
Mediensitzung erstellen
Neben dem von ihm verwalteten Player befindet sich eine Mediensitzung. Sie können eine
Mediensitzung mit einem Context
- und einem Player
-Objekt. Sie sollten
eine Mediensitzung bei Bedarf initialisieren, z. B. die onStart()
oder
onResume()
-Lebenszyklusmethode von Activity
oder Fragment
oder onCreate()
-Methode von Service
, zu der die Mediensitzung und der zugehörige Player gehören.
Um eine Mediensitzung zu erstellen, initialisieren Sie eine Player
und geben Sie sie 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 Statusverarbeitung
Die Media3-Bibliothek aktualisiert die Mediensitzung automatisch mithilfe der Spielerstatus angezeigt. So müssen Sie die Zuordnung von Spieler zu Sitzung wechseln.
Dies ist eine Abweichung vom Legacy-Ansatz, bei dem Sie das Erstellen und Verwalten
ein PlaybackStateCompat
unabhängig vom Player selbst, zum Beispiel für
auf Fehler hinweisen.
Eindeutige Sitzungs-ID
Standardmäßig erstellt MediaSession.Builder
eine Sitzung mit einem leeren String wie folgt:
die Sitzungs-ID. Dies ist ausreichend, wenn mit einer App nur eine einzige
Sitzungsinstanz. Dies ist der häufigste Fall.
Wenn eine App mehrere Sitzungsinstanzen gleichzeitig verwalten möchte,
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 ein IllegalStateException
Ihre App mit dem Fehler abstürzt
Nachricht IllegalStateException: Session ID must be unique. ID=
schreiben, dann ist es
Wahrscheinlichkeit, dass eine Sitzung unerwartet vor einer zuvor erstellten
-Instanz mit derselben ID freigegeben wurde. Damit Sitzungen nicht von einem
Programmierfehler auftreten, werden solche Fälle erkannt und
Ausnahme.
Anderen Kunden Kontrolle gewähren
Die Mediensitzung ist der Schlüssel zur Steuerung der Wiedergabe. Damit können Sie Befehle von externen Quellen an den Player, über den Medien. Bei diesen Quellen kann es sich um physische Schaltflächen wie die Wiedergabeschaltfläche auf einem Headset oder Fernbedienung des Fernsehers oder indirekte Befehle wie „Pause“ mit Google Assistant. Eventuell möchten Sie auch Zugriff auf die Android- für die Steuerung von Benachrichtigungen und Sperrbildschirm um die Wiedergabe über das Zifferblatt zu steuern. Externe Kunden können Verwenden Sie einen Mediencontroller, um Wiedergabebefehle an Ihre Medien-App zu senden. Dies sind in Ihrer Mediensitzung erhalten, wodurch letztendlich Befehle an die Mediaplayer.
<ph type="x-smartling-placeholder">![Ein Diagramm, das die Interaktion zwischen MediaSession und MediaController veranschaulicht.](https://developer.android.com/static/guide/topics/media/images/backgroundcontrols.png?authuser=0000&hl=de)
Wenn ein Controller eine Verbindung zu Ihrer Mediensitzung herstellen möchte,
onConnect()
aufgerufen wird. Sie können die bereitgestellte ControllerInfo
verwenden
um zu entscheiden, ob sie akzeptieren möchten,
oder ablehnen
der Anfrage. Ein Beispiel für das Annehmen einer Verbindungsanfrage finden Sie unter Deklarieren.
verfügbare Befehle.
Nach dem Verbinden kann ein Controller Wiedergabebefehle an die Sitzung senden. Die
und delegiert diese Befehle
an den Player. Wiedergabe und Playlist
Befehle, die in der Player
-Schnittstelle definiert sind, werden automatisch vom
Sitzung.
Mit anderen Callback-Methoden können Sie zum Beispiel Anfragen für
benutzerdefinierte Wiedergabebefehle und
das Bearbeiten der Playlist).
Diese Callbacks enthalten in ähnlicher Weise ein ControllerInfo
-Objekt, sodass Sie Änderungen daran vornehmen können.
wie Sie auf jede Anfrage für einen Verantwortlichen reagieren.
Playlist ändern
Eine Mediensitzung kann die Playlist ihres Players direkt ändern, wie unter
die
ExoPlayer-Leitfaden für Playlists
Controller können die Playlist auch ändern, wenn
COMMAND_SET_MEDIA_ITEM
oder COMMAND_CHANGE_MEDIA_ITEMS
für den Controller verfügbar.
Beim Hinzufügen neuer Elemente zur Playlist benötigt der Player normalerweise MediaItem
Instanzen mit einer
definierter URI
damit sie abgespielt werden können. Standardmäßig werden neu hinzugefügte Elemente automatisch weitergeleitet
zu Spielermethoden wie player.addMediaItem
, wenn dafür ein URI definiert ist.
Wenn du die MediaItem
-Instanzen anpassen möchtest, die dem Player hinzugefügt wurden, hast du folgende Möglichkeiten:
überschreiben
onAddMediaItems()
Dieser Schritt ist erforderlich, wenn Sie Controller unterstützen möchten, die Medien anfordern
ohne definierten URI. Stattdessen hat die MediaItem
normalerweise
Mindestens eines der folgenden Felder ist festgelegt, um die angeforderten Medien zu beschreiben:
MediaItem.id
: Eine generische ID zur Identifizierung des Mediums.MediaItem.RequestMetadata.mediaUri
: Ein Anfrage-URI, der einen benutzerdefinierten Schema und kann nicht unbedingt direkt vom Player wiedergegeben werden.MediaItem.RequestMetadata.searchQuery
: Eine Textsuchanfrage, z. B. von Google Assistant.MediaItem.MediaMetadata
: Strukturierte Metadaten wie „title“ oder "Interpret".
Weitere Anpassungsoptionen für völlig neue Playlists finden Sie
zusätzlich überschreiben
onSetMediaItems()
können Sie das Startelement und die Position in der Playlist festlegen. Beispiel:
können Sie ein einzelnes angefordertes Element auf eine ganze Playlist erweitern und das
Player so, dass er beim Index des ursprünglich angeforderten Elements beginnt. A
Beispielimplementierung von onSetMediaItems()
finden Sie in der
Session-Demo-App.
Benutzerdefiniertes Layout und benutzerdefinierte Befehle verwalten
In den folgenden Abschnitten wird beschrieben, wie Sie ein benutzerdefiniertes Layout für benutzerdefinierte Befehlstaste an Client-Apps und autorisieren die Controller, die benutzerdefinierten .
Benutzerdefiniertes Layout der Sitzung definieren
Um Client-Apps mitzuteilen, welche Steuerelemente für die Wiedergabe auf dem Gerät angezeigt werden sollen
können Sie das benutzerdefinierte Layout der Sitzung festlegen.
wenn Sie die MediaSession
in der onCreate()
-Methode Ihres
.
Kotlin
override fun onCreate() { super.onCreate() val likeButton = CommandButton.Builder() .setDisplayName("Like") .setIconResId(R.drawable.like_icon) .setSessionCommand(SessionCommand(SessionCommand.COMMAND_CODE_SESSION_SET_RATING)) .build() val favoriteButton = CommandButton.Builder() .setDisplayName("Save to favorites") .setIconResId(R.drawable.favorite_icon) .setSessionCommand(SessionCommand(SAVE_TO_FAVORITES, Bundle())) .build() session = MediaSession.Builder(this, player) .setCallback(CustomMediaSessionCallback()) .setCustomLayout(ImmutableList.of(likeButton, favoriteButton)) .build() }
Java
@Override public void onCreate() { super.onCreate(); CommandButton likeButton = new CommandButton.Builder() .setDisplayName("Like") .setIconResId(R.drawable.like_icon) .setSessionCommand(new SessionCommand(SessionCommand.COMMAND_CODE_SESSION_SET_RATING)) .build(); CommandButton favoriteButton = new CommandButton.Builder() .setDisplayName("Save to favorites") .setIconResId(R.drawable.favorite_icon) .setSessionCommand(new SessionCommand(SAVE_TO_FAVORITES, new Bundle())) .build(); Player player = new ExoPlayer.Builder(this).build(); mediaSession = new MediaSession.Builder(this, player) .setCallback(new CustomMediaSessionCallback()) .setCustomLayout(ImmutableList.of(likeButton, favoriteButton)) .build(); }
Verfügbare Player- und benutzerdefinierte Befehle deklarieren
Medienanwendungen können benutzerdefinierte Befehle definieren, die zum Beispiel in
ein benutzerdefiniertes Layout. Beispielsweise können Sie Schaltflächen implementieren,
um ein Medienelement in einer Liste mit Lieblingsinhalten zu speichern. Das MediaController
sendet benutzerdefinierte Befehle und MediaSession.Callback
empfängt diese.
Sie können festlegen, welche benutzerdefinierten Sitzungsbefehle einem
MediaController
, wenn eine Verbindung zu Ihrer Mediensitzung hergestellt wird. Das erreichen Sie,
MediaSession.Callback.onConnect()
wird überschrieben. Konfigurieren und zurückgeben
die verfügbaren Befehle beim Akzeptieren einer Verbindungsanfrage von einer
MediaController
in der Callback-Methode onConnect
:
Kotlin
private inner 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
onCustomCommand()
-Methode in der Callback
.
Kotlin
private inner 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 verfolgen, welcher Medienverantwortliche eine Anfrage stellt, indem Sie das Feld
Eigenschaft packageName
des Objekts MediaSession.ControllerInfo
, das
an Callback
-Methoden übergeben. So können Sie die Leistung Ihrer App
auf einen bestimmten Befehl reagieren,
wenn dieser vom System stammt,
oder andere Client-Apps.
Benutzerdefiniertes Layout nach einer Nutzerinteraktion aktualisieren
Nachdem du einen benutzerdefinierten Befehl
oder eine andere Interaktion mit deinem Player ausgeführt hast,
das auf der Benutzeroberfläche des Controllers angezeigte Layout zu aktualisieren. Ein typisches Beispiel
ist eine Ein/Aus-Schaltfläche, die ihr Symbol ändert, nachdem sie die zugehörige Aktion ausgelöst hat.
mit dieser Schaltfläche. Zum Aktualisieren des Layouts können Sie
MediaSession.setCustomLayout
:
Kotlin
val removeFromFavoritesButton = CommandButton.Builder() .setDisplayName("Remove from favorites") .setIconResId(R.drawable.favorite_remove_icon) .setSessionCommand(SessionCommand(REMOVE_FROM_FAVORITES, Bundle())) .build() mediaSession.setCustomLayout(ImmutableList.of(likeButton, removeFromFavoritesButton))
Java
CommandButton removeFromFavoritesButton = new CommandButton.Builder() .setDisplayName("Remove from favorites") .setIconResId(R.drawable.favorite_remove_icon) .setSessionCommand(new SessionCommand(REMOVE_FROM_FAVORITES, new Bundle())) .build(); mediaSession.setCustomLayout(ImmutableList.of(likeButton, removeFromFavoritesButton));
Verhalten von Wiedergabebefehlen anpassen
Zum Anpassen des Verhaltens eines in der Player
-Oberfläche definierten Befehls, z. B.
als play()
oder seekToNext()
verwenden, schließen Sie Player
in ForwardingPlayer
ein.
Kotlin
val player = ExoPlayer.Builder(context).build() val forwardingPlayer = object : ForwardingPlayer(player) { override fun play() { // Add custom logic super.play() } override fun setPlayWhenReady(playWhenReady: Boolean) { // Add custom logic super.setPlayWhenReady(playWhenReady) } } val mediaSession = MediaSession.Builder(context, forwardingPlayer).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build(); ForwardingPlayer forwardingPlayer = new ForwardingPlayer(player) { @Override public void play() { // Add custom logic super.play(); } @Override public void setPlayWhenReady(boolean playWhenReady) { // Add custom logic super.setPlayWhenReady(playWhenReady); } }; MediaSession mediaSession = new MediaSession.Builder(context, forwardingPlayer).build();
Weitere Informationen zu ForwardingPlayer
findest du im ExoPlayer-Handbuch unter
Anpassung.
Anfordernden Controller eines Spielerbefehls identifizieren
Wenn ein Aufruf einer Player
-Methode von MediaController
eingeht, können Sie
die Herkunftsquelle mit MediaSession.controllerForCurrentRequest
identifizieren
und rufen Sie die ControllerInfo
für die aktuelle Anfrage ab:
Kotlin
class CallerAwareForwardingPlayer(player: Player) : ForwardingPlayer(player) { override fun seekToNext() { Log.d( "caller", "seekToNext called from package ${session.controllerForCurrentRequest?.packageName}" ) super.seekToNext() } }
Java
public class CallerAwareForwardingPlayer extends ForwardingPlayer { public CallerAwareForwardingPlayer(Player player) { super(player); } @Override public void seekToNext() { Log.d( "caller", "seekToNext called from package: " + session.getControllerForCurrentRequest().getPackageName()); super.seekToNext(); } }
Auf Medienschaltflächen reagieren
Medienschaltflächen sind Hardwaretasten auf Android-Geräten und anderen Peripheriegeräten
(z. B. die Wiedergabe-/Pause-Taste an einem Bluetooth-Headset). Media3-Handles
Medienschaltflächen für Sie, wenn sie zur Sitzung kommen und die
Entsprechende Player
-Methode im Session-Player
Eine App kann das Standardverhalten überschreiben,
MediaSession.Callback.onMediaButtonEvent(Intent)
In einem solchen Fall kann die App
kann/muss alle API-Besonderheiten eigenständig bearbeiten.
Fehlerbehandlung und Berichterstellung
Es gibt zwei Arten von Fehlern, die in einer Sitzung ausgegeben und den Controllern gemeldet werden. Schwerwiegende Fehler melden einen technischen Fehler bei der Wiedergabe der Sitzung Player, der die Wiedergabe unterbricht. Schwerwiegende Fehler werden dem Controller gemeldet wenn sie auftreten. Nicht schwerwiegende Fehler sind nicht technisch oder richtlinienbedingt. Fehler, die die Wiedergabe nicht unterbrechen und vom manuell angewendet.
Schwerwiegende Wiedergabefehler
Der Player meldet einen schwerwiegenden Wiedergabefehler
den Controllern gemeldet,
Player.Listener.onPlayerError(PlaybackException)
und
Player.Listener.onPlayerErrorChanged(@Nullable PlaybackException)
.
In einem solchen Fall wird der Wiedergabestatus auf STATE_IDLE
umgestellt und
MediaController.getPlaybackError()
gibt die PlaybackException
zurück, die
für den Übergang. Ein Controller kann das PlayerException.errorCode
prüfen, um
Informationen zur Ursache des Fehlers.
Aus Interoperabilität wird ein schwerwiegender Fehler in den PlaybackStateCompat
repliziert
der Plattformsitzung, indem der Status in STATE_ERROR
geändert wird und
Fehlercode und Fehlermeldung gemäß PlaybackException
angezeigt.
Schwerwiegende Fehler anpassen
Um dem Nutzer lokalisierte und aussagekräftige Informationen zur Verfügung zu stellen, werden der Fehlercode,
Fehlermeldungen und Fehlerextras von schwerwiegenden
Wiedergabefehlern können angepasst werden,
mithilfe von ForwardingPlayer
beim Erstellen der Sitzung:
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 registriert ein Player.Listener
beim tatsächlichen Spieler.
und fängt Callbacks ab, die einen Fehler melden. Eine benutzerdefinierte
PlaybackException
wird dann an die Listener delegiert, die
im Weiterleitungsplayer registriert sind. Dazu muss der Weiterleitungsplayer
überschreibt Player.addListener
und Player.removeListener
, um Zugriff auf
Listener, mit denen benutzerdefinierte Fehlercodes, Nachrichten oder Extras gesendet werden:
Kotlin
class ErrorForwardingPlayer(private val context: Context, player: Player) : ForwardingPlayer(player) { private val listeners: MutableList<Player.Listener> = mutableListOf() private var customizedPlaybackException: PlaybackException? = null init { player.addListener(ErrorCustomizationListener()) } override fun addListener(listener: Player.Listener) { listeners.add(listener) } override fun removeListener(listener: Player.Listener) { listeners.remove(listener) } override fun getPlayerError(): PlaybackException? { return customizedPlaybackException } private inner class ErrorCustomizationListener : Player.Listener { override fun onPlayerErrorChanged(error: PlaybackException?) { customizedPlaybackException = error?.let { customizePlaybackException(it) } listeners.forEach { it.onPlayerErrorChanged(customizedPlaybackException) } } override fun onPlayerError(error: PlaybackException) { listeners.forEach { it.onPlayerError(customizedPlaybackException!!) } } private 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) } // Apps can customize further error messages by adding more branches. 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) } override fun onEvents(player: Player, events: Player.Events) { listeners.forEach { it.onEvents(player, events) } } // Delegate all other callbacks to all listeners without changing arguments like onEvents. } }
Java
private static class ErrorForwardingPlayer extends ForwardingPlayer { private final Context context; private List<Player.Listener> listeners; @Nullable private PlaybackException customizedPlaybackException; public ErrorForwardingPlayer(Context context, Player player) { super(player); this.context = context; listeners = new ArrayList<>(); player.addListener(new ErrorCustomizationListener()); } @Override public void addListener(Player.Listener listener) { listeners.add(listener); } @Override public void removeListener(Player.Listener listener) { listeners.remove(listener); } @Nullable @Override public PlaybackException getPlayerError() { return customizedPlaybackException; } private class ErrorCustomizationListener implements Listener { @Override public void onPlayerErrorChanged(@Nullable PlaybackException error) { customizedPlaybackException = error != null ? customizePlaybackException(error, context) : null; for (int i = 0; i < listeners.size(); i++) { listeners.get(i).onPlayerErrorChanged(customizedPlaybackException); } } @Override public void onPlayerError(PlaybackException error) { for (int i = 0; i < listeners.size(); i++) { listeners.get(i).onPlayerError(checkNotNull(customizedPlaybackException)); } } private PlaybackException customizePlaybackException( PlaybackException error, Context context) { 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; // Apps can customize further error messages by adding more case statements. 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); } @Override public void onEvents(Player player, Events events) { for (int i = 0; i < listeners.size(); i++) { listeners.get(i).onEvents(player, events); } } // Delegate all other callbacks to all listeners without changing arguments like onEvents. } }
Nicht schwerwiegende Fehler
Nicht schwerwiegende Fehler, die nicht auf eine technische Ausnahme zurückzuführen sind, können gesendet werden. durch eine App an alle oder einen bestimmten Controller:
Kotlin
val sessionError = SessionError( SessionError.ERROR_SESSION_AUTHENTICATION_EXPIRED, context.getString(R.string.error_message_authentication_expired), ) // Sending a nonfatal error to all controllers. mediaSession.sendError(sessionError) // Interoperability: Sending a nonfatal error to the media notification controller 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)); // Sending a nonfatal error to all controllers. mediaSession.sendError(sessionError); // Interoperability: Sending a nonfatal error to the media notification controller 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); }
Ein nicht schwerwiegender Fehler, der an den Media Notification Controller gesendet wurde, wird an den
PlaybackStateCompat
der Plattformsitzung. Daher werden nur der Fehlercode und
wird die Fehlermeldung entsprechend auf PlaybackStateCompat
gesetzt, während
PlaybackStateCompat.state
wurde nicht in STATE_ERROR
geändert.
Nicht schwerwiegende Fehler erhalten
Ein MediaController
erhält einen nicht schwerwiegenden Fehler durch Implementierung
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. } });