การตอบสนองต่อปุ่มสื่อ

ปุ่มสื่อเป็นปุ่มฮาร์ดแวร์ที่พบในอุปกรณ์ 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 กลับไปยัง ระบุว่ามีการจัดการกิจกรรมแล้ว ดังนี้
    KotlinJava
        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)
       
    }
       
        @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 ของเซสชันที่เหมาะสม

KotlinJava
private val mediaSessionCompat: MediaSessionCompat = ...

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
   
MediaButtonReceiver.handleIntent(mediaSessionCompat, intent)
   
return super.onStartCommand(intent, flags, startId)
}
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

KotlinJava
// Create a MediaSessionCompat
mediaSession
= MediaSessionCompat(context, LOG_TAG)
mediaSession
.setMediaButtonReceiver(null)
// 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() จาก Callback onConnected() ของตัวควบคุมสื่อ
  • หากต้องการอนุญาตให้ปุ่มสื่อเริ่มเซสชันที่ไม่ได้ใช้งานอีกครั้ง ให้สร้าง MediaButtonReceiver แบบไดนามิกด้วยการเรียกใช้ setMediaButtonReceiver() และส่งต่อ PendingIntent

เมื่อทำงานในระบบที่เก่ากว่า Android 5.0:

  • ลบล้าง onKeyDown() ของกิจกรรมเพื่อจัดการปุ่มสื่อ
  • สร้าง MediaButtonReceiver แบบคงที่โดยเพิ่มลงในไฟล์ Manifest ของแอป