播放列表 API 由 Player
接口定义,该接口由
所有 ExoPlayer
实现。通过播放列表,您可以连续播放多个
媒体内容。以下示例展示了如何开始播放播放列表
包含两个视频:
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();
播放列表中的项之间可以无缝切换。无要求
格式相同(例如,一个播放列表中可以同时包含
H264 和 VP9 视频)。它们甚至可能具有不同的类型(也就是说,
播放列表,包含视频、图片和纯音频流)。您可以使用
在一个播放列表中多次MediaItem
。
修改播放列表
你可以对播放列表进行动态修改,例如添加、移动、移除或替换 媒体内容。此操作可在播放之前和播放期间通过调用 相应的播放列表 API 方法:
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));
系统还支持替换和清除整个播放列表:
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();
在以正确的 方式:
- 如果移动当前正在播放的
MediaItem
,则播放不会中断,并且 新的继任游戏将在游戏结束时播放。 - 如果当前播放的
MediaItem
被移除,播放器将自动 播放剩下的第一个接续视频,或者跳到结束状态(如果没有 此类继承者存在。 - 如果替换当前播放的
MediaItem
,播放不会中断 如果MediaItem
中的所有属性均与播放无关 已更改。例如,您可以更新MediaItem.MediaMetadata
字段,而不会影响播放。
查询播放列表
您可以使用 Player.getMediaItemCount
和
Player.getMediaItemAt
。可以查询当前正在播放的媒体项
调用 Player.getCurrentMediaItem
。还有一些其他便利
Player.hasNextMediaItem
或 Player.getNextMediaItemIndex
等方法
简化在播放列表中的导航。
重复模式
播放器支持 3 种重复模式,你可以随时使用
Player.setRepeatMode
:
Player.REPEAT_MODE_OFF
:播放列表不会重复播放,播放器将 播放列表中的最后一项结束后,YouTube 将转到Player.STATE_ENDED
。Player.REPEAT_MODE_ONE
:当前项不断地在无限循环中重复。Player.seekToNextMediaItem
等方法会忽略这一点并寻找 列表中的下一个项目,然后无限循环。Player.REPEAT_MODE_ALL
:系统会以无限循环的方式重复播放整个播放列表。
随机播放模式
您可以随时启用或停用随机播放模式
Player.setShuffleModeEnabled
。在随机播放模式下,播放器会播放
预先计算随机排序的播放列表。所有内容都会播放一次,
随机播放模式还可以与 Player.REPEAT_MODE_ALL
结合使用来重复播放
以无限循环的方式呈现相同的随机顺序。关闭随机播放模式后,
从
播放列表。
请注意,诸如
Player.getCurrentMediaItemIndex
始终引用未重排的原始文件
订单。同样,Player.seekToNextMediaItem
也不会在
player.getCurrentMediaItemIndex() + 1
但根据
随机播放顺序。无论在播放列表中插入新项目还是移除项目,
会尽可能保持现有重排顺序不变。
设置自定义重排顺序
默认情况下,播放器支持使用 DefaultShuffleOrder
进行随机播放。
这可以通过提供自定义重排顺序实现或
在 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);
识别播放列表项
要识别播放列表项,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();
如果应用没有明确定义媒体项的媒体 ID,则字符串 URI 的表示法。
将应用数据与播放列表项相关联
除了 ID 之外,还可以为每个媒体项配置一个自定义代码, 该对象可以是应用提供的任何对象。自定义代码的一个用途是将 元数据:
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();
检测播放切换到另一个媒体项的时间
当播放过渡到另一个媒体项,或开始重复播放相同的内容时
媒体项时,系统会调用 Listener.onMediaItemTransition(MediaItem,
@MediaItemTransitionReason)
。此回调用于接收新媒体
以及指示过渡原因的 @MediaItemTransitionReason
错误。onMediaItemTransition
的一个常见用例是更新
新媒体项的应用界面:
Kotlin
override fun onMediaItemTransition( mediaItem: MediaItem?, @MediaItemTransitionReason reason: Int, ) { updateUiForPlayingMediaItem(mediaItem) }
Java
@Override public void onMediaItemTransition( @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) { updateUiForPlayingMediaItem(mediaItem); }
如果使用 那么实现代码可能如下所示:
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); }
检测播放列表何时发生更改
添加、移除或移动媒体内容时,
调用 Listener.onTimelineChanged(Timeline, @TimelineChangeReason)
立即与 TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED
对话。此回调是
调用该方法。
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); } }
当播放列表中媒体项的时长等信息变为
可用,系统将更新 Timeline
并调用 onTimelineChanged
与TIMELINE_CHANGE_REASON_SOURCE_UPDATE
共享。导致
时间表更新包括:
- 准备好自适应媒体项后,清单变为可用状态。
- 在直播播放期间定期更新的清单。