การใช้งานเซสชันสื่อ

เซสชันสื่อเป็นวิธีสากลในการโต้ตอบกับโปรแกรมเล่นเสียงหรือวิดีโอ การแจ้ง Android ว่าสื่อกำลังเล่นในแอปจะช่วยให้สามารถมอบสิทธิ์ตัวควบคุมการเล่นให้กับแอปได้ การผสานรวมกับเซสชันสื่อช่วยให้แอปโฆษณาการเล่นสื่อภายนอกและรับคำสั่งการเล่นจากแหล่งที่มาภายนอกได้ แหล่งที่มาเหล่านี้อาจเป็นปุ่มจริง (เช่น ปุ่มเล่นบนชุดหูฟังหรือรีโมตทีวี) หรือคำสั่งทางอ้อม (เช่น การสั่งให้ Google Assistant "หยุดชั่วคราว") จากนั้นเซสชันสื่อจะมอบสิทธิ์คำสั่งเหล่านี้ให้กับแอปที่ใช้คำสั่งเหล่านั้นกับมีเดียเพลเยอร์ ซึ่งจะทำให้ทราบว่าคำสั่งมาจากที่ใด

เซสชันสื่อจะอยู่ควบคู่ไปกับเพลเยอร์ที่จัดการ คุณควรสร้างและเริ่มต้นเซสชันสื่อในเมธอด onCreate() ของกิจกรรมหรือบริการที่เป็นเจ้าของเซสชันสื่อและโปรแกรมเล่นที่เชื่อมโยง

เริ่มต้นเซสชันสื่อ

เซสชันสื่อที่สร้างใหม่ไม่มีความสามารถ คุณต้องเริ่มต้นเซสชันโดยทำตามขั้นตอนต่อไปนี้

  • ตั้งค่าแฟล็กเพื่อให้เซสชันสื่อรับ Callback จากตัวควบคุมสื่อและปุ่มสื่อได้
  • สร้างและเริ่มต้นอินสแตนซ์ของ PlaybackStateCompat แล้วกำหนดให้กับเซสชัน สถานะการเล่นจะเปลี่ยนแปลงตลอดเซสชัน ดังนั้นเราขอแนะนำให้แคช PlaybackStateCompat.Builder เพื่อนำมาใช้ซ้ำ
  • สร้างอินสแตนซ์ของ MediaSessionCompat.Callback และกำหนดให้กับเซสชัน (ดูข้อมูลเพิ่มเติมเกี่ยวกับ Callback ด้านล่าง)

คุณควรสร้างและเริ่มต้นเซสชันสื่อในเมธอด onCreate() ของกิจกรรมหรือบริการที่เป็นเจ้าของเซสชัน

เพื่อให้ปุ่มสื่อทำงานเมื่อแอปของคุณเริ่มต้นใหม่ (หรือหยุดทำงาน) PlaybackState ของแอปต้องมีการดำเนินการเล่นที่ตรงกับ Intent ที่ปุ่มสื่อส่ง นี่คือเหตุผลที่ ACTION_PLAY ได้รับการกำหนดให้กับสถานะเซสชันระหว่างการเริ่มต้น ดูข้อมูลเพิ่มเติมได้ที่การตอบสนองต่อปุ่มสื่อ

คงสถานะการเล่นและข้อมูลเมตาไว้

มี 2 คลาสที่แสดงสถานะของเซสชันสื่อ

คลาส PlaybackStateCompat อธิบายสถานะการทำงานปัจจุบันของโปรแกรมเล่น ซึ่งรวมถึงเนื้อหาต่อไปนี้

  • สถานะการส่ง (เพลเยอร์กำลังเล่น/หยุดชั่วคราว/บัฟเฟอร์ ฯลฯ ดู getState())
  • รหัสข้อผิดพลาดและข้อความแสดงข้อผิดพลาด (ไม่บังคับ) หากมี (ดู getErrorCode() และอ่านสถานะและข้อผิดพลาดด้านล่าง)
  • ตำแหน่งของโปรแกรมเล่น
  • การดำเนินการของตัวควบคุมที่ถูกต้องซึ่งสามารถจัดการได้ในสถานะปัจจุบัน

