Ascoltare eventi di riproduzione
Gli eventi, come le modifiche allo stato e gli errori di riproduzione, vengono segnalati come registrati
Player.Listener
istanze. Per registrare un listener in modo che riceva tali
eventi:
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
ha metodi predefiniti vuoti, quindi devi solo implementare
i metodi che ti interessano. Vedi Javadoc per una descrizione completa
i metodi e quando vengono chiamati. Alcuni dei metodi più importanti
descritti più dettagliatamente di seguito.
I listener possono scegliere se implementare i callback di singoli eventi o un
callback onEvents
generico che viene chiamato dopo che si sono verificati uno o più eventi
in sinergia. Per una spiegazione, consulta Individual callbacks vs onEvents
da preferire per diversi casi d'uso.
Modifiche allo stato di riproduzione
Le modifiche allo stato del player possono essere ricevute implementando
onPlaybackStateChanged(@State int state)
in un account registrato
Player.Listener
. Il player può essere in uno dei quattro stati di riproduzione seguenti:
Player.STATE_IDLE
: si tratta dello stato iniziale, lo stato in cui il player è stata interrotta e la riproduzione non è riuscita. Il giocatore avrà solo risorse limitate in questo stato.Player.STATE_BUFFERING
: il giocatore non è in grado di giocare immediatamente dal suo posizione corrente. Ciò accade principalmente perché è necessario caricare più dati.Player.STATE_READY
: il giocatore può giocare immediatamente dalla sua posizione attuale posizione.Player.STATE_ENDED
: il player ha terminato la riproduzione di tutti i contenuti multimediali.
Oltre a questi stati, il giocatore ha una bandiera playWhenReady
per indicare
l'intenzione dell'utente di giocare. Le modifiche a questo flag possono essere ricevute implementando
onPlayWhenReadyChanged(playWhenReady, @PlayWhenReadyChangeReason int reason)
.
Un player è in riproduzione (ovvero, la sua posizione sta avanzando e i contenuti multimediali vengono presentati all'utente) quando tutte e tre le seguenti condizioni sono soddisfatte:
- Il player è nello stato
Player.STATE_READY
playWhenReady
ètrue
- La riproduzione non è soppressa per un motivo restituito da
Player.getPlaybackSuppressionReason
Anziché dover controllare queste proprietà singolarmente, Player.isPlaying
di Google Cloud. Le modifiche a questo stato possono essere ricevute implementando
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. } } });
Errori di riproduzione
Gli errori che causano la mancata riuscita della riproduzione possono essere ricevuti tramite l'implementazione
onPlayerError(PlaybackException error)
in un account registrato
Player.Listener
. In caso di errore, questo metodo viene chiamato
subito prima della transizione dello stato di riproduzione a Player.STATE_IDLE
.
È possibile ritentare le riproduzioni non riuscite o interrotte chiamando ExoPlayer.prepare
.
Tieni presente che alcune implementazioni di Player
passano istanze delle sottoclassi di
PlaybackException
per fornire ulteriori informazioni sull'errore. Per
ad esempio ExoPlayer
passa ExoPlaybackException
, che ha type
,
rendererIndex
e altri campi specifici di ExoPlayer.
L'esempio seguente mostra come rilevare quando una riproduzione non è riuscita a causa di un Problema di rete 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. } } } });
Transizioni playlist
Ogni volta che il player passa a un nuovo elemento multimediale nella playlist.
onMediaItemTransition(MediaItem mediaItem,
@MediaItemTransitionReason int reason)
è stata chiamata quando è stata effettuata la registrazione
Player.Listener
oggetti. Il motivo indica se si è trattato di un evento automatico
transizione, una ricerca (ad esempio dopo aver chiamato player.next()
), una ripetizione
lo stesso elemento o causato da una modifica alla playlist (ad esempio, se al momento
l'elemento in riproduzione viene rimosso).
Metadati
I metadati restituiti da player.getCurrentMediaMetadata()
possono cambiare a causa di molti
Motivi: transizioni di playlist, aggiornamenti dei metadati in-stream o aggiornamento
MediaItem
attuale durante la riproduzione.
Se ti interessa apportare modifiche ai metadati, ad esempio aggiornare una UI che mostri
il titolo attuale, puoi ascoltare onMediaMetadataChanged
.
Attivazione dello spostamento in corso
La chiamata di metodi Player.seekTo
comporta una serie di callback ai metodi registrati
Player.Listener
istanze:
onPositionDiscontinuity
conreason=DISCONTINUITY_REASON_SEEK
. Questo è il risultato diretto della chiamata aPlayer.seekTo
. Il callback haPositionInfo
campi per la posizione prima e dopo la ricerca.onPlaybackStateChanged
con qualsiasi modifica di stato immediata relativa alla ricerca. Tieni presente che questo cambiamento potrebbe non avvenire.
Callback individuali e onEvents
Gli ascoltatori possono scegliere se implementare singoli callback come
onIsPlayingChanged(boolean isPlaying)
e le opzioni generiche
Chiamata onEvents(Player player, Events events)
. Il callback generico fornisce
all'oggetto Player
e specifica l'insieme di events
che si è verificato
in sinergia. Questo callback viene sempre chiamato dopo i callback che corrispondono
i singoli eventi.
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); } }
È preferibile optare per i singoli eventi nei seguenti casi:
- L'ascoltatore è interessato ai motivi delle modifiche. Ad esempio,
motivi forniti per
onPlayWhenReadyChanged
oonMediaItemTransition
. - Il listener agisce solo sui nuovi valori forniti tramite i parametri di callback o attiva qualcos'altro che non dipende dai parametri di callback.
- L'implementazione dell'ascoltatore preferisce un'indicazione chiara e leggibile di ciò che abbia attivato l'evento nel nome del metodo.
- L'ascoltatore segnala a un sistema di analisi che deve conoscere tutti singoli eventi e modifiche di stato.
Il campo onEvents(Player player, Events events)
generico deve essere preferito nel campo
i seguenti casi:
- Il listener vuole attivare la stessa logica per più eventi. Per
ad esempio l'aggiornamento di una UI sia per
onPlaybackStateChanged
onPlayWhenReadyChanged
. - Il listener deve accedere all'oggetto
Player
per attivare ulteriori eventi, ad esempio la ricerca dopo la transizione di un elemento multimediale. - Il listener intende utilizzare più valori di stato segnalati
tramite callback separati insieme o in combinazione con il getter
Player
di machine learning. Ad esempio, l'utilizzo diPlayer.getCurrentWindowIndex()
con Il metodo di pagamentoTimeline
fornito inonTimelineChanged
è al sicuro soltanto all'interno di Chiamata dionEvents
. - Il listener è interessato a sapere se gli eventi si sono verificati logicamente insieme. Per
esempio, da
onPlaybackStateChanged
aSTATE_BUFFERING
a causa di un elemento multimediale una transizione.
In alcuni casi, gli ascoltatori potrebbero dover combinare i singoli callback con
callback onEvents
generico, ad esempio per registrare i motivi di modifica degli elementi multimediali
con onMediaItemTransition
, ma agisce solo una volta che è possibile utilizzare tutte le modifiche di stato
insieme in onEvents
.
In uso: AnalyticsListener
Quando utilizzi ExoPlayer
, è possibile registrare AnalyticsListener
con il player
chiamando il numero addAnalyticsListener
. AnalyticsListener
implementazioni sono in grado
per ascoltare eventi dettagliati che possono essere utili per l'analisi e il logging
scopi. Per ulteriori dettagli, consulta la pagina Dati e analisi.
In uso: EventLogger
EventLogger
è un AnalyticsListener
fornito direttamente dalla libreria per
per scopi di logging. Aggiungi EventLogger
a un ExoPlayer
per abilitare dati utili
logging aggiuntivo con un'unica riga:
Kotlin
player.addAnalyticsListener(EventLogger())
Java
player.addAnalyticsListener(new EventLogger());
Per ulteriori dettagli, consulta la pagina di logging del debug.
Attivazione di eventi in posizioni di riproduzione specificate
Alcuni casi d'uso richiedono l'attivazione di eventi in posizioni di riproduzione specifiche. Questo è
supportata tramite PlayerMessage
. È possibile creare un PlayerMessage
utilizzando
ExoPlayer.createMessage
. La posizione di riproduzione in cui deve essere eseguita
può essere impostato utilizzando PlayerMessage.setPosition
. I messaggi vengono eseguiti
la riproduzione del thread per impostazione predefinita, ma puoi personalizzarla utilizzando
PlayerMessage.setLooper
. È possibile usare PlayerMessage.setDeleteAfterDelivery
per controllare se il messaggio verrà eseguito ogni volta che
rilevata nella posizione di riproduzione (può verificarsi più volte a causa della ricerca
e ripetizione) o solo la prima volta. Una volta che PlayerMessage
è
configurato, può essere pianificato utilizzando 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();