Les sessions multimédias fournissent un moyen universel d'interagir avec un contenu audio ou vidéo
joueur. Dans Media3, le lecteur par défaut est la classe ExoPlayer
, qui implémente
l'interface Player
. Connecter la session multimédia au lecteur permet à une application
pour annoncer la lecture de contenus multimédias en externe et recevoir des commandes de lecture
sources externes.
Les commandes peuvent provenir de boutons physiques, comme le bouton de lecture du casque ou de la télécommande du téléviseur. Elles peuvent également provenir d'applications clientes contrôleur multimédia, par exemple en demandant la commande "pause" à l'Assistant Google. Les médias délègue ces commandes au lecteur de l'application multimédia.
Quand choisir une session multimédia ?
Lorsque vous implémentez MediaSession
, vous permettez aux utilisateurs de contrôler la lecture:
- Via leur casque Il y a souvent des boutons ou des interactions tactiles l'utilisateur peut jouer ou mettre en pause un contenu multimédia avec son casque, ou passer au suivant ou la piste précédente.
- En parlant à l'Assistant Google Une pratique courante consiste à dire "OK" "Google, mets en pause" pour mettre en pause tous les contenus multimédias en cours de lecture sur l'appareil.
- Via sa montre Wear OS Cela vous permet d'accéder plus facilement commandes de lecture courantes lorsqu'ils jouent sur leur téléphone.
- Via les commandes multimédias Ce carrousel présente des commandes pour chaque en cours d'exécution.
- Sur un téléviseur Autorise les actions avec des boutons de lecture physiques et la lecture via la plate-forme et la gestion de l'alimentation (par exemple, si le téléviseur, la barre de son ou le récepteur AV ou si l'entrée change, la lecture doit s'arrêter dans l'application).
- ainsi que tout autre processus externe qui doit influencer la lecture.
C'est la solution idéale dans de nombreux cas d'utilisation. En particulier, vous devez
vivement envisager
à l'aide de MediaSession
lorsque:
- Vous diffusez du contenu vidéo de longue durée, comme des films ou la télévision en direct.
- Vous diffusez en streaming des contenus audio de longue durée, comme des podcasts ou de la musique playlists.
- Vous développez une application TV.
Cependant, tous les cas d'utilisation ne sont pas adaptés à MediaSession
. Vous voudrez peut-être
Utilisez uniquement Player
dans les cas suivants:
- Vous diffusez des contenus courts, dans lesquels l'engagement et l'interaction des utilisateurs sont nombreux. est crucial.
- n'a pas une seule vidéo active (par exemple, un utilisateur fait défiler une liste) ; et plusieurs vidéos s'affichent à la fois sur l'écran.
- vous regardez une vidéo d'introduction ou d'explication ponctuelle, que l'utilisateur regarde activement.
- Votre contenu est sensible à la confidentialité, et vous ne souhaitez pas que des processus externes Accéder aux métadonnées multimédias (par exemple, en mode navigation privée dans un navigateur)
Si votre cas d'utilisation ne correspond à aucun de ces critères, demandez-vous
que votre application continue la lecture lorsque l'utilisateur n'interagit pas activement
avec le contenu. Si la réponse est oui, vous souhaiterez probablement
MediaSession
Si la réponse est non, vous souhaiterez probablement utiliser la fonction Player
à la place.
Créer une session multimédia
Les sessions multimédias accompagnent le lecteur qu'il gère. Vous pouvez construire un
session multimédia avec un objet Context
et un objet Player
. Vous devez créer et
d'initialiser une session multimédia si nécessaire, par exemple onStart()
ou
Méthode de cycle de vie onResume()
de Activity
, Fragment
ou onCreate()
Méthode du Service
propriétaire de la session multimédia et du lecteur associé.
Pour créer une session multimédia, initialisez un Player
et fournissez-le à
MediaSession.Builder
personnes aiment ça:
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();
Gestion automatique de l'état
La bibliothèque Media3 met automatiquement à jour la session multimédia à l'aide de la méthode l'état du lecteur. Ainsi, vous n'avez pas besoin de gérer manuellement le mappage joueur à session.
Il s'agit d'une rupture par rapport à l'ancienne approche, où vous deviez créer et gérer
un PlaybackStateCompat
indépendamment du lecteur lui-même, par exemple pour
indique d'éventuelles erreurs.
ID de session unique
Par défaut, MediaSession.Builder
crée une session avec une chaîne vide en tant que
l'ID de session. C'est suffisant si une application ne vise qu'une seule
une instance de session, ce qui est le cas le plus courant.
Si une application souhaite gérer plusieurs instances de session en même temps, elle
doit s'assurer que l'ID de session
de chaque session est unique. L'ID de session peut
doit être défini lors de la création de la session avec MediaSession.Builder.setId(String id)
.
Si vous constatez qu'une IllegalStateException
plante votre application avec l'erreur
message IllegalStateException: Session ID must be unique. ID=
alors le résultat est
probablement qu'une session ait été créée de manière inattendue avant qu'une session
portant le même ID a été libérée. Pour éviter que les sessions soient divulguées par
de programmation, de telles situations sont détectées et notifiées en renvoyant une
une exception.
Accorder le contrôle à d'autres clients
La session multimédia est essentielle pour contrôler la lecture. Elle vous permet d'acheminer des commandes externes au lecteur qui effectue le travail de lecture de votre médias. Ces sources peuvent être des boutons physiques, comme le bouton de lecture de la télécommande du casque ou du téléviseur, ou des commandes indirectes telles que "Mettre en pause" à l'Assistant Google. De même, vous pouvez autoriser l'accès pour faciliter les commandes de notification et de verrouillage de l'écran, ou à un système d'exploitation Wear OS pour contrôler la lecture à partir du cadran. Les clients externes peuvent utiliser une télécommande multimédia pour envoyer des commandes de lecture à votre application multimédia. Il s'agit reçues par votre session multimédia, qui délègue ensuite des commandes au du lecteur multimédia.
<ph type="x-smartling-placeholder">Lorsqu'une manette est sur le point de se connecter à votre session multimédia,
onConnect()
est appelée. Vous pouvez utiliser la ControllerInfo
fournie
décider d'accepter ou non
ou refuser
la demande. Vous trouverez un exemple d'acceptation d'une demande de connexion dans la section Déclarer
commandes disponibles.
Une fois connectée, une manette peut envoyer des commandes de lecture à la session. La
délègue ensuite ces commandes au joueur. Lecture et playlist
définies dans l'interface Player
sont automatiquement gérées par
session.
D'autres méthodes de rappel vous permettent, par exemple, de gérer les requêtes pour
commandes de lecture personnalisées
modifier la playlist).
Ces rappels incluent également un objet ControllerInfo
afin que vous puissiez modifier
comment vous répondez à chaque demande pour chaque responsable du traitement.
Modifier la playlist
Une session multimédia peut modifier directement la playlist de son lecteur, comme expliqué dans
la
Guide ExoPlayer pour les playlists
Les contrôleurs peuvent également modifier la playlist si :
COMMAND_SET_MEDIA_ITEM
ou COMMAND_CHANGE_MEDIA_ITEMS
est disponible pour la manette.
Lors de l'ajout de nouveaux éléments à la playlist, le lecteur a généralement besoin de MediaItem
des instances avec un
URI défini
pour les rendre jouables. Par défaut, les nouveaux éléments sont transférés automatiquement
aux méthodes du lecteur telles que player.addMediaItem
si un URI est défini.
Si vous souhaitez personnaliser les instances MediaItem
ajoutées au lecteur, vous pouvez
ignorer
onAddMediaItems()
Cette étape est nécessaire si vous souhaitez accepter les manettes qui demandent des contenus multimédias
sans URI défini. Au lieu de cela, MediaItem
a généralement
Un ou plusieurs des champs suivants sont définis pour décrire le contenu multimédia demandé:
MediaItem.id
: ID générique identifiant le contenu multimédia.MediaItem.RequestMetadata.mediaUri
: URI de requête pouvant utiliser un nom personnalisé et n'est pas nécessairement lisible directement par le lecteur.MediaItem.RequestMetadata.searchQuery
: requête de recherche textuelle, par exemple depuis l'Assistant Google.MediaItem.MediaMetadata
: métadonnées structurées telles que "title" ou "artist" (artiste).
Si vous souhaitez plus d'options de personnalisation pour de toutes nouvelles playlists, vous pouvez
remplacer également
onSetMediaItems()
qui vous permet de définir l'élément
de départ et la position dans la playlist. Par exemple :
vous pouvez étendre un élément demandé à une playlist entière et demander à
pour que le lecteur commence à l'index de l'élément initialement demandé. A
Exemple d'implémentation de onSetMediaItems()
avec cette fonctionnalité sont disponibles dans l'application de démonstration de la session.
Gérer la mise en page personnalisée et les commandes personnalisées
Les sections suivantes décrivent comment promouvoir une mise en page personnalisée des aux applications clientes et autoriser les manettes à envoyer le modèle commandes.
Définir la mise en page personnalisée de la session
Pour indiquer aux applications clientes les commandes de lecture que vous souhaitez présenter à l'application
définir la mise en page personnalisée de la session ;
lorsque vous créez le MediaSession
dans la méthode onCreate()
de votre
Google Cloud.
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(); }
Déclarer le lecteur disponible et les commandes personnalisées
Les applications multimédias peuvent définir des commandes personnalisées utilisables, par exemple,
une mise en page personnalisée. Par exemple, vous pouvez implémenter des boutons qui permettent au
pour enregistrer un élément multimédia dans une liste d'éléments favoris. MediaController
envoie des commandes personnalisées, et MediaSession.Callback
les reçoit.
Vous pouvez définir les commandes de session personnalisées disponibles
MediaController
lorsqu'il se connecte à votre session multimédia. Pour y parvenir,
remplacer MediaSession.Callback.onConnect()
. Configurer et renvoyer
l'ensemble des commandes disponibles lors de l'acceptation d'une demande de connexion
MediaController
dans la méthode de rappel 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(); } }
Pour recevoir des requêtes de commande personnalisées à partir d'un MediaController
, remplacez le
Méthode onCustomCommand()
dans 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) ); } ... } }
Vous pouvez identifier le contrôleur multimédia qui envoie une requête à l'aide de la propriété
Propriété packageName
de l'objet MediaSession.ControllerInfo
qui est
transmises dans les méthodes Callback
. Cela vous permet d'adapter
en réponse à une commande donnée si celle-ci provient du système,
votre propre application ou
d'autres applications clientes.
Mettre à jour la mise en page personnalisée après une interaction utilisateur
Après avoir traité une commande personnalisée ou toute autre interaction avec le lecteur, vous
vous devrez peut-être mettre à jour la disposition affichée dans l'UI de la manette. Exemple typique
est un bouton d'activation qui modifie son icône après le déclenchement de l'action associée
à l'aide de ce bouton. Pour mettre à jour la mise en page, vous pouvez utiliser
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));
Personnaliser le comportement des commandes de lecture
Pour personnaliser le comportement d'une commande définie dans l'interface Player
, par exemple
en tant que play()
ou seekToNext()
, encapsulez votre Player
dans un ForwardingPlayer
.
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();
Pour en savoir plus sur ForwardingPlayer
, consultez le guide ExoPlayer sur
Personnalisation.
Identifier le contrôleur à l'origine de la demande d'une commande du joueur
Lorsqu'un appel à une méthode Player
provient d'un MediaController
, vous pouvez
Identifier la source d'origine avec MediaSession.controllerForCurrentRequest
et acquérez le ControllerInfo
pour la requête actuelle:
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(); } }
Réagir aux boutons multimédias
Les boutons multimédias sont des boutons physiques présents sur les appareils Android et les autres périphériques
tels que le bouton lecture/pause d'un casque Bluetooth. Poignées Media3
les événements du bouton multimédia à votre place lorsqu'ils arrivent à la session et appelle
la méthode Player
appropriée sur le lecteur de session.
Une application peut ignorer le comportement par défaut en remplaçant
MediaSession.Callback.onMediaButtonEvent(Intent)
Dans ce cas, l’application
peut/doit gérer toutes les spécificités de l'API par elle-même.
Traitement des erreurs et création de rapports
Une session émet deux types d'erreurs et les signale aux contrôleurs. Les erreurs fatales signalent un échec technique de lecture de la session qui interrompt la lecture. Les erreurs fatales sont signalées au contrôleur automatiquement quand ils se produisent. Les erreurs non fatales ne sont pas d'ordre technique ou ne concernent pas le règlement erreurs qui n'interrompent pas la lecture et sont envoyées aux manettes par manuellement.
Erreurs de lecture fatales
Une erreur de lecture fatale est signalée à la session par le lecteur, puis
signalées aux manettes pour qu'elles appellent
Player.Listener.onPlayerError(PlaybackException)
et
Player.Listener.onPlayerErrorChanged(@Nullable PlaybackException)
Dans ce cas, l'état de lecture passe à STATE_IDLE
.
MediaController.getPlaybackError()
renvoie l'PlaybackException
qui a causé
la transition. Un contrôleur peut inspecter le PlayerException.errorCode
pour obtenir
des informations sur le motif de l'erreur.
Pour des raisons d'interopérabilité, une erreur fatale est répliquée sur PlaybackStateCompat
.
de la session de la plate-forme en faisant passer son état à STATE_ERROR
et en définissant
code d'erreur et message en fonction de PlaybackException
.
Personnalisation d'une erreur fatale
Pour fournir des informations
localisées et significatives à l'utilisateur,
les messages d'erreur et les extras d'une erreur de lecture fatale peuvent être personnalisés
Utiliser un ForwardingPlayer
lors de la création de la session:
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();
Le lecteur de transfert enregistre un Player.Listener
pour le joueur réel.
et intercepte les rappels qui signalent une erreur. Une configuration personnalisée
PlaybackException
est ensuite délégué aux écouteurs
sont enregistrés dans le lecteur de transfert. Pour que cela fonctionne, le lecteur de transfert
remplace Player.addListener
et Player.removeListener
pour avoir accès
Écouteurs avec lesquels envoyer un code d'erreur, un message ou des éléments supplémentaires personnalisés:
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. } }
Erreurs non fatales
Les erreurs non fatales qui ne proviennent pas d'une exception technique peuvent être envoyées par une application à tous les contrôleurs ou à un contrôleur spécifique:
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); }
Une erreur non fatale envoyée au contrôleur de notification multimédia est répliquée sur
PlaybackStateCompat
de la session sur la plate-forme. Ainsi, seuls le code d'erreur et
le message d'erreur est défini sur PlaybackStateCompat
en conséquence, alors que
PlaybackStateCompat.state
n'est pas remplacé par STATE_ERROR
.
Recevoir des erreurs non fatales
Un MediaController
reçoit une erreur non fatale en implémentant
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. } });