คลาส MediaMetadataCompat จะอธิบายเนื้อหาที่กำลังเล่นอยู่ ดังนี้

  • ชื่อศิลปิน อัลบั้ม และแทร็ก
  • ระยะเวลาของแทร็ก
  • ภาพปกอัลบั้มสำหรับแสดงบนหน้าจอล็อก รูปภาพเป็นบิตแมปที่มีขนาดสูงสุด 320x320dp (หากใหญ่กว่านี้ ระบบจะปรับขนาดให้เล็กลง)
  • อินสแตนซ์ของ ContentUris ที่ชี้ไปยังอาร์ตเวิร์กเวอร์ชันที่ใหญ่ขึ้น

สถานะและข้อมูลเมตาของเพลเยอร์อาจเปลี่ยนแปลงได้ตลอดอายุของเซสชันสื่อ ทุกครั้งที่สถานะหรือข้อมูลเมตาเปลี่ยนแปลง คุณต้องใช้ Builder ที่เกี่ยวข้องสำหรับแต่ละคลาส PlaybackStateCompat.Builder() หรือ MediaMetadataCompat.Builder() แล้วส่งอินสแตนซ์ใหม่ไปยังเซสชันสื่อโดยเรียกใช้ setPlaybackState() หรือ setMetaData() เพื่อลดการใช้หน่วยความจำโดยรวมจากการดำเนินการที่เกิดขึ้นบ่อยครั้งเหล่านี้ ขอแนะนำให้สร้าง Builder เพียงครั้งเดียวและนำกลับมาใช้ซ้ำตลอดอายุของเซสชัน

สถานะและข้อผิดพลาด

โปรดทราบว่า PlaybackState เป็นออบเจ็กต์ที่มีค่าแยกต่างหากสำหรับสถานะการเล่นของเซสชัน (getState()) และรหัสข้อผิดพลาดที่เกี่ยวข้อง (getErrorCode()) เมื่อจำเป็น ข้อผิดพลาดอาจร้ายแรงหรือไม่ร้ายแรง ดังนี้

เมื่อใดก็ตามที่การเล่นหยุดชะงัก คุณควรสร้างข้อผิดพลาดร้ายแรง โดยตั้งค่าสถานะการส่งเป็น STATE_ERROR และระบุข้อผิดพลาดที่เกี่ยวข้องด้วย setErrorMessage(int, CharSequence) ตราบใดที่การเล่นยังถูกบล็อกโดยข้อผิดพลาด PlaybackState ควรรายงาน STATE_ERROR และข้อผิดพลาดต่อไป

ข้อผิดพลาดที่ไม่ร้ายแรงจะเกิดขึ้นเมื่อแอปไม่สามารถจัดการคำขอได้ แต่ยังคงเล่นต่อได้ โดยการส่งจะยังคงอยู่ในสถานะ "ปกติ" (เช่น STATE_PLAYING) แต่ PlaybackState จะมีรหัสข้อผิดพลาด ตัวอย่างเช่น หากเพลงสุดท้ายกำลังเล่นอยู่และผู้ใช้ขอให้ข้ามไปยังเพลงถัดไป การเล่นจะดำเนินต่อไปได้ แต่คุณควรสร้าง PlaybackState ใหม่ที่มีรหัสข้อผิดพลาด ERROR_CODE_END_OF_QUEUE แล้วเรียกใช้ setPlaybackState() ตัวควบคุมสื่อที่แนบมากับเซสชันจะได้รับ Callback onPlaybackStateChanged() และอธิบายให้ผู้ใช้ทราบถึงสิ่งที่เกิดขึ้น ควรรายงานข้อผิดพลาดที่ไม่ร้ายแรงเพียงครั้งเดียวเมื่อเกิดข้อผิดพลาด ครั้งถัดไปที่เซสชันอัปเดต PlaybackState อย่าตั้งค่าข้อผิดพลาดที่ไม่ร้ายแรงเดียวกันอีก (เว้นแต่ข้อผิดพลาดจะเกิดขึ้นเพื่อตอบสนองต่อคำขอใหม่)

หน้าจอล็อกของเซสชันสื่อ

ตั้งแต่ Android 4.0 (ระดับ API 14) เป็นต้นไป ระบบจะเข้าถึงสถานะการเล่นและข้อมูลเมตาของเซสชันสื่อได้ หน้าจอล็อกจะแสดงตัวควบคุมสื่อและอาร์ตเวิร์กในลักษณะนี้ ลักษณะการทำงานจะแตกต่างกันไปตามเวอร์ชัน Android

ภาพปกอัลบั้ม

