Zdarzenia dotyczące odtwarzacza

Nasłuchiwanie zdarzeń odtwarzania

Zdarzenia, takie jak zmiany stanu i błędy odtwarzania, są zgłaszane do zarejestrowanych Player.Listener instancji. Aby zarejestrować detektor i otrzymywać takie wydarzenia:

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);

Metoda Player.Listener ma puste metody domyślne, więc musisz tylko zaimplementować z metod, które Cię interesują. Pełny opis języka Javadoc znajdziesz metod i czas ich wywoływania. Najważniejsze z nich są omówiono szczegółowo poniżej.

Detektory mogą zdecydować, czy stosować wywołania zwrotne poszczególnych zdarzeń, czy ogólne wywołanie zwrotne onEvents, które jest wywoływane po wystąpieniu co najmniej jednego zdarzenia razem. Aby dowiedzieć się, które z nich znajdziesz w artykule Individual callbacks vs onEvents, jest preferowane w różnych przypadkach użycia.

Zmiany stanu odtwarzania

Zmiany stanu odtwarzacza można odbierać po wdrożeniu onPlaybackStateChanged(@State int state) w zarejestrowanym Player.Listener Odtwarzacz może mieć jeden z 4 stanów odtwarzania:

  • Player.STATE_IDLE: stan początkowy, w którym odtwarzacz jest zatrzymuje odtwarzanie, a odtwarzanie się nie powiodło. Odtwarzacz będzie miał tylko ograniczone zasoby w tym stanie.
  • Player.STATE_BUFFERING: gracz nie może od razu rozpocząć odtwarzania ze swojego bieżącej pozycji. Dzieje się tak głównie dlatego, że trzeba wczytać więcej danych.
  • Player.STATE_READY: gracz może od razu rozpocząć odtwarzanie od bieżącego pozycji.
  • Player.STATE_ENDED: odtwarzacz zakończył odtwarzanie wszystkich multimediów.

Oprócz tych stanów gracz ma również flagę playWhenReady, która wskazuje, od intencji użytkownika. Zmiany w tej flagi można otrzymywać po wdrożeniu onPlayWhenReadyChanged(playWhenReady, @PlayWhenReadyChangeReason int reason)

Odtwarzacz jest odtwarzany (czyli jego pozycja przesuwa się w górę, a multimedia są przedstawiane użytkownikowi), gdy są spełnione wszystkie 3 następujące warunki:

  • Odtwarzacz jest w stanie Player.STATE_READY
  • Wydarzenie playWhenReady zacznie się true
  • Odtwarzanie nie zostało wstrzymane z powodu zwróconego przez Player.getPlaybackSuppressionReason

Zamiast sprawdzać te właściwości pojedynczo, Player.isPlaying . Zmiany tego stanu można otrzymywać po wdrożeniu 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.
        }
      }
    });

Błędy odtwarzania

Błędy, które powodują niepowodzenie odtwarzania, mogą być zgłaszane przez onPlayerError(PlaybackException error) w zarejestrowanym Player.Listener W przypadku niepowodzenia wywoływana jest metoda bezpośrednio przed zmianą stanu odtwarzania na Player.STATE_IDLE. Aby spróbować ponownie odtworzyć nieudane lub zatrzymane odtwarzanie, wywołaj ExoPlayer.prepare.

Pamiętaj, że niektóre implementacje Player przekazują wystąpienia podklas PlaybackException w celu podania dodatkowych informacji o błędzie. Dla: na przykład ExoPlayer przekazuje ExoPlaybackException, w którym jest type, rendererIndex i innych pól dotyczących odtwarzacza ExoPlayer.

W przykładzie poniżej pokazujemy, jak wykryć, że odtwarzanie nie powiodło się z powodu błędu Problem z siecią 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.
          }
        }
      }
    });

Przejścia playlisty

Za każdym razem, gdy odtwarzacz zmienia element multimedialny na playliście. Połączenie z numerem onMediaItemTransition(MediaItem mediaItem, @MediaItemTransitionReason int reason) po zarejestrowaniu Player.Listener obiektów. Przyczyna wskazuje, czy było to działanie automatyczne przejście, przewijanie (np. po wywołaniu funkcji player.next()), powtórzenie tego samego elementu lub spowodowane zmianą playlisty (np. jeśli obecnie odtwarzany element zostanie usunięty).

Metadane

Metadane zwrócone z serwera player.getCurrentMediaMetadata() mogą się zmienić ze względu na wiele powodów: przejścia na playlistach, aktualizacji metadanych In-Stream lub aktualizacji obecnie MediaItem w trakcie odtwarzania.

Jeśli interesuje Cię zmiana metadanych, na przykład jeśli chcesz zaktualizować interfejs użytkownika pokazujący bieżący tytuł, możesz posłuchać wykonawcy onMediaMetadataChanged.

Szukam

