เพลย์ลิสต์

เพลย์ลิสต์ API กำหนดโดยอินเทอร์เฟซ Player ซึ่งติดตั้งใช้งานโดยExoPlayerทั้งหมด เพลย์ลิสต์ช่วยให้เล่นรายการสื่อหลายรายการ ตามลำดับได้ ตัวอย่างต่อไปนี้แสดงวิธีเริ่มเล่นเพลย์ลิสต์ที่มีวิดีโอ 2 รายการ

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: เพลย์ลิสต์จะไม่เล่นซ้ำ และโปรแกรมเล่นจะเปลี่ยนไปเป็น Player.STATE_ENDED เมื่อเล่นรายการสุดท้ายในเพลย์ลิสต์แล้ว
  • Player.REPEAT_MODE_ONE: รายการปัจจุบันแสดงซ้ำวนไปเรื่อยๆ วิธีการอย่าง Player.seekToNextMediaItem จะละเว้นการดำเนินการนี้และข้ามไปยังรายการถัดไปในรายการ ซึ่งจะวนซ้ำไปเรื่อยๆ
  • Player.REPEAT_MODE_ALL: ทั้งเพลย์ลิสต์เล่นซ้ำแบบวนซ้ำไม่สิ้นสุด

โหมดสุ่มเพลง

คุณเปิดหรือปิดใช้โหมดสุ่มได้ทุกเมื่อด้วย Player.setShuffleModeEnabled เมื่ออยู่ในโหมดสุ่ม โปรแกรมเล่นจะเล่นเพลย์ลิสต์ตามลำดับแบบสุ่มที่คำนวณไว้ล่วงหน้า ระบบจะเล่นรายการทั้งหมด 1 ครั้ง และคุณยังใช้โหมดสุ่มร่วมกับ 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();

หากแอปไม่ได้กำหนดรหัสสื่อสำหรับรายการสื่ออย่างชัดเจน ระบบจะใช้การนำเสนอสตริงของ URI

การเชื่อมโยงข้อมูลแอปกับรายการเพลย์ลิสต์

นอกจากรหัสแล้ว รายการสื่อแต่ละรายการยังกําหนดค่าด้วยแท็กที่กําหนดเองได้ด้วย ซึ่งอาจเป็นออบเจ็กต์ใดก็ได้ที่แอประบุ การใช้แท็กที่กำหนดเองอย่างหนึ่งคือ การแนบข้อมูลเมตากับรายการสื่อแต่ละรายการดังนี้

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 คืออัปเดต UI ของแอปสำหรับรายการสื่อใหม่ ดังนี้

Kotlin

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

Java

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

หากแนบข้อมูลเมตาที่จำเป็นในการอัปเดต UI อยู่กับรายการสื่อแต่ละรายการโดยใช้แท็กที่กำหนดเอง การใช้งานอาจมีลักษณะดังนี้

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 สาเหตุอื่นๆ ที่อาจทําให้ไทม์ไลน์อัปเดต ได้แก่

  • ไฟล์ Manifest พร้อมใช้งานหลังจากเตรียมรายการสื่อแบบปรับอัตโนมัติ
  • ไฟล์ Manifest มีการอัปเดตเป็นระยะระหว่างการเล่นสตรีมแบบสด