Die Playlist API wird durch die Player
-Schnittstelle definiert, die von allen ExoPlayer
-Implementierungen implementiert wird. Playlists ermöglichen die sequenzielle
Wiedergabe mehrerer Medieninhalte. Im folgenden Beispiel wird gezeigt, wie die Wiedergabe einer Playlist mit zwei Videos gestartet wird:
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();
Die Übergänge zwischen den Elementen in einer Playlist sind nahtlos. Es muss nicht dasselbe Format verwendet werden. Eine Playlist kann beispielsweise sowohl H264- als auch VP9-Videos enthalten. Sie können sogar verschiedener Art sein. Das heißt, eine Playlist kann Videos, Bilder und Streams mit reiner Audiowiedergabe enthalten. Du kannst dieselbe MediaItem
innerhalb einer Playlist mehrmals verwenden.
Playlist ändern
Du kannst eine Playlist dynamisch ändern, indem du Medienelemente hinzufügst, verschiebst, entfernst oder ersetzt. Das ist sowohl vor als auch während der Wiedergabe möglich. Rufe dazu die entsprechenden Playlist API-Methoden auf:
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));
Es wird auch unterstützt, die gesamte Playlist zu ersetzen und zu löschen:
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();
Im Player werden Änderungen während der Wiedergabe automatisch richtig verarbeitet:
- Wenn die aktuell wiedergegebene
MediaItem
verschoben wird, wird die Wiedergabe nicht unterbrochen und der neue Nachfolger wird nach dem Ende abgespielt. - Wenn der aktuell wiedergegebene
MediaItem
entfernt wird, spielt der Spieler automatisch den ersten verbleibenden Nachfolger ab. Ist kein Nachfolger vorhanden, wechselt er in den Status „Beendet“. - Wenn das aktuell wiedergegebene
MediaItem
ersetzt wird, wird die Wiedergabe nicht unterbrochen, falls keine der für die Wiedergabe relevanten Eigenschaften inMediaItem
geändert wird. So ist es beispielsweise möglich, dieMediaItem.MediaMetadata
-Felder in den meisten Fällen zu aktualisieren, ohne die Wiedergabe zu beeinträchtigen.
Playlist abfragen
Die Playlist kann mit Player.getMediaItemCount
und Player.getMediaItemAt
abgefragt werden. Das aktuell wiedergegebene Medienelement kann durch Aufrufen von Player.getCurrentMediaItem
abgefragt werden. Es gibt auch andere praktische Methoden wie Player.hasNextMediaItem
oder Player.getNextMediaItemIndex
, um die Navigation in der Playlist zu vereinfachen.
Wiederholungsmodi
Der Player unterstützt drei Wiederholungsmodi, die jederzeit mit Player.setRepeatMode
festgelegt werden können:
Player.REPEAT_MODE_OFF
: Die Playlist wird nicht wiederholt und der Player wechselt zuPlayer.STATE_ENDED
, sobald der letzte Titel in der Playlist abgespielt wurde.Player.REPEAT_MODE_ONE
: Das aktuelle Element wird in einer Endlosschleife wiederholt. Methoden wiePlayer.seekToNextMediaItem
ignorieren dies und springen zum nächsten Element in der Liste, das dann in einer Endlosschleife wiederholt wird.Player.REPEAT_MODE_ALL
: Die gesamte Playlist wird in einer Endlosschleife wiederholt.
Zufallsmix
Der Shuffle-Modus kann jederzeit mit Player.setShuffleModeEnabled
aktiviert oder deaktiviert werden. Im Zufallsmix spielt der Player die Playlist in einer vorausberechneten, zufälligen Reihenfolge ab. Alle Elemente werden einmal abgespielt und der Zufallsmix kann auch mit Player.REPEAT_MODE_ALL
kombiniert werden, um dieselbe zufällige Reihenfolge in einer Endlosschleife zu wiederholen. Wenn der Zufallsmix deaktiviert ist, wird die Wiedergabe ab dem aktuellen Element an seiner ursprünglichen Position in der Playlist fortgesetzt.
Die Indizes, die von Methoden wie Player.getCurrentMediaItemIndex
zurückgegeben werden, beziehen sich immer auf die ursprüngliche, nicht zufällige Reihenfolge. Wenn du Player.seekToNextMediaItem
drückst, wird nicht das Element an player.getCurrentMediaItemIndex() + 1
abgespielt, sondern das nächste Element gemäß der Zufallsmixreihenfolge. Wenn du neue Elemente in die Playlist einfügst oder Elemente entfernst, bleibt die vorhandene Zufallsmix-Reihenfolge nach Möglichkeit unverändert.
Benutzerdefinierte Zufallsmixreihenfolge festlegen
Standardmäßig unterstützt der Player das Zufallsmixen mit der Taste DefaultShuffleOrder
.
Das kann angepasst werden, indem eine benutzerdefinierte Zufallsmixreihenfolge implementiert oder eine benutzerdefinierte Reihenfolge im Konstruktor von DefaultShuffleOrder
festgelegt wird:
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);
Playlist-Elemente identifizieren
Um Playlist-Elemente zu identifizieren, kann MediaItem.mediaId
beim Erstellen des Elements festgelegt werden:
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();
Wenn eine App keine Medien-ID für ein Medienelement explizit definiert, wird die Stringdarstellung des URI verwendet.
App-Daten mit Playlist-Elementen verknüpfen
Neben einer ID kann jedes Medienelement auch mit einem benutzerdefinierten Tag konfiguriert werden. Das kann jedes von der App bereitgestellte Objekt sein. Eine Verwendung von benutzerdefinierten Tags besteht darin, jedem Medienelement Metadaten hinzuzufügen:
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();
Erkennen, wenn die Wiedergabe zu einem anderen Medienelement wechselt
Wenn die Wiedergabe zu einem anderen Medienelement wechselt oder dasselbe Medienelement wiederholt wird, wird Listener.onMediaItemTransition(MediaItem,
@MediaItemTransitionReason)
aufgerufen. Dieser Callback empfängt das neue Medienelement zusammen mit einem @MediaItemTransitionReason
, das angibt, warum der Übergang aufgetreten ist. Ein häufiger Anwendungsfall für onMediaItemTransition
ist das Aktualisieren der Benutzeroberfläche der App für das neue Medienelement:
Kotlin
override fun onMediaItemTransition( mediaItem: MediaItem?, @MediaItemTransitionReason reason: Int, ) { updateUiForPlayingMediaItem(mediaItem) }
Java
@Override public void onMediaItemTransition( @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) { updateUiForPlayingMediaItem(mediaItem); }
Wenn die zum Aktualisieren der Benutzeroberfläche erforderlichen Metadaten mithilfe benutzerdefinierter Tags an jedes Medienelement angehängt werden, könnte eine Implementierung so aussehen:
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); }
Erkennen, wenn sich die Playlist ändert
Wenn ein Medienelement hinzugefügt, entfernt oder verschoben wird, wird Listener.onTimelineChanged(Timeline, @TimelineChangeReason)
sofort mit TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED
aufgerufen. Dieser Callback wird auch dann aufgerufen, wenn der Player noch nicht vorbereitet wurde.
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); } }
Wenn Informationen wie die Dauer eines Medienelements in der Playlist verfügbar sind, wird Timeline
aktualisiert und onTimelineChanged
mit TIMELINE_CHANGE_REASON_SOURCE_UPDATE
aufgerufen. Weitere Gründe, die zu einer Aktualisierung der Zeitachse führen können, sind:
- Ein Manifest, das nach der Vorbereitung eines adaptiven Medienelements verfügbar wird.
- Ein Manifest, das während der Wiedergabe eines Livestreams regelmäßig aktualisiert wird.