媒體按鈕是 Android 裝置和其他週邊裝置的硬體按鈕,例如藍牙耳機上的暫停/播放按鈕。當使用者按下媒體按鈕時,Android 會產生 KeyEvent
,其中包含用於識別按鈕的按鍵碼。媒體按鈕 KeyEvents 的按鍵碼是開頭為 KEYCODE_MEDIA
(例如 KEYCODE_MEDIA_PLAY
) 的常數。
應用程式應該要能依照下列順序,在三種情況下處理媒體按鈕事件 優先順序:
- 當應用程式的 UI 活動顯示時
- 隱藏 UI 活動,且應用程式的媒體工作階段已啟用時
- 使用者介面活動已隱藏,且應用程式的媒體工作階段已閒置且需要重新啟動時
處理前景活動中的媒體按鈕
前景活動會在其 onKeyDown()
中收到媒體按鈕的重要事件
方法。視 Android 的執行版本而定,系統會將事件轉送至以下兩種方式:
媒體控制器:
- 如果您使用 Android 5.0 (API 級別 21) 以上版本,請呼叫
FLAG_HANDLES_MEDIA_BUTTONS
MediaBrowserCompat.ConnectionCallback.onConnected
。這將 自動呼叫媒體控制器的dispatchMediaButtonEvent()
, 將按鍵程式碼轉譯為媒體工作階段回呼。 - 在 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 裝置上,有兩種方法可以搜尋媒體工作階段:
如果使用 Android 8.0 (API 級別 26) 以上版本,系統會嘗試 找出最後一個含有 MediaSession 在本機播放音訊的應用程式。如果工作階段 Android 仍會將事件直接傳送給該活動。否則,如果 工作階段未啟用,且含有媒體按鈕接收器,Android 會傳送事件 來重新啟動工作階段,以便接收事件。 (詳情請參閱使用媒體按鈕重新啟動閒置的媒體工作階段)。 如果工作階段沒有媒體按鈕接收器,系統就會捨棄媒體 按鈕事件,畫面上也不會出現任何回應。邏輯如下所示 圖表:
在 Android 8.0 (API 級別 26) 以下版本中,系統會嘗試將事件傳送至 活動媒體工作階段。如有多個執行中的媒體工作階段,Android 會嘗試 即可選擇準備播放的媒體工作階段 (緩衝處理/連線); 而不是已經停止的播放或暫停(詳情請參閱 處理進行中的媒體工作階段中的媒體按鈕 )。如果沒有啟用 Android 就會嘗試將事件傳送至最近使用的工作階段。 (詳情請參閱使用媒體按鈕重新啟動閒置的媒體工作階段)。 邏輯如下圖所示:
處理有效媒體工作階段中的媒體按鈕
在 Android 5.0 (API 級別 21) 以上版本中,Android 會透過呼叫,自動將媒體按鈕事件分派到執行中的媒體工作階段
onMediaButtonEvent()
。
根據預設,此回呼會將 KeyEvent 轉譯為與按鍵程式碼相符的適當媒體工作階段回呼方法。
在 Android 5.0 (API 級別 21) 以下版本中,Android 會透過廣播意圖處理媒體按鈕事件
執行 ACTION_MEDIA_BUTTON
動作。您的應用程式必須註冊
BroadcastReceiver 可攔截這些意圖。
MediaButtonReceiver
這堂課程專為
。這是在
Android
media-compat 程式庫
會處理 ACTION_MEDIA_BUTTON
,並將傳入的 Intent 轉譯為
適當的 MediaSessionCompat.Callback
方法呼叫
MediaButtonReceiver
是短期的 BroadcastReceiver。它會轉寄傳入的
呼叫及管理媒體工作階段的服務。如要使用
如果是 Android 5.0 以下版本的系統,請務必加入媒體按鈕,
透過 MEDIA_BUTTON
意圖篩選器,取得資訊清單中的 MediaButtonReceiver
。:
<receiver android:name="android.support.v4.media.session.MediaButtonReceiver" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
BroadcastReceiver
會將意圖轉送至您的服務。剖析意圖
然後產生媒體工作階段的回呼,在服務的 onStartCommand()
中加入 MediaButtonReceiver.handleIntent()
方法。
這項作業會將金鑰程式碼轉譯為適當的工作階段回呼方法。
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 可以找出上次進行中的媒體工作階段,就會嘗試傳送 ACTION_MEDIA_BUTTON
意圖至已註冊資訊清單的元件 (例如服務或 BroadcastReceiver
),藉此重新啟動工作階段。
這可讓應用程式在顯示 UI 時重新啟動播放,這對於大多數音訊應用程式而言都是如此。
使用 MediaSessionCompat
時,系統會自動啟用這項行為。如果發生以下情況:
使用 Android 架構的 MediaSession
或支援資料庫 24.0.0 版
25.1.1 您必須呼叫 setMediaButtonReceiver
,讓媒體按鈕重新啟動
閒置媒體工作階段。
您可以在 Android 5.0 (API 級別 21) 以上版本中停用這項行為,方法如下: 設定空值的媒體按鈕接收器:
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 以上版本中執行時:
- 從媒體控制器
onConnected()
回呼呼叫MediaControllerCompat.setMediaController()
- 如要允許媒體按鈕重新啟動閒置的工作階段,請呼叫以下程式碼,以動態方式建立
MediaButtonReceiver
:setMediaButtonReceiver()
並向其傳遞PendingIntent
在 Android 5.0 以下版本的系統中執行時:
- 覆寫活動的
onKeyDown()
來處理媒體按鈕 - 以靜態方式建立
MediaButtonReceiver
,方法是將其新增至應用程式資訊清單