Interfejs API playlisty jest zdefiniowany przez interfejs Player, który jest implementowany przez wszystkie implementacje ExoPlayer. Playlisty umożliwiają sekwencyjne odtwarzanie wielu elementów multimedialnych. Poniższy przykład pokazuje, 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 na playliście są płynne. Nie ma wymogu, aby były one w tym samym formacie (np. na playliście mogą znajdować się filmy w formatach H264 i VP9). Mogą one nawet być różnych typów (czyli lista odtwarzania może zawierać filmy, obrazy i strumienie tylko audio). Możesz użyć tego samego MediaItem wiele razy na jednej playliście.
Modyfikowanie playlisty
Możesz dynamicznie modyfikować playlistę, dodając, przenosząc, usuwając lub zastępując elementy multimedialne. Możesz to zrobić przed odtwarzaniem i w jego trakcie, 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));
Obsługiwane jest też zastępowanie i czyszczenie całej playlisty:
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 obsługuje modyfikacje podczas odtwarzania w odpowiedni sposób:
- Jeśli aktualnie odtwarzany
MediaItemzostanie przeniesiony, odtwarzanie nie zostanie przerwane, a po jego zakończeniu zostanie odtworzony nowy następca. - Jeśli aktualnie odtwarzany element
MediaItemzostanie usunięty, odtwarzacz automatycznie odtworzy pierwszy pozostały element następny lub przejdzie do stanu zakończonego, jeśli nie ma takiego elementu. - Jeśli aktualnie odtwarzany element
MediaItemzostanie zastąpiony, odtwarzanie nie zostanie przerwane, o ile żadna z właściwości w elemencieMediaItemistotna dla odtwarzania nie ulegnie zmianie. Na przykład w większości przypadków można zaktualizowaćMediaItem.MediaMetadatapola bez wpływu na odtwarzanie.
Wysyłanie zapytań dotyczących playlisty
O playlistę można wysłać zapytanie za pomocą parametrów Player.getMediaItemCount i Player.getMediaItemAt. Obecnie odtwarzany element multimedialny można sprawdzić, wywołując funkcję Player.getCurrentMediaItem. Dostępne są też inne wygodne metody, takie jak Player.hasNextMediaItem lub Player.getNextMediaItemIndex, które ułatwiają poruszanie się po playliście.
Tryby powtarzania
Odtwarzacz obsługuje 3 tryby powtarzania, które można ustawić w dowolnym momencie za pomocą przyciskuPlayer.setRepeatMode:
Player.REPEAT_MODE_OFF: playlista nie jest powtarzana, a odtwarzacz przejdzie do stanuPlayer.STATE_ENDEDpo odtworzeniu ostatniego elementu na playliście.Player.REPEAT_MODE_ONE: bieżący element jest powtarzany w nieskończonej pętli. Metody takie jakPlayer.seekToNextMediaItemzignorują to i przejdą do następnego elementu na liście, który będzie powtarzany w nieskończonej pętli.Player.REPEAT_MODE_ALL: cała playlista jest powtarzana w nieskończonej pętli.
Tryb odtwarzania losowego
Tryb odtwarzania losowego można włączyć lub wyłączyć w dowolnym momencie za pomocą ikony Player.setShuffleModeEnabled. W trybie losowym odtwarzacz będzie odtwarzać playlistę w losowej kolejności. Wszystkie elementy zostaną odtworzone raz. Tryb losowy można też połączyć z Player.REPEAT_MODE_ALL, aby powtarzać tę samą losową kolejność w nieskończonej pętli. Gdy tryb losowego odtwarzania jest wyłączony, odtwarzanie jest kontynuowane od bieżącego elementu w jego pierwotnym miejscu na playliście.
Pamiętaj, że indeksy zwracane przez metody takie jak
Player.getCurrentMediaItemIndex zawsze odnoszą się do oryginalnej, nieprzemieszanej kolejności. Podobnie Player.seekToNextMediaItem nie odtworzy elementu w pozycji player.getCurrentMediaItemIndex() + 1, ale następny element zgodnie z kolejnością odtwarzania losowego. Wstawianie nowych elementów do playlisty lub usuwanie z niej elementów w miarę możliwości nie zmienia dotychczasowej kolejności losowej.
Ustawianie niestandardowej kolejności losowej
Domyślnie odtwarzacz obsługuje losowe odtwarzanie za pomocą ikony DefaultShuffleOrder.
Możesz to dostosować, podając niestandardową implementację kolejności losowej 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ć parametr 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 zdefiniuje jawnie identyfikatora multimediów dla elementu multimedialnego, użyty zostanie ciąg znaków reprezentujący URI.
Powiązywanie danych aplikacji z elementami playlisty
Oprócz identyfikatora każdy element multimedialny można też skonfigurować za pomocą niestandardowego tagu, który może być dowolnym obiektem dostarczonym przez aplikację. Jednym z zastosowań tagów niestandardowych jest 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 odtwarzania do innego elementu multimedialnego
Gdy odtwarzanie przechodzi do innego elementu multimedialnego lub zaczyna powtarzać ten sam element, wywoływana jest funkcja Listener.onMediaItemTransition(MediaItem,
@MediaItemTransitionReason). Funkcja zwrotna otrzymuje nowy element multimedialny wraz z wartością @MediaItemTransitionReason wskazującą przyczynę przejścia. Częstym przypadkiem użycia onMediaItemTransition jest aktualizowanie 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 zaktualizowania 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
Gdy element multimedialny zostanie dodany, usunięty lub przeniesiony, wywoływana jest funkcja
Listener.onTimelineChanged(Timeline, @TimelineChangeReason) z parametrem TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED. To wywołanie zwrotne jest 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 dostępne staną się informacje takie jak czas trwania elementu multimedialnego na playliście, Timeline zostanie zaktualizowany, a onTimelineChanged zostanie wywołany z parametrem TIMELINE_CHANGE_REASON_SOURCE_UPDATE. Inne przyczyny aktualizacji osi czasu:
- Plik manifestu staje się dostępny po przygotowaniu adaptacyjnego elementu multimedialnego.
- Plik manifestu jest okresowo aktualizowany podczas odtwarzania transmisji na żywo.