Auf Wiedergabeereignisse warten
Ereignisse wie Statusänderungen und Wiedergabefehler werden an registrierte Player.Listener-Instanzen gemeldet. So registrieren Sie einen Listener, der solche Ereignisse empfängt:
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 hat leere Standardmethoden. Sie müssen also nur die Methoden implementieren, die Sie interessieren. Eine vollständige Beschreibung der Methoden und der Zeitpunkte, zu denen sie aufgerufen werden, finden Sie im Javadoc. Einige der wichtigsten Methoden werden im Folgenden genauer beschrieben.
Listener haben die Wahl zwischen der Implementierung einzelner Event-Callbacks oder eines generischen onEvents-Callbacks, der nach dem gemeinsamen Auftreten eines oder mehrerer Events aufgerufen wird. Informationen dazu, welche für verschiedene Anwendungsfälle bevorzugt werden sollten, finden Sie unter Individual callbacks vs onEvents.
Änderungen des Wiedergabestatus
Änderungen am Player-Status können empfangen werden, indem Sie onPlaybackStateChanged(@State int state) in einem registrierten Player.Listener implementieren.
Der Player kann sich in einem von vier Wiedergabestatus befinden:
Player.STATE_IDLE: Dies ist der Ausgangsstatus, der Status, wenn der Player gestoppt ist und wenn die Wiedergabe fehlgeschlagen ist. Der Player hat in diesem Zustand nur begrenzte Ressourcen.Player.STATE_BUFFERING: Der Player kann nicht sofort von der aktuellen Position aus wiedergeben. Das liegt meistens daran, dass mehr Daten geladen werden müssen.Player.STATE_READY: Der Player kann sofort von seiner aktuellen Position aus wiedergeben.Player.STATE_ENDED: Der Player hat die Wiedergabe aller Medien abgeschlossen.
Zusätzlich zu diesen Status hat der Player das Flag playWhenReady, um die Absicht des Nutzers anzugeben, das Video abzuspielen. Änderungen an diesem Flag können durch die Implementierung von onPlayWhenReadyChanged(playWhenReady, @PlayWhenReadyChangeReason int reason) empfangen werden.
Ein Player wird wiedergegeben (d. h. seine Position wird vorangetrieben und dem Nutzer werden Media präsentiert), wenn alle drei der folgenden Bedingungen erfüllt sind:
- Der Player befindet sich im Status
Player.STATE_READY. playWhenReadyisttrue- Die Wiedergabe wird nicht aus einem Grund unterdrückt, der von
Player.getPlaybackSuppressionReasonzurückgegeben wird.
Anstatt diese Eigenschaften einzeln prüfen zu müssen, kann Player.isPlaying aufgerufen werden. Änderungen an diesem Status können durch die Implementierung von onIsPlayingChanged(boolean isPlaying) empfangen werden:
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. } } });
Wiedergabefehler
Fehler, die dazu führen, dass die Wiedergabe fehlschlägt, können durch die Implementierung von onPlayerError(PlaybackException error) in einem registrierten Player.Listener empfangen werden. Wenn ein Fehler auftritt, wird diese Methode unmittelbar vor dem Übergang des Wiedergabestatus zu Player.STATE_IDLE aufgerufen. Fehlgeschlagene oder angehaltene Wiedergaben können durch Aufrufen von ExoPlayer.prepare wiederholt werden.
Bei einigen Player-Implementierungen werden Instanzen von Unterklassen von PlaybackException übergeben, um zusätzliche Informationen zum Fehler zu liefern. Beispiel: ExoPlayer wird an ExoPlaybackException übergeben, das type, rendererIndex und andere ExoPlayer-spezifische Felder enthält.
Das folgende Beispiel zeigt, wie Sie erkennen, wenn eine Wiedergabe aufgrund eines HTTP-Netzwerkproblems fehlgeschlagen ist:
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. } } } });
Playlist-Übergänge
Immer wenn der Player zu einem neuen Media-Element in der Playlist wechselt, wird onMediaItemTransition(MediaItem mediaItem, @MediaItemTransitionReason int
reason) für registrierte Player.Listener-Objekte aufgerufen. Der Grund gibt an, ob es sich um einen automatischen Übergang, einen Seek (z. B. nach dem Aufrufen von player.next()), eine Wiederholung desselben Elements oder eine Änderung der Playlist handelt (z. B. wenn das aktuell wiedergegebene Element entfernt wird).
Metadaten
Die von player.getCurrentMediaMetadata() zurückgegebenen Metadaten können aus vielen Gründen geändert werden, z. B. durch Playlist-Übergänge, In-Stream-Metadatenaktualisierungen oder durch Aktualisieren der aktuellen MediaItem während der Wiedergabe.
Wenn Sie an Änderungen von Metadaten interessiert sind, z. B. um eine Benutzeroberfläche zu aktualisieren, auf der der aktuelle Titel angezeigt wird, können Sie auf onMediaMetadataChanged warten.
Springen zu Videopositionen aktiviert
Das Aufrufen von Player.seekTo-Methoden führt zu einer Reihe von Rückrufen an registrierte Player.Listener-Instanzen:
onPositionDiscontinuitymitreason=DISCONTINUITY_REASON_SEEK. Dies ist das direkte Ergebnis des Aufrufs vonPlayer.seekTo. Der Callback hatPositionInfo-Felder für die Position vor und nach dem Seek.onPlaybackStateChangedmit allen sofortigen Statusänderungen im Zusammenhang mit dem Suchvorgang. Möglicherweise gibt es keine solche Änderung.
Einzelne Callbacks im Vergleich zu onEvents
Hörer können zwischen der Implementierung einzelner Callbacks wie onIsPlayingChanged(boolean isPlaying) und dem generischen Callback onEvents(Player
player, Events events) wählen. Der generische Callback bietet Zugriff auf das Player-Objekt und gibt die Menge der events an, die zusammen aufgetreten sind. Dieser Callback wird immer nach den Callbacks aufgerufen, die den einzelnen Ereignissen entsprechen.
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); } }
Einzelne Ereignisse sollten in den folgenden Fällen bevorzugt werden:
- Der Zuhörer interessiert sich für die Gründe für die Änderungen. Beispiel: Die Gründe für
onPlayWhenReadyChangedoderonMediaItemTransition. - Der Listener reagiert nur auf die neuen Werte, die über Callback-Parameter bereitgestellt werden, oder löst etwas anderes aus, das nicht von den Callback-Parametern abhängt.
- Bei der Listener-Implementierung wird eine klare, lesbare Angabe dessen bevorzugt, was das Ereignis ausgelöst hat.
- Der Listener meldet sich bei einem Analysesystem, das über alle einzelnen Ereignisse und Statusänderungen informiert werden muss.
Die generische onEvents(Player player, Events events) sollte in den folgenden Fällen bevorzugt werden:
- Der Listener soll dieselbe Logik für mehrere Ereignisse auslösen. Beispiel: Aktualisieren einer Benutzeroberfläche für
onPlaybackStateChangedundonPlayWhenReadyChanged. - Der Listener muss auf das
Player-Objekt zugreifen, um weitere Ereignisse auszulösen, z. B. das Suchen nach einem Übergang zwischen Media-Elementen. - Der Listener möchte mehrere Statuswerte verwenden, die über separate Callbacks gemeldet werden, oder in Kombination mit
Player-Getter-Methoden. Die Verwendung vonPlayer.getCurrentWindowIndex()mit dem inonTimelineChangedbereitgestelltenTimelineist beispielsweise nur innerhalb desonEvents-Callbacks sicher. - Der Listener ist daran interessiert, ob Ereignisse logisch zusammen aufgetreten sind.
Beispiel:
onPlaybackStateChangedwird aufgrund eines Übergangs des Media-Elements zuSTATE_BUFFERING.
In einigen Fällen müssen Zuhörer die einzelnen Callbacks mit dem generischen onEvents-Callback kombinieren, um beispielsweise Gründe für Änderungen an Medienelementen mit onMediaItemTransition aufzuzeichnen, aber erst zu reagieren, wenn alle Statusänderungen zusammen in onEvents verwendet werden können.
AnalyticsListener verwenden
Wenn Sie ExoPlayer verwenden, kann ein AnalyticsListener beim Player registriert werden, indem Sie addAnalyticsListener aufrufen. AnalyticsListener-Implementierungen können auf detaillierte Ereignisse warten, die für Analyse- und Protokollierungszwecke nützlich sein können. Weitere Informationen finden Sie auf der Analyseseite.
EventLogger verwenden
EventLogger ist ein AnalyticsListener, das direkt von der Bibliothek für Protokollierungszwecke bereitgestellt wird. Fügen Sie EventLogger einem ExoPlayer hinzu, um mit einer einzigen Zeile nützliche zusätzliche Protokollierung zu aktivieren:
Kotlin
player.addAnalyticsListener(EventLogger())
Java
player.addAnalyticsListener(new EventLogger());
Weitere Informationen finden Sie auf der Seite zum Debug-Logging.
Ereignisse an bestimmten Wiedergabepositionen auslösen
In einigen Anwendungsfällen müssen Ereignisse an bestimmten Wiedergabepositionen ausgelöst werden. Dies wird mit PlayerMessage unterstützt. Ein PlayerMessage kann mit ExoPlayer.createMessage erstellt werden. Die Wiedergabeposition, an der sie ausgeführt werden soll, kann mit PlayerMessage.setPosition festgelegt werden. Nachrichten werden standardmäßig im Wiedergabethread ausgeführt. Dies kann jedoch mit PlayerMessage.setLooper angepasst werden. Mit PlayerMessage.setDeleteAfterDelivery können Sie festlegen, ob die Nachricht jedes Mal ausgeführt wird, wenn die angegebene Wiedergabeposition erreicht wird (dies kann aufgrund von Such- und Wiederholungsmodi mehrmals geschehen), oder nur beim ersten Mal. Nachdem die PlayerMessage konfiguriert wurde, kann sie mit PlayerMessage.send geplant werden.
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();