Wywołanie metod Player.seekTo powoduje serię wywołań zwrotnych do zarejestrowanych. Player.Listener instancja:

  1. onPositionDiscontinuity z: reason=DISCONTINUITY_REASON_SEEK. To jest bezpośredni wynik wywołania funkcji Player.seekTo. Wywołanie zwrotne ma PositionInfo pola pozycji przed przewijaniem i po nim.
  2. onPlaybackStateChanged z natychmiastową zmianą stanu związaną z wyszukiwaniem. Pamiętaj, że takie zmiany mogą nie zostać wprowadzone.

Pojedyncze wywołania zwrotne a onEvents

Słuchacze mogą zdecydować, czy stosować poszczególne wywołania zwrotne, takie jak onIsPlayingChanged(boolean isPlaying) i reklamie ogólnej onEvents(Player player, Events events) oddzwonienie. Ogólne wywołanie zwrotne zapewnia dostęp do obiektu Player i określa zbiór events, które wystąpiły razem. To wywołanie zwrotne jest zawsze wywoływane po wszystkich wywołaniach zwrotnych odpowiadających argumentowi poszczególne zdarzenia.

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);
  }
}

Poszczególne wydarzenia powinny być preferowane w tych przypadkach:

  • Słuchacz jest zainteresowany przyczynami zmian. Na przykład parametr przyczyny podane dla funkcji onPlayWhenReadyChanged lub onMediaItemTransition.
  • Detektor działa tylko na nowych wartościach podanych za pomocą parametrów wywołania zwrotnego lub uruchamia inny element, który nie jest zależny od parametrów wywołania zwrotnego.
  • Implementacja funkcji detektora preferuje jednoznaczne, czytelne wskazanie wywołał zdarzenie w nazwie metody.
  • Odbiornik zgłasza się do systemu analitycznego, który musi wiedzieć o wszystkim, poszczególnych zdarzeń i zmian stanu.

Ogólna kategoria onEvents(Player player, Events events) powinna być preferowana w w następujących przypadkach:

  • Detektor chce aktywować tę samą logikę w przypadku wielu zdarzeń. Dla: na przykład do zaktualizowania UI zarówno w onPlaybackStateChanged, jak i w przeglądarce onPlayWhenReadyChanged
  • Detektor potrzebuje dostępu do obiektu Player, aby aktywować kolejne zdarzenia, np. przewijanie po przejściu elementu multimedialnego.
  • Detektor zamierza używać wielu zgłaszanych wartości stanu za pomocą osobnych wywołań zwrotnych lub w połączeniu z metodą getter Player . Na przykład użycie parametru Player.getCurrentWindowIndex() z parametrem Timeline podano w onTimelineChanged jest bezpieczne tylko z onEvents oddzwonienie.
  • Detektor chce sprawdzić, czy zdarzenia wystąpiły logicznie razem. Dla: przykład, od onPlaybackStateChanged do STATE_BUFFERING ze względu na element multimedialny przejścia.

W niektórych przypadkach detektory mogą być zmuszone do łączenia poszczególnych wywołań zwrotnych z funkcją ogólne wywołanie zwrotne onEvents, na przykład w celu rejestrowania powodów zmiany elementu multimedialnego za pomocą onMediaItemTransition, ale działają tylko wtedy, gdy można użyć wszystkich zmian stanu razem w usłudze onEvents.

Jak korzystać z aplikacji AnalyticsListener

Jeśli używasz funkcji ExoPlayer, w odtwarzaczu można zarejestrować element AnalyticsListener , dzwoniąc pod numer addAnalyticsListener. Implementacje „AnalyticsListener” mogą nasłuchiwanie szczegółowych zdarzeń, które mogą być przydatne do analiz i logowania. w celach informacyjnych. Więcej informacji znajdziesz na stronie statystyk.

Jak korzystać z aplikacji EventLogger

EventLogger to AnalyticsListener dostarczony bezpośrednio przez bibliotekę dla w celach związanych z logowaniem danych. Dodaj EventLogger do ExoPlayer, aby włączyć przydatne funkcje dodatkowe logowanie w jednym wierszu:

Kotlin

player.addAnalyticsListener(EventLogger())

Java

player.addAnalyticsListener(new EventLogger());

Więcej informacji znajdziesz na stronie rejestrowania debugowania.

Uruchamianie zdarzeń w określonych pozycjach odtwarzania

Niektóre przypadki użycia wymagają uruchamiania zdarzeń w określonych pozycjach odtwarzania. To jest obsługiwane przez PlayerMessage. PlayerMessage można utworzyć za pomocą: ExoPlayer.createMessage Pozycja odtwarzania, w której film ma zostać uruchomiony można ustawić za pomocą funkcji PlayerMessage.setPosition. Wiadomości są wykonywane na domyślnie, ale można to dostosować, PlayerMessage.setLooper PlayerMessage.setDeleteAfterDelivery można użyć aby kontrolować, czy komunikat ma być wykonywany za każdym razem, gdy określony pozycja odtwarzania (może się to zdarzać wiele razy z powodu przewijania i powtórzeń) lub tylko za pierwszym razem. Gdy PlayerMessage będzie skonfigurowany, można zaplanować go za pomocą funkcji 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();