อินเทอร์เฟซของโปรแกรมเล่น

โปรแกรมเล่นคือคอมโพเนนต์ของแอปที่ช่วยให้เล่นรายการสื่อได้ อินเทอร์เฟซ Media3 Player จะกำหนดเค้าโครงของฟังก์ชันการทำงานที่โดยทั่วไปแล้วเพลเยอร์จะจัดการ ซึ่งรวมถึง

  • ส่งผลต่อการควบคุมการเล่น เช่น การเล่น หยุดชั่วคราว และการกรอ
  • การค้นหาพร็อพเพอร์ตี้ของสื่อที่เล่นอยู่ เช่น ตําแหน่งการเล่น
  • การจัดการเพลย์ลิสต์/คิวของรายการสื่อ
  • การกำหนดค่าพร็อพเพอร์ตี้การเล่น เช่น การสับ การเล่นซ้ำ ความเร็ว และระดับเสียง
  • การแสดงผลวิดีโอบนหน้าจอ

Media3 ยังให้บริการการใช้งานอินเทอร์เฟซ Player ที่เรียกว่า ExoPlayer ด้วย

อินเทอร์เฟซทั่วไประหว่างคอมโพเนนต์

คอมโพเนนต์หลายรายการใน Media3 ใช้อินเทอร์เฟซ Player เช่น

ส่วนประกอบ คำอธิบายและหมายเหตุเกี่ยวกับลักษณะการทำงาน
ExoPlayer API ของโปรแกรมเล่นสื่อ และการใช้งานอินเทอร์เฟซ Player เริ่มต้น
MediaController โต้ตอบกับ MediaSession เพื่อส่งคำสั่งการเล่น หาก Player และ MediaSession อยู่ใน Service ที่แยกจาก Activity หรือ Fragment ที่ UI ของโปรแกรมเล่นอยู่ คุณสามารถกำหนด MediaController ให้เป็นโปรแกรมเล่นสำหรับ UI ของ PlayerView ระบบจะส่งการเรียกใช้เมธอดการเล่นและเพลย์ลิสต์ไปยัง Player ผ่าน MediaSession
MediaBrowser นอกเหนือจากฟังก์ชันการทำงานที่ MediaController นำเสนอแล้ว ยังโต้ตอบกับ MediaLibrarySession เพื่อเรียกดูเนื้อหาสื่อที่มี
ForwardingPlayer การใช้งาน Player ที่ส่งต่อการเรียกเมธอดไปยัง Player อื่น ใช้คลาสนี้เพื่อระงับหรือแก้ไขการดำเนินการที่เฉพาะเจาะจงโดยการลบล้างเมธอดที่เกี่ยวข้อง
SimpleBasePlayer การติดตั้งใช้งาน Player ที่ลดจำนวนวิธีการติดตั้งใช้งานให้เหลือน้อยที่สุด มีประโยชน์เมื่อใช้โปรแกรมเล่นที่กำหนดเองซึ่งคุณต้องการเชื่อมต่อกับ MediaSession
CastPlayer การใช้งาน Player ที่สื่อสารกับแอปตัวรับ Cast ลักษณะการทำงานจะขึ้นอยู่กับเซสชัน Cast ที่เกี่ยวข้อง

แม้ว่า MediaSession จะไม่ใช้อินเทอร์เฟซ Player แต่ต้องใช้ Player เมื่อสร้าง โดยมีวัตถุประสงค์เพื่อให้สิทธิ์เข้าถึง Player จากกระบวนการหรือเธรดอื่นๆ

สถาปัตยกรรมการเล่นของ Media3

หากมีสิทธิ์เข้าถึง Player คุณควรเรียกใช้เมธอดของ Player โดยตรงเพื่อออกคำสั่งการเล่น คุณสามารถโฆษณาการเล่นและมอบสิทธิ์ควบคุมการเล่นให้กับแหล่งที่มาภายนอกได้โดยใช้ MediaSession แหล่งที่มาภายนอกเหล่านี้ใช้ MediaController ซึ่งช่วยให้เชื่อมต่อกับเซสชันสื่อและส่งคําขอคําสั่งการเล่นได้ง่ายขึ้น

เมื่อเล่นสื่อในเบื้องหลัง คุณต้องจัดเก็บเซสชันและโปรแกรมเล่นสื่อภายใน MediaSessionService หรือ MediaLibraryService ที่ทำงานเป็นบริการที่ทำงานอยู่เบื้องหน้า ซึ่งจะช่วยให้คุณแยกเพลเยอร์ออกจากกิจกรรมในแอปที่มี UI สำหรับการควบคุมการเล่นได้ ซึ่งอาจทำให้คุณต้องใช้ตัวควบคุมสื่อ

แผนภาพแสดงวิธีที่คอมโพเนนต์การเล่นของ Media3 ทำงานร่วมกับสถาปัตยกรรมแอปสื่อ
รูปที่ 1: อินเทอร์เฟซ Player มีบทบาทสําคัญในสถาปัตยกรรมของ Media3

สถานะโปรแกรมเล่น

