Écouter des événements de lecture
Les événements, tels que les changements d'état et les erreurs de lecture, sont signalés aux instances Player.Listener
enregistrées. Pour enregistrer un écouteur afin de recevoir de tels événements, procédez comme suit:
Kotlin
// Add a listener to receive events from the player. player.addListener(listener)
Java
// Add a listener to receive events from the player. player.addListener(listener);
Player.Listener
comporte des méthodes par défaut vides. Vous ne devez donc implémenter que celles qui vous intéressent. Consultez la page Javadoc pour obtenir une description complète des méthodes et du moment où elles sont appelées. Certaines des méthodes les plus importantes sont décrites plus en détail ci-dessous.
Les écouteurs ont le choix entre implémenter des rappels d'événements individuels ou un rappel onEvents
générique qui est appelé après qu'un ou plusieurs événements se produisent ensemble. Consultez la section Individual callbacks vs onEvents
pour en savoir plus sur les méthodes à privilégier pour différents cas d'utilisation.
Changements de l'état de la lecture
Vous pouvez recevoir les modifications de l'état du lecteur en implémentant onPlaybackStateChanged(@State int state)
dans un Player.Listener
enregistré. Le lecteur peut avoir l'un des quatre états de lecture suivants:
Player.STATE_IDLE
: état initial, état d'arrêt du lecteur et d'échec de la lecture. Dans cet état, le lecteur ne dispose que de ressources limitées.Player.STATE_BUFFERING
: le lecteur ne peut pas lancer immédiatement la lecture à partir de sa position actuelle. Cela se produit généralement lorsque davantage de données doivent être chargées.Player.STATE_READY
: le lecteur peut lancer la lecture immédiatement à partir de sa position actuelle.Player.STATE_ENDED
: le lecteur a fini de lire tous les contenus multimédias.
En plus de ces états, le lecteur dispose d'un indicateur playWhenReady
pour indiquer l'intention de l'utilisateur de jouer. Vous pouvez recevoir les modifications apportées à cette option en implémentant onPlayWhenReadyChanged(playWhenReady, @PlayWhenReadyChangeReason int reason)
.
Le lecteur est en cours de lecture (c'est-à-dire que sa position progresse et que le contenu multimédia est présenté à l'utilisateur) lorsque les trois conditions suivantes sont remplies:
- Le lecteur est à l'état
Player.STATE_READY
. playWhenReady
esttrue
- La lecture n'est pas interrompue pour un motif renvoyé par
Player.getPlaybackSuppressionReason
.
Au lieu de devoir vérifier ces propriétés individuellement, Player.isPlaying
peut être appelé. Vous pouvez recevoir les modifications apportées à cet état en implémentant onIsPlayingChanged(boolean isPlaying)
:
Kotlin
player.addListener( object : Player.Listener { override fun onIsPlayingChanged(isPlaying: Boolean) { if (isPlaying) { // Active playback. } else { // Not playing because playback is paused, ended, suppressed, or the player // is buffering, stopped or failed. Check player.playWhenReady, // player.playbackState, player.playbackSuppressionReason and // player.playerError for details. } } } )
Java
player.addListener( new Player.Listener() { @Override public void onIsPlayingChanged(boolean isPlaying) { if (isPlaying) { // Active playback. } else { // Not playing because playback is paused, ended, suppressed, or the player // is buffering, stopped or failed. Check player.getPlayWhenReady, // player.getPlaybackState, player.getPlaybackSuppressionReason and // player.getPlaybackError for details. } } });
Erreurs de lecture
Les erreurs qui entraînent l'échec de la lecture peuvent être reçues en implémentant onPlayerError(PlaybackException error)
dans un Player.Listener
enregistré. En cas d'échec, cette méthode est appelée immédiatement avant que l'état de lecture ne passe à Player.STATE_IDLE
.
Vous pouvez relancer la lecture en cas d'échec ou d'arrêt en appelant ExoPlayer.prepare
.
Notez que certaines implémentations de Player
transmettent des instances des sous-classes de PlaybackException
pour fournir des informations supplémentaires sur l'échec. Par exemple, ExoPlayer
transmet ExoPlaybackException
, qui contient type
, rendererIndex
et d'autres champs spécifiques à ExoPlayer.
L'exemple suivant montre comment détecter un échec de lecture en raison d'un problème de réseau HTTP:
Kotlin
player.addListener( object : Player.Listener { override fun onPlayerError(error: PlaybackException) { val cause = error.cause if (cause is HttpDataSourceException) { // An HTTP error occurred. val httpError = cause // It's possible to find out more about the error both by casting and by querying // the cause. if (httpError is InvalidResponseCodeException) { // Cast to InvalidResponseCodeException and retrieve the response code, message // and headers. } else { // Try calling httpError.getCause() to retrieve the underlying cause, although // note that it may be null. } } } } )
Java
player.addListener( new Player.Listener() { @Override public void onPlayerError(PlaybackException error) { @Nullable Throwable cause = error.getCause(); if (cause instanceof HttpDataSourceException) { // An HTTP error occurred. HttpDataSourceException httpError = (HttpDataSourceException) cause; // It's possible to find out more about the error both by casting and by querying // the cause. if (httpError instanceof HttpDataSource.InvalidResponseCodeException) { // Cast to InvalidResponseCodeException and retrieve the response code, message // and headers. } else { // Try calling httpError.getCause() to retrieve the underlying cause, although // note that it may be null. } } } });
Transitions des playlists
Chaque fois que le lecteur passe à un nouvel élément multimédia dans la playlist, onMediaItemTransition(MediaItem mediaItem,
@MediaItemTransitionReason int reason)
est appelé sur les objets Player.Listener
enregistrés. Le motif indique s'il s'agit d'une transition automatique, d'une recherche (par exemple, après avoir appelé player.next()
), d'une répétition du même élément ou d'une modification de la playlist (par exemple, si l'élément en cours de lecture est supprimé).
Metadata
Les métadonnées renvoyées par player.getCurrentMediaMetadata()
peuvent être modifiées pour de nombreuses raisons: les transitions de playlists, les mises à jour des métadonnées InStream ou la mise à jour de l'MediaItem
actuelle en cours de lecture.
Si vous êtes intéressé par les modifications de métadonnées, par exemple pour mettre à jour une UI qui affiche le titre actuel, vous pouvez écouter onMediaMetadataChanged
.
Recherche…
L'appel des méthodes Player.seekTo
entraîne une série de rappels sur les instances Player.Listener
enregistrées:
onPositionDiscontinuity
avecreason=DISCONTINUITY_REASON_SEEK
. Il s'agit du résultat direct de l'appel dePlayer.seekTo
. Le rappel comporte des champsPositionInfo
pour la position avant et après la recherche.onPlaybackStateChanged
avec tout changement d'état immédiat lié à la recherche. Notez qu'un tel changement n'est peut-être pas le cas.
Rappels individuels et rappel onEvents
Les écouteurs peuvent choisir d'implémenter des rappels individuels tels que onIsPlayingChanged(boolean isPlaying)
ou le rappel générique onEvents(Player player, Events events)
. Le rappel générique fournit un accès à l'objet Player
et spécifie l'ensemble des events
qui ont eu lieu ensemble. Ce rappel est toujours appelé après les rappels correspondant aux événements individuels.
Kotlin
override fun onEvents(player: Player, events: Player.Events) { if ( events.contains(Player.EVENT_PLAYBACK_STATE_CHANGED) || events.contains(Player.EVENT_PLAY_WHEN_READY_CHANGED) ) { uiModule.updateUi(player) } }
Java
@Override public void onEvents(Player player, Events events) { if (events.contains(Player.EVENT_PLAYBACK_STATE_CHANGED) || events.contains(Player.EVENT_PLAY_WHEN_READY_CHANGED)) { uiModule.updateUi(player); } }
Il convient de privilégier les événements individuels dans les cas suivants:
- L'écouteur s'intéresse aux raisons des changements. Par exemple, les raisons fournies pour
onPlayWhenReadyChanged
ouonMediaItemTransition
. - L'écouteur n'agit que sur les nouvelles valeurs fournies via les paramètres de rappel ou déclenche un autre élément qui ne dépend pas des paramètres de rappel.
- L'implémentation de l'écouteur préfère une indication claire et lisible de ce qui a déclenché l'événement dans le nom de la méthode.
- L'écouteur est transmis à un système d'analyse qui doit connaître tous les événements individuels et tous les changements d'état.
Il est préférable d'utiliser le paramètre onEvents(Player player, Events events)
générique dans les cas suivants:
- L'écouteur souhaite déclencher la même logique pour plusieurs événements. Par exemple, vous pouvez mettre à jour une UI pour
onPlaybackStateChanged
etonPlayWhenReadyChanged
. - L'écouteur doit accéder à l'objet
Player
pour déclencher d'autres événements, par exemple en effectuant une recherche après une transition d'élément multimédia. - L'écouteur a l'intention d'utiliser plusieurs valeurs d'état transmises ensemble via des rappels distincts ou en combinaison avec des méthodes getter
Player
. Par exemple, l'utilisation dePlayer.getCurrentWindowIndex()
avec leTimeline
fourni dansonTimelineChanged
n'est sécurisée qu'à partir du rappelonEvents
. - L'écouteur vérifie si les événements se sont produits ensemble de manière logique. Par exemple, passer de
onPlaybackStateChanged
àSTATE_BUFFERING
en raison d'une transition d'élément multimédia.
Dans certains cas, les écouteurs peuvent avoir besoin de combiner les rappels individuels avec le rappel onEvents
générique, par exemple pour enregistrer les motifs de modification d'un élément multimédia avec onMediaItemTransition
, mais agir seulement une fois que tous les changements d'état peuvent être utilisés ensemble dans onEvents
.
AnalyticsListener
utilisé(s)
Lorsque vous utilisez ExoPlayer
, un AnalyticsListener
peut être enregistré auprès du lecteur en appelant addAnalyticsListener
. Les implémentations AnalyticsListener
peuvent écouter des événements détaillés pouvant être utiles à des fins d'analyse et de journalisation. Pour en savoir plus, consultez la page des données analytiques.
EventLogger
utilisé(s)
EventLogger
est un AnalyticsListener
fourni directement par la bibliothèque à des fins de journalisation. Ajoutez EventLogger
à un ExoPlayer
pour activer la journalisation supplémentaire utile avec une seule ligne:
Kotlin
player.addAnalyticsListener(EventLogger())
Java
player.addAnalyticsListener(new EventLogger());
Pour en savoir plus, consultez la page de journalisation du débogage.
Événements déclenchés à des positions de lecture spécifiées
Certains cas d'utilisation nécessitent le déclenchement d'événements à des positions de lecture spécifiées. Cette opération est possible à l'aide de PlayerMessage
. Un PlayerMessage
peut être créé à l'aide de ExoPlayer.createMessage
. La position de lecture à laquelle l'exécuter peut être définie à l'aide de PlayerMessage.setPosition
. Les messages sont exécutés sur le thread de lecture par défaut, mais cela peut être personnalisé à l'aide de PlayerMessage.setLooper
. PlayerMessage.setDeleteAfterDelivery
permet de contrôler si le message sera exécuté chaque fois que la position de lecture spécifiée est atteinte (cela peut se produire plusieurs fois en raison des modes de recherche et de répétition), ou uniquement la première fois. Une fois l'PlayerMessage
configurée, vous pouvez la planifier à l'aide de PlayerMessage.send
.
Kotlin
player .createMessage { messageType: Int, payload: Any? -> } .setLooper(Looper.getMainLooper()) .setPosition(/* mediaItemIndex= */ 0, /* positionMs= */ 120000) .setPayload(customPayloadData) .setDeleteAfterDelivery(false) .send()
Java
player .createMessage( (messageType, payload) -> { // Do something at the specified playback position. }) .setLooper(Looper.getMainLooper()) .setPosition(/* mediaItemIndex= */ 0, /* positionMs= */ 120_000) .setPayload(customPayloadData) .setDeleteAfterDelivery(false) .send();