Danh sách phát

API danh sách phát được xác định bằng giao diện Player, được triển khai bằng tất cả các phương thức triển khai ExoPlayer. Danh sách phát cho phép phát tuần tự nhiều mục nội dung đa phương tiện. Ví dụ sau đây cho biết cách bắt đầu phát một danh sách phát chứa hai video:

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();

Chuyển đổi liền mạch giữa các mục trong danh sách phát. Không bắt buộc phải có cùng định dạng (ví dụ: một danh sách phát có thể chứa cả video H264 và VP9). Thậm chí chúng có thể thuộc nhiều loại khác nhau (nghĩa là một danh sách phát có thể chứa cả luồng video và luồng chỉ âm thanh thì không có vấn đề gì). Bạn có thể sử dụng cùng một MediaItem nhiều lần trong một danh sách phát.

Sửa đổi danh sách phát

Bạn có thể sửa đổi danh sách phát một cách linh động bằng cách thêm, di chuyển, xoá hoặc thay thế các mục nội dung nghe nhìn. Bạn có thể thực hiện việc này cả trước và trong khi phát bằng cách gọi các phương thức API danh sách phát tương ứng:

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));

Thay thế và xoá toàn bộ danh sách phát cũng được hỗ trợ:

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();

Trình phát tự động xử lý các nội dung sửa đổi trong quá trình phát theo đúng cách:

  • Nếu MediaItem đang phát bị di chuyển, quá trình phát sẽ không bị gián đoạn và phiên bản kế thừa mới sẽ được phát sau khi hoàn tất.
  • Nếu MediaItem đang phát bị xoá, trình phát sẽ tự động chơi trò kế thừa đầu tiên còn lại hoặc chuyển sang trạng thái kết thúc nếu không có trình kế thừa nào như vậy tồn tại.
  • Nếu MediaItem đang phát được thay thế thì quá trình phát sẽ không bị gián đoạn nếu không có thuộc tính nào trong MediaItem liên quan đến việc thay đổi quá trình phát. Ví dụ: bạn có thể cập nhật các trường MediaItem.MediaMetadata trong hầu hết các trường hợp mà không ảnh hưởng đến việc phát.

Truy vấn danh sách phát

Bạn có thể truy vấn danh sách phát này bằng cách sử dụng Player.getMediaItemCountPlayer.getMediaItemAt. Bạn có thể truy vấn mục nội dung nghe nhìn đang phát bằng cách gọi Player.getCurrentMediaItem. Ngoài ra, còn có các phương thức tiện lợi khác như Player.hasNextMediaItem hoặc Player.getNextMediaItemIndex để đơn giản hoá quá trình điều hướng trong danh sách phát.

Chế độ lặp lại

Trình phát hỗ trợ 3 chế độ lặp lại mà bạn có thể đặt bất cứ lúc nào bằng Player.setRepeatMode:

  • Player.REPEAT_MODE_OFF: Danh sách phát không lặp lại và trình phát sẽ chuyển đổi sang Player.STATE_ENDED sau khi mục cuối cùng trong danh sách phát đã được phát.
  • Player.REPEAT_MODE_ONE: Mục hiện tại được lặp lại trong một vòng lặp vô tận. Các phương thức như Player.seekToNextMediaItem sẽ bỏ qua điều này và tìm kiếm mục tiếp theo trong danh sách. Sau đó, mục này sẽ được lặp lại trong một vòng lặp vô tận.
  • Player.REPEAT_MODE_ALL: Toàn bộ danh sách phát lặp lại trong một vòng lặp vô tận.

Chế độ trộn bài

Bạn có thể bật hoặc tắt chế độ trộn bài bất cứ lúc nào bằng Player.setShuffleModeEnabled. Khi ở chế độ trộn bài, người chơi sẽ phát danh sách phát theo thứ tự ngẫu nhiên, được tính toán trước. Tất cả các mục sẽ được phát một lần và bạn cũng có thể kết hợp chế độ trộn bài với Player.REPEAT_MODE_ALL để lặp lại cùng một thứ tự ngẫu nhiên trong một vòng lặp vô tận. Khi bạn tắt chế độ trộn bài, quá trình phát sẽ tiếp tục từ mục hiện tại ở vị trí ban đầu trong danh sách phát.

