Die Playlist API wird von der Player
-Schnittstelle definiert, die durch alle ExoPlayer
-Implementierungen implementiert wird. Playlists ermöglichen die sequentielle
Wiedergabe mehrerer Medienelemente. Das folgende Beispiel zeigt, 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 ist nicht erforderlich, dass sie dasselbe Format haben. Zum Beispiel kann eine Playlist sowohl H264- als auch VP9-Videos enthalten. Sie können sogar unterschiedliche Typen haben. Das heißt, eine Playlist kann sowohl Video- als auch reine Audiostreams enthalten. Du kannst dasselbe MediaItem
-Element in einer Playlist mehrmals verwenden.
Playlist ändern
Du kannst eine Playlist dynamisch ändern, indem du Medienelemente hinzufügst, verschiebst, entfernst oder ersetzt. Dies kann sowohl vor als auch während der Wiedergabe durch Aufrufen der entsprechenden Playlist API-Methoden erfolgen:
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));
Das Ersetzen und Löschen der gesamten Playlist wird ebenfalls unterstützt:
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();
Änderungen werden während der Wiedergabe automatisch richtig verarbeitet:
- Wenn die aktuell wiedergegebene
MediaItem
verschoben wird, wird die Wiedergabe nicht unterbrochen und nach Abschluss wird der neue Nachfolger abgespielt. - Wenn die aktuell wiedergegebene
MediaItem
entfernt wird, spielt der Player automatisch den ersten verbleibenden Nachfolger wieder oder wechselt in den Status „Beendet“, wenn kein solcher Nachfolger vorhanden ist. - Wird die aktuell wiedergegebene
MediaItem
ersetzt, wird die Wiedergabe nicht unterbrochen, wenn sich keines der für die Wiedergabe relevanten Attribute imMediaItem
ändert. Beispielsweise ist es in den meisten Fällen möglich, dieMediaItem.MediaMetadata
-Felder 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
eingestellt werden können:
Player.REPEAT_MODE_OFF
: Die Playlist wird nicht wiederholt und der Player wechselt zuPlayer.STATE_ENDED
, sobald das letzte Element der Playlist wiedergegeben wurde.Player.REPEAT_MODE_ONE
: Das aktuelle Element wird in einer Endlosschleife wiederholt. Methoden wiePlayer.seekToNextMediaItem
ignorieren dies und suchen 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 Zufallsmix 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. 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 von Methoden wie Player.getCurrentMediaItemIndex
zurückgegebenen Indexe beziehen sich immer auf die ursprüngliche, nicht nach dem Zufallsprinzip angeordnete Reihenfolge. Ebenso gibt Player.seekToNextMediaItem
das Element nicht bei player.getCurrentMediaItemIndex() + 1
wieder, sondern das nächste Element gemäß der Shuffle-Reihenfolge. Wenn du neue Elemente in die Playlist einfügst oder Elemente entfernst, bleibt die vorhandene Zufallsreihenfolge so weit wie möglich unverändert.
Benutzerdefinierte Shuffle-Reihenfolge festlegen
Standardmäßig unterstützt der Player die Zufallswiedergabe mithilfe von DefaultShuffleOrder
.
Dies kann angepasst werden, indem eine benutzerdefinierte Implementierung der Shuffle-Reihenfolge angegeben oder eine benutzerdefinierte Reihenfolge im DefaultShuffleOrder
-Konstruktor 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
Zur Identifizierung von Playlist-Elementen kann beim Erstellen des Elements MediaItem.mediaId
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 in einer App keine Medien-ID für ein Medienelement explizit definiert wird, wird die Stringdarstellung des URI verwendet.
App-Daten mit Playlist-Elementen verknüpfen
Zusätzlich zu einer ID kann jedes Medienelement auch mit einem benutzerdefinierten Tag konfiguriert werden, bei dem es sich um ein beliebiges von der App bereitgestelltes Objekt handeln kann. Mit benutzerdefinierten Tags können Sie z. B. Metadaten an jedes Medienelement anhängen:
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 bei der Wiedergabe zu einem anderen Medienelement gewechselt wird
Wenn die Wiedergabe zu einem anderen Medienelement überspringt oder wiederholt dasselbe Medienelement wiederholt, wird Listener.onMediaItemTransition(MediaItem,
@MediaItemTransitionReason)
aufgerufen. Dieser Callback empfängt das neue Medienelement zusammen mit einem @MediaItemTransitionReason
, der angibt, warum der Übergang stattgefunden hat. Ein häufiger Anwendungsfall für onMediaItemTransition
ist die Aktualisierung der App-UI 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 UI erforderlichen Metadaten mithilfe von benutzerdefinierten 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); }
Änderungen der Playlist erkennen
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 für eine Aktualisierung des Zeitplans sind:
- Manifest, das nach der Vorbereitung eines adaptiven Medienelements verfügbar wird
- Ein Manifest, das während der Wiedergabe eines Livestreams regelmäßig aktualisiert wird.