API списка воспроизведения определяется интерфейсом Player
, который реализован во всех реализациях ExoPlayer
. Списки воспроизведения позволяют последовательно воспроизводить несколько элементов мультимедиа. В следующем примере показано, как начать воспроизведение списка воспроизведения, содержащего два видео:
Котлин
// 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()
Ява
// 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 плейлиста:
Котлин
// 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))
Ява
// 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));
Также поддерживается замена и очистка всего плейлиста:
Котлин
// 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()
Ява
// 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
: список воспроизведения не повторяется, и проигрыватель перейдет в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
:
Котлин
// 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
Ява
// 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
можно установить при создании элемента:
Котлин
// Build a media item with a media ID. val mediaItem = MediaItem.Builder().setUri(uri).setMediaId(mediaId).build()
Ява
// Build a media item with a media ID. MediaItem mediaItem = new MediaItem.Builder().setUri(uri).setMediaId(mediaId).build();
Если приложение явно не определяет идентификатор мультимедиа для элемента мультимедиа, используется строковое представление URI.
Связывание данных приложения с элементами списка воспроизведения
Помимо идентификатора, каждый элемент мультимедиа также можно настроить с помощью пользовательского тега, который может быть любым объектом, предоставленным приложением. Одним из вариантов использования пользовательских тегов является прикрепление метаданных к каждому элементу мультимедиа:
Котлин
// Build a media item with a custom tag. val mediaItem = MediaItem.Builder().setUri(uri).setTag(metadata).build()
Ява
// Build a media item with a custom tag. MediaItem mediaItem = new MediaItem.Builder().setUri(uri).setTag(metadata).build();
Обнаружение перехода воспроизведения к другому элементу мультимедиа
Когда воспроизведение переходит к другому элементу мультимедиа или начинает повторять один и тот же элемент мультимедиа, вызывается Listener.onMediaItemTransition(MediaItem, @MediaItemTransitionReason)
. Этот обратный вызов получает новый элемент мультимедиа вместе с @MediaItemTransitionReason
, указывающим, почему произошел переход. Распространенным вариантом использования onMediaItemTransition
является обновление пользовательского интерфейса приложения для нового элемента мультимедиа:
Котлин
override fun onMediaItemTransition( mediaItem: MediaItem?, @MediaItemTransitionReason reason: Int, ) { updateUiForPlayingMediaItem(mediaItem) }
Ява
@Override public void onMediaItemTransition( @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) { updateUiForPlayingMediaItem(mediaItem); }
Если метаданные, необходимые для обновления пользовательского интерфейса, прикреплены к каждому элементу мультимедиа с помощью пользовательских тегов, то реализация может выглядеть так:
Котлин
override fun onMediaItemTransition( mediaItem: MediaItem?, @MediaItemTransitionReason reason: Int, ) { var metadata: CustomMetadata? = null mediaItem?.localConfiguration?.let { localConfiguration -> metadata = localConfiguration.tag as? CustomMetadata } updateUiForPlayingMediaItem(metadata) }
Ява
@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
. Этот обратный вызов вызывается, даже если игрок еще не подготовлен.
Котлин
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) } }
Ява
@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
. Другие причины, которые могут вызвать обновление временной шкалы, включают в себя:
- Манифест становится доступным после подготовки адаптивного медиа-элемента.
- Манифест периодически обновляется во время воспроизведения прямой трансляции.