Lưu ý rằng các chỉ mục mà các phương thức như Player.getCurrentMediaItemIndex trả về luôn tham chiếu đến thứ tự ban đầu, không bị xáo trộn. Tương tự, Player.seekToNextMediaItem sẽ không phát mục đó tại player.getCurrentMediaItemIndex() + 1 mà phát mục tiếp theo theo thứ tự xáo trộn. Việc chèn mục mới vào danh sách phát hoặc xoá các mục sẽ giữ nguyên thứ tự xáo trộn hiện tại nhiều nhất có thể.

Đặt thứ tự trộn bài tuỳ chỉnh

Theo mặc định, trình phát hỗ trợ phát ngẫu nhiên bằng cách sử dụng DefaultShuffleOrder. Bạn có thể tuỳ chỉnh việc này bằng cách triển khai thứ tự trộn bài tuỳ chỉnh hoặc đặt thứ tự tuỳ chỉnh trong hàm khởi tạo 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);

Xác định các mục trong danh sách phát

Để xác định các mục trong danh sách phát, bạn có thể đặt MediaItem.mediaId khi tạo mục:

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();

Nếu ứng dụng không xác định rõ ràng mã nhận dạng nội dung đa phương tiện cho một mục nội dung đa phương tiện, thì hệ thống sẽ sử dụng chuỗi đại diện của URI.

Liên kết dữ liệu ứng dụng với các mục trong danh sách phát

Ngoài mã nhận dạng, mỗi mục nội dung đa phương tiện cũng có thể được định cấu hình bằng một thẻ tuỳ chỉnh, có thể là đối tượng bất kỳ do ứng dụng cung cấp. Có một cách sử dụng thẻ tuỳ chỉnh là đính kèm siêu dữ liệu vào mỗi mục nội dung đa phương tiện:

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();

Phát hiện thời điểm chuyển đổi quá trình phát sang một mục nội dung nghe nhìn khác

Khi chuyển đổi quá trình phát sang một mục nội dung nghe nhìn khác hoặc bắt đầu lặp lại cùng một mục nội dung nghe nhìn, Listener.onMediaItemTransition(MediaItem, @MediaItemTransitionReason) sẽ được gọi. Lệnh gọi lại này nhận được mục nội dung đa phương tiện mới, cùng với @MediaItemTransitionReason cho biết lý do tại sao quá trình chuyển đổi diễn ra. Một trường hợp sử dụng phổ biến cho onMediaItemTransition là cập nhật giao diện người dùng của ứng dụng cho mục nội dung đa phương tiện mới:

Kotlin

override fun onMediaItemTransition(
  mediaItem: MediaItem?,
  @MediaItemTransitionReason reason: Int,
) {
  updateUiForPlayingMediaItem(mediaItem)
}

Java

@Override
public void onMediaItemTransition(
    @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) {
  updateUiForPlayingMediaItem(mediaItem);
}

Nếu siêu dữ liệu cần thiết để cập nhật giao diện người dùng được đính kèm vào từng mục nội dung đa phương tiện bằng cách sử dụng thẻ tuỳ chỉnh, thì quá trình triển khai có thể trông giống như sau:

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);
}

Phát hiện thời điểm danh sách phát thay đổi

Khi thêm, xoá hoặc di chuyển một mục nội dung đa phương tiện, Listener.onTimelineChanged(Timeline, @TimelineChangeReason) sẽ được gọi ngay lập tức bằng TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED. Lệnh gọi lại này được gọi ngay cả khi trình phát chưa sẵn sàng.

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);
  }
}

Khi có các thông tin như thời lượng của một mục nội dung đa phương tiện trong danh sách phát, Timeline sẽ được cập nhật và onTimelineChanged sẽ được gọi bằng TIMELINE_CHANGE_REASON_SOURCE_UPDATE. Sau đây là những lý do khác có thể khiến việc cập nhật dòng thời gian:

  • Một tệp kê khai sẽ xuất hiện sau khi chuẩn bị một mục nội dung nghe nhìn thích ứng.
  • Tệp kê khai được cập nhật định kỳ trong khi phát sự kiện phát trực tiếp.