Die Playlist API wird durch die Player-Schnittstelle definiert, die von allen ExoPlayer-Implementierungen implementiert wird. Playlists ermöglichen die sequenzielle 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();
Übergänge zwischen Elementen in einer Playlist sind nahtlos. Sie müssen nicht dasselbe Format haben. Eine Playlist kann beispielsweise sowohl H264- als auch VP9-Videos enthalten. Sie können sogar unterschiedliche Typen haben, d. h. eine Playlist kann Videos, Bilder und reine Audio-Streams enthalten. Sie können dasselbe MediaItem mehrmals in einer Playlist verwenden.
Playlist bearbeiten
Sie können eine Playlist dynamisch ändern, indem Sie Media-Elemente hinzufügen, verschieben, entfernen oder ersetzen. Das ist sowohl vor als auch während der Wiedergabe möglich. Rufen Sie 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));
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();
Der Player verarbeitet Änderungen während der Wiedergabe automatisch auf die richtige Weise:
- Wenn die aktuell wiedergegebene
MediaItemverschoben wird, wird die Wiedergabe nicht unterbrochen. Nach Abschluss der Wiedergabe wird der neue Nachfolger wiedergegeben. - Wenn die aktuell wiedergegebene
MediaItementfernt wird, spielt der Player automatisch den ersten verbleibenden Nachfolger ab oder wechselt in den Status „Beendet“, wenn kein solcher Nachfolger vorhanden ist. - Wenn das aktuell wiedergegebene
MediaItemersetzt wird, wird die Wiedergabe nicht unterbrochen, sofern sich keine der für die Wiedergabe relevanten Eigenschaften imMediaItemgeändert hat. So ist es beispielsweise in den meisten Fällen möglich, die FelderMediaItem.MediaMetadatazu 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 das letzte Element in der Playlist wiedergegeben wurde.Player.REPEAT_MODE_ONE: Das aktuelle Element wird in einer Endlosschleife wiederholt. Bei Methoden wiePlayer.seekToNextMediaItemwird dies ignoriert und zum nächsten Element in der Liste gesprungen, das dann in einer Endlosschleife wiederholt wird.Player.REPEAT_MODE_ALL: Die gesamte Playlist wird in einer Endlosschleife wiederholt.
Zufallsmodus
Der Zufallsmix kann jederzeit mit Player.setShuffleModeEnabled aktiviert oder deaktiviert werden. Im Zufallsmix-Modus wird die Playlist in einer vorab berechneten, zufälligen Reihenfolge wiedergegeben. Alle Elemente werden einmal abgespielt. Der Zufallsmodus kann auch mit Player.REPEAT_MODE_ALL kombiniert werden, um dieselbe zufällige Reihenfolge in einer Endlosschleife zu wiederholen. Wenn der Zufallsmodus deaktiviert ist, wird die Wiedergabe des aktuellen Elements an seiner ursprünglichen Position in der Playlist fortgesetzt.
Die von Methoden wie Player.getCurrentMediaItemIndex zurückgegebenen Indexwerte beziehen sich immer auf die ursprüngliche, nicht gemischte Reihenfolge. Ebenso wird bei Player.seekToNextMediaItem nicht das Element bei player.getCurrentMediaItemIndex() + 1, sondern das nächste Element in der zufälligen Reihenfolge wiedergegeben. Wenn du neue Elemente in die Playlist einfügst oder Elemente entfernst, bleibt die vorhandene zufällige Reihenfolge so weit wie möglich unverändert.
Benutzerdefinierte Shuffle-Reihenfolge festlegen
Standardmäßig unterstützt der Player das Shuffling mit DefaultShuffleOrder.
Sie können dies anpassen, indem Sie eine benutzerdefinierte Implementierung der zufälligen Reihenfolge angeben oder eine benutzerdefinierte Reihenfolge im DefaultShuffleOrder-Konstruktor festlegen:
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
Zum Identifizieren von Playlist-Elementen 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 für ein Media-Element keine Media-ID explizit definiert ist, wird die Stringdarstellung des URI verwendet.
App-Daten mit Playlist-Elementen verknüpfen
Zusätzlich zu einer ID kann jedes Media-Element auch mit einem benutzerdefinierten Tag konfiguriert werden, das ein beliebiges von der App bereitgestelltes Objekt sein kann. Benutzerdefinierte Tags können unter anderem verwendet werden, um jedem Media-Element Metadaten zuzuweisen:
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 Media-Element wechselt oder dasselbe Media-Element wiederholt wird, wird Listener.onMediaItemTransition(MediaItem,
@MediaItemTransitionReason) aufgerufen. Dieser Callback empfängt das neue Media-Element zusammen mit einem @MediaItemTransitionReason, das angibt, warum der Übergang stattgefunden hat. Ein häufiger Anwendungsfall für onMediaItemTransition ist das Aktualisieren der Benutzeroberfläche der App für das neue Media-Element:
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 jedem Media-Element mithilfe von benutzerdefinierten Tags 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 Media-Element 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 werden, wird Timeline aktualisiert und onTimelineChanged wird mit TIMELINE_CHANGE_REASON_SOURCE_UPDATE aufgerufen. Weitere Gründe für eine Aktualisierung der Zeitachse:
- Ein Manifest wird verfügbar, nachdem ein adaptives Media-Element vorbereitet wurde.
- Ein Manifest, das während der Wiedergabe eines Livestreams regelmäßig aktualisiert wird.