ใน Android 4.0 (ระดับ API 14) ถึง Android 10 (ระดับ API 29) พื้นหลังของหน้าจอล็อกจะแสดงภาพหน้าปกอัลบั้ม แต่จะแสดงก็ต่อเมื่อข้อมูลเมตาของเซสชันสื่อมีบิตแมปพื้นหลังเท่านั้น

การควบคุมการรับส่งข้อมูล

ใน Android 4.0 (API ระดับ 14) ถึง Android 4.4 (API ระดับ 19) เมื่อเซสชันสื่อทำงานอยู่และข้อมูลเมตาของเซสชันสื่อมีบิตแมปพื้นหลัง หน้าจอล็อกจะแสดงการควบคุมการส่งโดยอัตโนมัติ

ใน Android 5.0 (ระดับ API 21) ขึ้นไป ระบบจะไม่มีตัวควบคุมการรับส่งข้อมูลในหน้าจอล็อก แต่คุณควรใช้การแจ้งเตือน MediaStyle เพื่อแสดงตัวควบคุมการส่งแทน

เพิ่มการกระทำที่กำหนดเอง

แอปพลิเคชันสื่อสามารถกำหนดการกระทำที่กำหนดเองได้ เช่น กดชอบ กดถูกใจ หรือกรอกลับ 30 วินาที การดำเนินการที่กำหนดเองควรใช้ลักษณะการทำงานใหม่ทั้งหมด อย่าใช้การกระทำที่กำหนดเองเพื่อแทนที่การกระทำในการควบคุมการส่งข้อมูลมาตรฐานที่กำหนดไว้ใน PlaybackStateCompat

เพิ่มการดำเนินการที่กำหนดเองด้วย addCustomAction() ตัวอย่างต่อไปนี้แสดงวิธีเพิ่มการควบคุมสำหรับการดำเนินการกดชอบ

Kotlin

stateBuilder.addCustomAction(
        PlaybackStateCompat.CustomAction.Builder(
                CUSTOM_ACTION_THUMBS_UP,
                resources.getString(R.string.thumbs_up),
                thumbsUpIcon
        ).run {
            setExtras(customActionExtras)
            build()
        }
)

Java

stateBuilder.addCustomAction(new PlaybackStateCompat.CustomAction.Builder(
    CUSTOM_ACTION_THUMBS_UP, resources.getString(R.string.thumbs_up), thumbsUpIcon)
    .setExtras(customActionExtras)
    .build());

ดูตัวอย่างที่เสร็จสมบูรณ์ได้ที่ Universal Music Player

คุณตอบสนองต่อการดำเนินการด้วย onCustomAction()

Kotlin

override fun onCustomAction(action: String, extras: Bundle?) {
    when(action) {
        CUSTOM_ACTION_THUMBS_UP -> {
            ...
        }
    }
}

Java

@Override
public void onCustomAction(@NonNull String action, Bundle extras) {
    if (CUSTOM_ACTION_THUMBS_UP.equals(action)) {
        ...
    }
}

ดูข้อมูลเพิ่มเติมได้ที่เครื่องเล่นเพลงสากล

Callback ของเซสชันสื่อ

เมธอด Callback ของเซสชันสื่อหลักคือ onPlay(), onPause() และ onStop() ซึ่งเป็นที่ที่คุณเพิ่มโค้ดที่ควบคุมโปรแกรมเล่น

เนื่องจากคุณสร้างอินสแตนซ์และตั้งค่า Callback ของเซสชันที่รันไทม์ (ใน onCreate()) แอปจึงสามารถกำหนด Callback ทางเลือกที่ใช้เพลเยอร์ที่แตกต่างกัน และเลือกชุดค่าผสมของ Callback และเพลเยอร์ที่เหมาะสมโดยขึ้นอยู่กับอุปกรณ์และระดับระบบ คุณสามารถเปลี่ยนโปรแกรมเล่นได้โดยไม่ต้องเปลี่ยนส่วนที่เหลือของแอป เช่น คุณสามารถใช้ ExoPlayer เมื่อทำงานบน Android 4.1 (ระดับ API 16) ขึ้นไป และใช้ MediaPlayer ในระบบก่อนหน้า

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

การติดตั้งใช้งานเมธอด Callback ของเซสชันสื่อจะขึ้นอยู่กับโครงสร้างของแอป โปรดดูหน้าแยกต่างหากที่อธิบายวิธีใช้ Callback ในแอปเสียงและแอปวิดีโอ ซึ่งอธิบายวิธีติดตั้งใช้งาน Callback สำหรับแอปแต่ละประเภท