Interfejs API playlisty jest definiowany przez interfejs Player
, który jest zaimplementowany przez wszystkie implementacje ExoPlayer
. Playlisty umożliwiają sekwencyjne odtwarzanie
wielu elementów multimedialnych. Z przykładu poniżej dowiesz się, jak rozpocząć odtwarzanie playlisty zawierającej 2 filmy:
Kotlin
// Build the media items. val firstItem = MediaItem.fromUri(firstVideoUri) val secondItem = MediaItem.fromUri(secondVideoUri) // Add the media items to be played. player.addMediaItem(firstItem) player.addMediaItem(secondItem) // Prepare the player. player.prepare() // Start the playback. player.play()
Java
// Build the media items. MediaItem firstItem = MediaItem.fromUri(firstVideoUri); MediaItem secondItem = MediaItem.fromUri(secondVideoUri); // Add the media items to be played. player.addMediaItem(firstItem); player.addMediaItem(secondItem); // Prepare the player. player.prepare(); // Start the playback. player.play();
Przejścia między elementami playlisty są płynne. Nie ma wymogu, by były w tym samym formacie (na przykład playlista może zawierać zarówno filmy H264, jak i VP9). Mogą one być różne (tzn. playlista może zawierać zarówno strumienie wideo, jak i audio). Tego samego elementu MediaItem
możesz użyć kilka razy w ramach playlisty.
Modyfikowanie playlisty
Możesz dynamicznie modyfikować playlistę przez dodawanie, przenoszenie, usuwanie lub zastępowanie elementów multimedialnych. Można to zrobić zarówno przed odtwarzaniem, jak i w trakcie odtwarzania, wywołując odpowiednie metody interfejsu API playlisty:
Kotlin
// Adds a media item at position 1 in the playlist. player.addMediaItem(/* index= */ 1, MediaItem.fromUri(thirdUri)) // Moves the third media item from position 2 to the start of the playlist. player.moveMediaItem(/* currentIndex= */ 2, /* newIndex= */ 0) // Removes the first item from the playlist. player.removeMediaItem(/* index= */ 0) // Replace the second item in the playlist. player.replaceMediaItem(/* index= */ 1, MediaItem.fromUri(newUri))
Java
// Adds a media item at position 1 in the playlist. player.addMediaItem(/* index= */ 1, MediaItem.fromUri(thirdUri)); // Moves the third media item from position 2 to the start of the playlist. player.moveMediaItem(/* currentIndex= */ 2, /* newIndex= */ 0); // Removes the first item from the playlist. player.removeMediaItem(/* index= */ 0); // Replace the second item in the playlist. player.replaceMediaItem(/* index= */ 1, MediaItem.fromUri(newUri));
Możesz też zastępować i usuwać całą playlistę:
Kotlin
// Replaces the playlist with a new one. val newItems: List<MediaItem> = listOf(MediaItem.fromUri(fourthUri), MediaItem.fromUri(fifthUri)) player.setMediaItems(newItems, /* resetPosition= */ true) // Clears the playlist. If prepared, the player transitions to the ended state. player.clearMediaItems()
Java
// Replaces the playlist with a new one. ImmutableList<MediaItem> newItems = ImmutableList.of(MediaItem.fromUri(fourthUri), MediaItem.fromUri(fifthUri)); player.setMediaItems(newItems, /* resetPosition= */ true); // Clears the playlist. If prepared, the player transitions to the ended state. player.clearMediaItems();
Odtwarzacz automatycznie wprowadza zmiany podczas odtwarzania:
- Jeśli aktualnie odtwarzany utwór
MediaItem
zostanie przeniesiony, odtwarzanie nie zostanie przerwane i po zakończeniu zostanie odtworzony jego nowy następca. - Jeśli element
MediaItem
, który obecnie jest odtwarzany, zostanie usunięty, odtwarzacz automatycznie rozpocznie odtwarzanie pierwszej pozostałej części następcy, a jeśli nie ma następcy – przejdzie do stanu zakończenia odtwarzania. - Jeśli obecnie odtwarzany element
MediaItem
zostanie zastąpiony, odtwarzanie nie zostanie przerwane, jeśli żadna z właściwościMediaItem
, które go dotyczą, nie ulegnie zmianie. W większości przypadków można na przykład zaktualizować polaMediaItem.MediaMetadata
, nie wpływając na odtwarzanie.
Zapytanie dotyczące playlisty
Zapytanie o playlistę można wysłać za pomocą parametrów Player.getMediaItemCount
i Player.getMediaItemAt
. Można przesłać zapytanie o odtwarzany obecnie element multimedialny, wywołując metodę Player.getCurrentMediaItem
. Istnieją też inne, wygodne metody, takie jak Player.hasNextMediaItem
czy Player.getNextMediaItemIndex
, które upraszczają nawigację po playliście.
Tryby powtarzania
Odtwarzacz obsługuje 3 tryby powtarzania, które można ustawić w każdej chwili w Player.setRepeatMode
:
Player.REPEAT_MODE_OFF
: playlista nie jest powtarzana i po odtworzeniu ostatniego elementu na playliście odtwarzacz zostanie przeniesiony do trybuPlayer.STATE_ENDED
.Player.REPEAT_MODE_ONE
: bieżący element powtarza się w niekończącej się pętli. Metody takie jakPlayer.seekToNextMediaItem
zignorują tę wiadomość i przeprowadzą do następnego elementu na liście, który będzie powtarzany w niekończącej się pętli.Player.REPEAT_MODE_ALL
: cała playlista powtarza się w niekończącej się pętli.
Tryb tasowania
Tryb tasowania możesz w każdej chwili włączyć lub wyłączyć w Player.setShuffleModeEnabled
. W trybie losowym odtwarzacz odtwarza playlistę w wstępnie ustalonej, losowej kolejności. Wszystkie elementy zostaną odtworzone raz. Tryb tasowania można też połączyć z funkcją Player.REPEAT_MODE_ALL
, aby w nieskończonej pętli powtarzać tę samą kolejność losową. Gdy tryb odtwarzania losowego jest wyłączony, odtwarzanie bieżącego elementu jest kontynuowane na jego pierwotnej pozycji na playliście.
Pamiętaj, że indeksy zwracane przez metody takie jak Player.getCurrentMediaItemIndex
zawsze odwołują się do pierwotnej kolejności bez kolejności. Analogicznie Player.seekToNextMediaItem
nie odtworzy elementu pod adresem player.getCurrentMediaItemIndex() + 1
, ale jako następny zgodnie z kolejnością losową. Wstawianie nowych elementów do playlisty lub usuwanie elementów sprawi, że dotychczasowa kolejność odtwarzania nie ulegnie zmianie.
Ustawianie niestandardowej kolejności losowej
Domyślnie odtwarzacz obsługuje tasowanie za pomocą komponentu DefaultShuffleOrder
.
Można to dostosować, stosując implementację niestandardowej kolejności tasowania lub ustawiając niestandardową kolejność w konstruktorze DefaultShuffleOrder
:
Kotlin
// Set a custom shuffle order for the 5 items currently in the playlist: exoPlayer.setShuffleOrder(DefaultShuffleOrder(intArrayOf(3, 1, 0, 4, 2), randomSeed)) // Enable shuffle mode. exoPlayer.shuffleModeEnabled = true
Java
// Set a custom shuffle order for the 5 items currently in the playlist: exoPlayer.setShuffleOrder(new DefaultShuffleOrder(new int[] {3, 1, 0, 4, 2}, randomSeed)); // Enable shuffle mode. exoPlayer.setShuffleModeEnabled(/* shuffleModeEnabled= */ true);
Identyfikowanie elementów playlisty
Aby zidentyfikować elementy playlisty, podczas tworzenia elementu można ustawić MediaItem.mediaId
:
Kotlin
// Build a media item with a media ID. val mediaItem = MediaItem.Builder().setUri(uri).setMediaId(mediaId).build()
Java
// Build a media item with a media ID. MediaItem mediaItem = new MediaItem.Builder().setUri(uri).setMediaId(mediaId).build();
Jeśli aplikacja nie określa wyraźnie identyfikatora multimediów dla elementu multimedialnego, używany jest ciąg reprezentujący identyfikator URI.
Powiązanie danych aplikacji z elementami playlist
Oprócz identyfikatora każdy element multimedialny można skonfigurować za pomocą tagu niestandardowego, który może być dowolnym obiektem dostarczanym przez aplikację. Niestandardowe tagi to na przykład dołączanie metadanych do każdego elementu multimedialnego:
Kotlin
// Build a media item with a custom tag. val mediaItem = MediaItem.Builder().setUri(uri).setTag(metadata).build()
Java
// Build a media item with a custom tag. MediaItem mediaItem = new MediaItem.Builder().setUri(uri).setTag(metadata).build();
Wykrywanie przejścia do innego elementu multimedialnego
Gdy odtwarzanie przechodzi do innego elementu multimedialnego lub rozpoczyna powtarzanie tego samego elementu, wywoływane jest polecenie Listener.onMediaItemTransition(MediaItem,
@MediaItemTransitionReason)
. To wywołanie zwrotne odbiera nowy element multimedialny z identyfikatorem @MediaItemTransitionReason
wskazującym powód przeniesienia. Typowym przypadkiem użycia onMediaItemTransition
jest zaktualizowanie interfejsu aplikacji pod kątem nowego elementu multimedialnego:
Kotlin
override fun onMediaItemTransition( mediaItem: MediaItem?, @MediaItemTransitionReason reason: Int, ) { updateUiForPlayingMediaItem(mediaItem) }
Java
@Override public void onMediaItemTransition( @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) { updateUiForPlayingMediaItem(mediaItem); }
Jeśli metadane wymagane do aktualizacji interfejsu są dołączone do każdego elementu multimedialnego za pomocą tagów niestandardowych, implementacja może wyglądać tak:
Kotlin
override fun onMediaItemTransition( mediaItem: MediaItem?, @MediaItemTransitionReason reason: Int, ) { var metadata: CustomMetadata? = null mediaItem?.localConfiguration?.let { localConfiguration -> metadata = localConfiguration.tag as? CustomMetadata } updateUiForPlayingMediaItem(metadata) }
Java
@Override public void onMediaItemTransition( @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) { @Nullable CustomMetadata metadata = null; if (mediaItem != null && mediaItem.localConfiguration != null) { metadata = (CustomMetadata) mediaItem.localConfiguration.tag; } updateUiForPlayingMediaItem(metadata); }
Wykrywanie zmian na playliście
Po dodaniu, usunięciu lub przeniesieniu elementu multimedialnego Listener.onTimelineChanged(Timeline, @TimelineChangeReason)
jest natychmiast wywoływany za pomocą funkcji TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED
. Jest ono wywoływane nawet wtedy, gdy odtwarzacz nie został jeszcze przygotowany.
Kotlin
override fun onTimelineChanged(timeline: Timeline, @TimelineChangeReason reason: Int) { if (reason == Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED) { // Update the UI according to the modified playlist (add, move or remove). updateUiForPlaylist(timeline) } }
Java
@Override public void onTimelineChanged(Timeline timeline, @TimelineChangeReason int reason) { if (reason == TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED) { // Update the UI according to the modified playlist (add, move or remove). updateUiForPlaylist(timeline); } }
Gdy informacje takie jak czas trwania elementu multimedialnego na playliście staną się dostępne, parametr Timeline
zostanie zaktualizowany, a pole onTimelineChanged
zostanie wywoływane z wartością TIMELINE_CHANGE_REASON_SOURCE_UPDATE
. Inne przyczyny aktualizacji osi czasu:
- Plik manifestu pojawia się po przygotowaniu adaptacyjnego elementu multimedialnego.
- Plik manifestu jest okresowo aktualizowany podczas odtwarzania transmisji na żywo.