สถานะของโปรแกรมเล่นสื่อที่ใช้อินเทอร์เฟซ Player ประกอบด้วยข้อมูล 4 หมวดหมู่หลักๆ ดังนี้

  1. สถานะการเล่น
  2. เพลย์ลิสต์ของรายการสื่อ
    • อินสแตนซ์ MediaItem รายการสำหรับเล่น
    • เรียกข้อมูลด้วย getCurrentTimeline()
    • อินสแตนซ์ Player สามารถระบุวิธีการดำเนินการกับเพลย์ลิสต์ เช่น การเพิ่มหรือการนำออก MediaItem และวิธีการที่สะดวก เช่น getCurrentMediaItem()
  3. พร็อพเพอร์ตี้เล่น/หยุดชั่วคราว เช่น
    • playWhenReady: ตัวบ่งชี้ว่าผู้ใช้ต้องการให้เล่นสื่อเมื่อเป็นไปได้หรือให้หยุดชั่วคราว
    • เหตุผลในการระงับการเล่น: การระบุสาเหตุที่ระงับการเล่น (หากมี) แม้ว่าplayWhenReadyจะเป็น true ก็ตาม
    • isPlaying: ตัวบ่งชี้ว่าขณะนี้เพลเยอร์เล่นอยู่หรือไม่ ซึ่งจะเป็นtrueก็ต่อเมื่อสถานะการเล่นเป็นSTATE_READY, playWhenReadyเป็นtrue และไม่มีการระงับการเล่น
  4. ตำแหน่งการเล่น ซึ่งรวมถึงข้อมูลต่อไปนี้

นอกจากนี้ อินเทอร์เฟซ Player ยังอนุญาตให้เข้าถึงแทร็กที่ใช้ได้ ข้อมูลเมตาของสื่อ ความเร็วในการเล่น ระดับเสียง และพร็อพเพอร์ตี้เสริมอื่นๆ ของการเล่น

ฟังการเปลี่ยนแปลง

ใช้ Player.Listener เพื่อรอฟังการเปลี่ยนแปลงใน Player ดูรายละเอียดเกี่ยวกับวิธีสร้างและใช้ Listener ได้จากเอกสารประกอบของ ExoPlayer เกี่ยวกับเหตุการณ์ของ Player

โปรดทราบว่าอินเทอร์เฟซโปรแกรมฟังไม่ได้รวมการเรียกกลับเพื่อติดตามความคืบหน้าในการเล่นตามปกติ หากต้องการตรวจสอบความคืบหน้าในการเล่นอย่างต่อเนื่อง เช่น การตั้งค่า UI แถบความคืบหน้า คุณควรค้นหาตำแหน่งปัจจุบันเป็นระยะๆ

Kotlin

val handler = Handler(Looper.getMainLooper())
fun checkPlaybackPosition(delayMs: Long): Boolean =
  handler.postDelayed(
    {
      val currentPosition = player.currentPosition
      // Update UI based on currentPosition
      checkPlaybackPosition(delayMs)
    },
    delayMs)

Java

Handler handler = new Handler(Looper.getMainLooper());
boolean checkPlaybackPosition(long delayMs) {
    return handler.postDelayed(() -> {
        long currentPosition = player.getCurrentPosition();
        // Update UI based on currentPosition
        checkPlaybackPosition(delayMs);
    }, delayMs);
}

ควบคุมการเล่น

อินเทอร์เฟซ Player มีวิธีจัดการสถานะและควบคุมการเล่นหลายวิธี ดังนี้

การติดตั้งใช้งาน Player ที่กําหนดเอง

หากต้องการสร้างเพลเยอร์ที่กำหนดเอง คุณสามารถขยาย SimpleBasePlayer ที่รวมอยู่ใน Media3 คลาสนี้ให้การใช้งานพื้นฐานของPlayer อินเทอร์เฟซเพื่อลดจํานวนเมธอดที่จําเป็นต้องใช้ให้เหลือน้อยที่สุด

เริ่มต้นด้วยการลบล้างเมธอด getState() เมธอดนี้ควรสร้างสถานะผู้เล่นปัจจุบันเมื่อเรียกใช้ ซึ่งรวมถึงข้อมูลต่อไปนี้

  • ชุดคำสั่งที่ใช้ได้
  • พร็อพเพอร์ตี้การเล่น เช่น โปรแกรมเล่นควรเริ่มเล่นเมื่อสถานะการเล่นเป็น STATE_READY หรือไม่ ดัชนีของรายการสื่อที่เล่นอยู่ และตำแหน่งการเล่นภายในรายการปัจจุบัน

Kotlin

class CustomPlayer : SimpleBasePlayer(looper) {
  override fun getState(): State {
    return State.Builder()
      .setAvailableCommands(...) // Set which playback commands the player can handle
      // Configure additional playback properties
      .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST)
      .setCurrentMediaItemIndex(0)
      .setContentPositionMs(0)
      .build()
  }
}

Java

public class CustomPlayer extends SimpleBasePlayer {
  public CustomPlayer(Looper looper) {
    super(looper);
  }

  @Override
  protected State getState() {
    return new State.Builder()
      .setAvailableCommands(...) // Set which playback commands the player can handle
      // Configure additional playback properties
      .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST)
      .setCurrentMediaItemIndex(0)
      .setContentPositionMs(0)
      .build();
  }
}

SimpleBasePlayer จะบังคับให้สร้าง State ด้วยชุดค่าผสมของค่าสถานะที่ถูกต้อง รวมถึงจะจัดการผู้ฟังและแจ้งให้ทราบถึงการเปลี่ยนแปลงสถานะด้วย หากต้องการเรียกให้อัปเดตสถานะด้วยตนเอง ให้โทรหา invalidateState()

นอกจากเมธอด getState() แล้ว คุณต้องใช้เฉพาะเมธอดที่ใช้สำหรับคำสั่งที่ผู้เล่นประกาศว่าพร้อมใช้งาน ค้นหาเมธอดตัวแฮนเดิลที่ลบล้างได้ซึ่งสอดคล้องกับฟังก์ชันการทำงานที่คุณต้องการใช้ เช่น ลบล้างเมธอด handleSeek() เพื่อรองรับการดำเนินการต่างๆ เช่น COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM และ COMMAND_SEEK_TO_NEXT_MEDIA_ITEM