ปุ่มสื่อเป็นปุ่มฮาร์ดแวร์ที่พบในอุปกรณ์ Android และอุปกรณ์ต่อพ่วงอื่นๆ เช่น ปุ่มหยุดชั่วคราว/เล่นบนชุดหูฟังบลูทูธ เมื่อผู้ใช้กดปุ่มสื่อ Android จะสร้าง KeyEvent
ซึ่งมีรหัสคีย์ที่ระบุปุ่มดังกล่าว รหัสคีย์สำหรับปุ่มสื่อ KeyEvent เป็นค่าคงที่ที่ขึ้นต้นด้วย KEYCODE_MEDIA
(เช่น KEYCODE_MEDIA_PLAY
)
แอปควรสามารถจัดการเหตุการณ์ปุ่มสื่อได้ใน 3 กรณี โดยเรียงตามลำดับดังนี้ ลำดับความสำคัญ:
- เมื่อกิจกรรม UI ของแอปปรากฏ
- เมื่อกิจกรรม UI ซ่อนอยู่และเซสชันสื่อของแอปทำงานอยู่
- เมื่อกิจกรรม UI ซ่อนอยู่และเซสชันสื่อของแอปไม่มีการใช้งานและต้องรีสตาร์ท
การจัดการปุ่มสื่อในกิจกรรมที่ทำงานอยู่เบื้องหน้า
กิจกรรมเบื้องหน้าได้รับเหตุการณ์สำคัญของปุ่มสื่อในonKeyDown()
มี 2 วิธีในการกำหนดเส้นทางเหตุการณ์ ทั้งนี้ขึ้นอยู่กับเวอร์ชัน Android ที่ใช้งานอยู่
ตัวควบคุมสื่อ
- หากคุณใช้ Android 5.0 (API ระดับ 21) ขึ้นไป โปรดโทร
FLAG_HANDLES_MEDIA_BUTTONS
MediaBrowserCompat.ConnectionCallback.onConnected
การดำเนินการนี้จะ เรียกตัวควบคุมสื่อdispatchMediaButtonEvent()
, ซึ่งจะแปลโค้ดคีย์เป็น Callback ของเซสชันสื่อ - เวอร์ชันก่อนหน้า Android 5.0 (API ระดับ 21) คุณต้องแก้ไข
onKeyDown()
เพื่อจัดการ ของเหตุการณ์ด้วยตัวคุณเอง (ดูรายละเอียดได้ที่การจัดการปุ่มสื่อในเซสชันสื่อที่ใช้งานอยู่) ข้อมูลโค้ดต่อไปนี้แสดงวิธีสกัดกั้น รหัสคีย์และการเรียกใช้ DispatchMediaButtonEvent() อย่าลืมนำtrue
กลับไปยัง ระบุว่ามีการจัดการกิจกรรมแล้ว ดังนี้Kotlin
fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { return super.onKeyDown(keyCode, event) } when (keyCode) { KeyEvent.KEYCODE_MEDIA_PLAY -> { yourMediaController.dispatchMediaButtonEvent(event) return true } } return super.onKeyDown(keyCode, event) }
Java
@Override boolean onKeyDown(int keyCode, KeyEvent event) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { return super.onKeyDown(keyCode, event); } switch (keyCode) { case KeyEvent.KEYCODE_MEDIA_PLAY: yourMediaController.dispatchMediaButtonEvent(event); return true; } return super.onKeyDown(keyCode, event); }
การค้นหาเซสชันสื่อ
หากกิจกรรมเบื้องหน้าไม่สามารถจัดการกิจกรรมได้ Android จะพยายามหา เซสชันสื่อที่จัดการได้ เช่นเดียวกัน ทั้งนี้ขึ้นอยู่กับรุ่นที่ใช้งานอยู่ของ สำหรับ Android คุณสามารถค้นหาเซสชันสื่อได้ 2 วิธีดังนี้
หากคุณใช้ Android 8.0 (API ระดับ 26) ขึ้นไป ระบบจะพยายาม หาแอปล่าสุดที่มี MediaSession ที่เล่นเสียงในเครื่อง หากเซสชัน ยังคงใช้งานอยู่ Android จะส่งเหตุการณ์ไปยังเหตุการณ์โดยตรง มิเช่นนั้น หาก เซสชันไม่ได้ใช้งานอยู่และมีตัวรับปุ่มสื่อ Android จะส่งเหตุการณ์ ให้กับผู้รับ ซึ่งจะเริ่มต้นเซสชันใหม่และรับเหตุการณ์ได้ (โปรดดูรายละเอียดที่หัวข้อการใช้ปุ่มสื่อเพื่อเริ่มเซสชันสื่อที่ไม่ได้ใช้งานใหม่) หากเซสชันไม่มีตัวรับปุ่มสื่อ ระบบจะทิ้งสื่อนั้น เหตุการณ์ของปุ่มและจะไม่มีอะไรเกิดขึ้น ตรรกะจะแสดงในข้อมูลต่อไปนี้ แผนภาพ:
เวอร์ชันก่อนหน้า Android 8.0 (API ระดับ 26) ระบบจะพยายามส่งเหตุการณ์ไปยัง เซสชันสื่อที่ใช้งานอยู่ หากมีเซสชันสื่อที่ใช้งานอยู่หลายเซสชัน Android จะพยายาม เพื่อเลือกเซสชันสื่อที่กำลังเตรียมเล่น (บัฟเฟอร์/เชื่อมต่อ) วิดีโอหยุดเล่น หรือหยุดชั่วคราว มากกว่าวิดีโอที่หยุดเล่น (โปรดดู การจัดการปุ่มสื่อในเซสชันสื่อที่ใช้งานอยู่ เพื่อดูรายละเอียดเพิ่มเติม) หากไม่มีรายการที่ใช้งานอยู่ เซสชัน Android จะพยายามส่งเหตุการณ์ไปยังเซสชันที่ใช้งานล่าสุด (โปรดดูรายละเอียดที่หัวข้อการใช้ปุ่มสื่อเพื่อเริ่มเซสชันสื่อที่ไม่ได้ใช้งานใหม่) ตรรกะจะแสดงในแผนภาพต่อไปนี้
การจัดการปุ่มสื่อในเซสชันสื่อที่ใช้งานอยู่
ใน Android 5.0 (API ระดับ 21) ขึ้นไป Android จะส่งเหตุการณ์ของปุ่มสื่อไปยังเซสชันสื่อที่ใช้งานอยู่โดยอัตโนมัติด้วยการเรียกใช้
onMediaButtonEvent()
โดยค่าเริ่มต้น Callback นี้จะแปล KeyEvent เป็นเมธอด Callback ของเซสชันสื่อที่เหมาะสมซึ่งตรงกับโค้ดคีย์
เวอร์ชันก่อนหน้า Android 5.0 (API ระดับ 21) Android จัดการเหตุการณ์ปุ่มสื่อด้วยการประกาศความตั้งใจ
ด้วยการดำเนินการ ACTION_MEDIA_BUTTON
แอปของคุณต้องลงทะเบียน
BroadcastReceiver เพื่อสกัดกั้นความตั้งใจเหล่านี้
MediaButtonReceiver
ได้รับการออกแบบมาสำหรับ
วัตถุประสงค์นี้ ซึ่งเป็นคลาสอำนวยความสะดวกใน
Android
ไลบรารีที่ทำงานร่วมกับสื่อนั้น
จัดการ ACTION_MEDIA_BUTTON
และแปลง Intent ที่เข้ามาใหม่เป็น
ในการเรียกเมธอด MediaSessionCompat.Callback
ที่เหมาะสม
MediaButtonReceiver
เป็น BroadcastReceiver ที่มีอายุสั้น ส่งต่อขาเข้า
บริการที่จัดการเซสชันสื่อของคุณ หากต้องการใช้
ปุ่มสื่อในระบบที่เก่ากว่า Android 5.0 คุณต้องมี
MediaButtonReceiver
ในไฟล์ Manifest ที่มีตัวกรอง Intent MEDIA_BUTTON
:
<receiver android:name="android.support.v4.media.session.MediaButtonReceiver" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
BroadcastReceiver
ส่งต่อ Intent ไปยังบริการของคุณ วิธีแยกวิเคราะห์ความตั้งใจ
และสร้างการติดต่อกลับไปยังเซสชันสื่อของคุณ ให้รวมเมธอด MediaButtonReceiver.handleIntent()
ใน onStartCommand()
ของบริการของคุณ
ซึ่งจะแปลโค้ดคีย์เป็นเมธอด Callback ของเซสชันที่เหมาะสม
Kotlin
private val mediaSessionCompat: MediaSessionCompat = ... override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { MediaButtonReceiver.handleIntent(mediaSessionCompat, intent) return super.onStartCommand(intent, flags, startId) }
Java
private MediaSessionCompat mediaSessionCompat = ...; public int onStartCommand(Intent intent, int flags, int startId) { MediaButtonReceiver.handleIntent(mediaSessionCompat, intent); return super.onStartCommand(intent, flags, startId); }
การใช้ปุ่มสื่อเพื่อรีสตาร์ทเซสชันสื่อที่ไม่ได้ใช้งาน
หาก Android ระบุเซสชันสื่อที่มีการใช้งานล่าสุดได้ ระบบจะพยายามรีสตาร์ทเซสชันโดยการส่ง Intent ของ ACTION_MEDIA_BUTTON
ไปยังคอมโพเนนต์ที่ลงทะเบียนไฟล์ Manifest (เช่น บริการหรือ BroadcastReceiver
)
ซึ่งจะช่วยให้แอปรีสตาร์ทการเล่นโดยที่ UI ไม่ปรากฏ ซึ่งมักเป็นกรณีที่แอปเสียงส่วนใหญ่
ระบบจะเปิดใช้ลักษณะการทำงานนี้โดยอัตโนมัติเมื่อคุณใช้ MediaSessionCompat
หากคุณ
ใช้ MediaSession
ของเฟรมเวิร์ก Android หรือ Support Library 24.0.0 ถึง
25.1.1 คุณต้องเรียกใช้ setMediaButtonReceiver
เพื่อให้ปุ่มสื่อรีสตาร์ท
เซสชันสื่อที่ไม่ได้ใช้งาน
คุณสามารถปิดลักษณะการทำงานนี้ใน Android 5.0 (API ระดับ 21) ขึ้นไปได้โดย การตั้งค่าตัวรับปุ่มสื่อ Null
Kotlin
// Create a MediaSessionCompat mediaSession = MediaSessionCompat(context, LOG_TAG) mediaSession.setMediaButtonReceiver(null)
Java
// Create a MediaSessionCompat mediaSession = new MediaSessionCompat(context, LOG_TAG); mediaSession.setMediaButtonReceiver(null);
การปรับแต่งเครื่องจัดการปุ่มสื่อ
ลักษณะการทำงานเริ่มต้นของ onMediaButtonEvent()
จะดึงโค้ดของคีย์ออกมา และใช้สถานะปัจจุบันของเซสชันสื่อและรายการการดำเนินการที่รองรับเพื่อกำหนดวิธีการที่จะเรียกใช้ ตัวอย่างเช่น KEYCODE_MEDIA_PLAY
จะเรียกใช้ onPlay()
หากต้องการมอบประสบการณ์การใช้งานปุ่มสื่อที่สอดคล้องกันในทุกแอป คุณควรใช้
พฤติกรรมที่เป็นค่าเริ่มต้นและจะเบี่ยงเบนไปเพื่อจุดประสงค์ที่เจาะจงเท่านั้น หากเป็นปุ่มสื่อ
ซึ่งต้องการการจัดการที่กำหนดเอง
onMediaButtonEvent()
ให้ดึงข้อมูล KeyEvent
โดยใช้
intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT)
,
จัดการเหตุการณ์ด้วยตนเอง แล้วกลับไปที่ true
สรุป
หากต้องการจัดการเหตุการณ์ปุ่มสื่ออย่างเหมาะสมใน Android ทุกเวอร์ชัน คุณต้องทำดังนี้
ระบุ FLAG_HANDLES_MEDIA_BUTTONS
เมื่อคุณสร้างเซสชันสื่อ
นอกจากนี้ ขึ้นอยู่กับเวอร์ชัน Android ที่คุณวางแผนจะรองรับ คุณต้องมีคุณสมบัติตามข้อกำหนดต่อไปนี้ด้วย
เมื่อใช้ Android 5.0 ขึ้นไป
- เรียก
MediaControllerCompat.setMediaController()
จาก CallbackonConnected()
ของตัวควบคุมสื่อ - หากต้องการอนุญาตให้ปุ่มสื่อเริ่มเซสชันที่ไม่ได้ใช้งานอีกครั้ง ให้สร้าง
MediaButtonReceiver
แบบไดนามิกด้วยการเรียกใช้setMediaButtonReceiver()
และส่งต่อPendingIntent
เมื่อทำงานในระบบที่เก่ากว่า Android 5.0:
- ลบล้าง
onKeyDown()
ของกิจกรรมเพื่อจัดการปุ่มสื่อ - สร้าง
MediaButtonReceiver
แบบคงที่โดยเพิ่มลงในไฟล์ Manifest ของแอป