android音視頻指南-響應(yīng)媒體按鈕

翻譯自Responding to media buttons

媒體按鈕是Android設(shè)備和其他外圍設(shè)備上的硬件按鈕,例如藍(lán)牙耳機(jī)上的暫停/播放按鈕。當(dāng)用戶按下媒體按鈕時(shí),Android會(huì)生成一個(gè)KeyEvent,其中包含一個(gè)識(shí)別按鈕的密鑰代碼。media button KeyEvents的關(guān)鍵代碼是以KEYCODE_MEDIA開頭的常量(例如,KEYCODE_MEDIA_PLAY)。

應(yīng)用程序應(yīng)該能夠在三種情況下處理媒體按鈕事件,按優(yōu)先順序排列:

  • 當(dāng)應(yīng)用程序的UI活動(dòng)可見時(shí)
  • 當(dāng)UI活動(dòng)隱藏且應(yīng)用程序的媒體會(huì)話處于活動(dòng)狀態(tài)時(shí)
  • 當(dāng)UI活動(dòng)被隱藏,應(yīng)用程序的媒體會(huì)話不活躍,需要重新啟動(dòng)時(shí)

處理前臺(tái)活動(dòng)中的媒體按鈕

前臺(tái)活動(dòng)在其onKeyDown()方法中接收media button key事件。根據(jù)Android的運(yùn)行版本,系統(tǒng)有兩種方式將事件路由到媒體控制器:

  • 如果你運(yùn)行的是安卓5.0 (API level 21)或更高版本,調(diào)用FLAG_HANDLES_MEDIA_BUTTONS MediaBrowserCompat.ConnectionCallback.onConnected。這將自動(dòng)調(diào)用您的媒體控制器的dispatchMediaButtonEvent(),它將關(guān)鍵代碼轉(zhuǎn)換為媒體會(huì)話回調(diào)。
  • 在Android 5.0 (API level 21)之前,您需要修改onKeyDown()來自己處理事件。(有關(guān)詳細(xì)信息,請(qǐng)參閱Handling media buttons in an active media session。)下面的代碼片段展示了如何截獲關(guān)鍵代碼并調(diào)用dispatchMediaButtonEvent()。確保返回true以指示事件已處理:
@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);
    }

尋找媒體會(huì)話

如果前臺(tái)活動(dòng)不處理事件,Android將嘗試找到一個(gè)可以處理它的媒體會(huì)話。同樣,根據(jù)Android的運(yùn)行版本,有兩種方法可以搜索媒體會(huì)話:

  • 如果你運(yùn)行的是安卓8.0 (API level 26)或更高版本,系統(tǒng)會(huì)試圖找到最后一個(gè)帶有本地播放音頻的MediaSession的應(yīng)用。如果會(huì)話仍然是活動(dòng)的,Android會(huì)將事件直接發(fā)送到它。否則,如果會(huì)話不是活動(dòng)的,并且它有一個(gè)mediabutton接收器,Android將事件發(fā)送給接收器,接收器將重新啟動(dòng)會(huì)話,因此它可以接收事件。(有關(guān)詳細(xì)信息,請(qǐng)參閱Using media buttons to restart an inactive media session 。)如果會(huì)話沒有媒體按鈕接收器,系統(tǒng)將丟棄媒體按鈕事件,并且什么也不會(huì)發(fā)生。邏輯如下圖所示:


    image
  • 在Android 8.0 (API級(jí)別26)之前,系統(tǒng)嘗試將事件發(fā)送到活動(dòng)媒體會(huì)話。如果有多個(gè)活動(dòng)媒體會(huì)話,Android會(huì)嘗試選擇準(zhǔn)備播放(緩沖/連接)、播放或暫停的媒體會(huì)話,而不是停止的。(有關(guān)更多細(xì)節(jié),請(qǐng)參見 Handling media buttons in an active media session。)如果沒有活動(dòng)會(huì)話,Android會(huì)嘗試將事件發(fā)送到最近的活動(dòng)會(huì)話。(有關(guān)詳細(xì)信息,請(qǐng)參閱使用Using media buttons to restart an inactive media session。)邏輯如下圖所示:
    image

處理活動(dòng)媒體會(huì)話中的媒體按鈕

在Android 5.0 (API level 21)及更高版本上,Android通過調(diào)用onMediaButtonEvent()自動(dòng)將媒體按鈕事件分派給您的活動(dòng)媒體會(huì)話。默認(rèn)情況下,此回調(diào)將KeyEvent轉(zhuǎn)換為與密鑰代碼匹配的適當(dāng)?shù)拿襟w會(huì)話回調(diào)方法。

在Android 5.0 (API level 21)之前,Android通過使用ACTION_MEDIA_BUTTON操作廣播一個(gè)意圖來處理媒體按鈕事件。你的應(yīng)用程序必須注冊(cè)一個(gè)廣播接收器來攔截這些意圖。MediaButtonReceiver類是專門為此目的設(shè)計(jì)的。它是Android media-compat庫中的一個(gè)方便類,它處理ACTION_MEDIA_BUTTON并將傳入的意圖轉(zhuǎn)換為適當(dāng)?shù)?code>MediaSessionCompat.Callback方法調(diào)用。

MediaButtonReceiver是一個(gè)短命的廣播接收器。它將傳入的意圖轉(zhuǎn)發(fā)給管理媒體會(huì)話的服務(wù)。如果你想在Android 5.0之前在系統(tǒng)中使用媒體按鈕,你必須在清單中包括MediaButtonReceiverMEDIA_BUTTON意圖過濾器。

<receiver android:name="android.support.v4.media.session.MediaButtonReceiver" >
   <intent-filter>
     <action android:name="android.intent.action.MEDIA_BUTTON" />
   </intent-filter>
 </receiver>

廣播接收器將意圖轉(zhuǎn)發(fā)給您的服務(wù)。要解析意圖并生成對(duì)媒體會(huì)話的回調(diào),請(qǐng)?jiān)诜?wù)的onStartCommand()中包含MediaButtonReceiver.handleIntent()方法。這將把關(guān)鍵代碼轉(zhuǎn)換為適當(dāng)?shù)臅?huì)話回調(diào)方法。

private MediaSessionCompat mMediaSessionCompat = ...;

public int onStartCommand(Intent intent, int flags, int startId) {
  MediaButtonReceiver.handleIntent(mMediaSessionCompat, intent);
  return super.onStartCommand(intent, flags, startId);
}

注意:如果您沒有MediaBrowserServiceCompat,您還可以向任何服務(wù)添加ACTION_MEDIA_BUTTON意圖過濾器。有關(guān)更多信息,請(qǐng)參閱MediaButtonReceiver文檔。

使用媒體按鈕重新啟動(dòng)非活動(dòng)的媒體會(huì)話

如果Android能夠識(shí)別最后一個(gè)活動(dòng)媒體會(huì)話,它會(huì)試圖通過發(fā)送一個(gè)ACTION_MEDIA_BUTTON意圖到一個(gè)聲明注冊(cè)的組件(如服務(wù)或廣播接收器)來重新啟動(dòng)會(huì)話。

這可以讓你的應(yīng)用在UI不可見時(shí)重啟回放,這是大多數(shù)音頻應(yīng)用的情況。

當(dāng)您使用MediaSessionCompat時(shí),將自動(dòng)啟用此行為。如果你使用Android框架的MediaSession或者Support Library 24.0.0到25.1.1,你必須調(diào)用setMediaButtonReceiver,讓媒體按鈕重新啟動(dòng)一個(gè)非活動(dòng)的媒體會(huì)話。

你可以通過設(shè)置一個(gè)空媒體按鈕接收器,在Android 5.0 (API級(jí)別21)或更高版本中禁用此行為:

// Create a MediaSessionCompat
mMediaSession = new MediaSessionCompat(context, LOG_TAG);
mMediaSession.setMediaButtonReceiver(null);

注意:對(duì)于在Android 5.0 (API level 21)之前的系統(tǒng)中運(yùn)行的應(yīng)用程序,您注冊(cè)以處理活動(dòng)會(huì)話的媒體按鈕的MediaButtonReceiver也會(huì)在會(huì)話不活動(dòng)時(shí)接收媒體按鈕事件。無法禁用此行為。

定制媒體按鈕處理程序

onMediaButtonEvent()的默認(rèn)行為提取關(guān)鍵代碼并使用媒體會(huì)話的當(dāng)前狀態(tài)和支持的操作列表來確定調(diào)用哪個(gè)方法。例如,KEYCODE_MEDIA_PLAY調(diào)用onPlay()。

為了在所有應(yīng)用程序中提供一致的媒體按鈕體驗(yàn),您應(yīng)該使用默認(rèn)行為,并且只為了特定的目的而偏離。如果媒體按鈕需要自定義處理,重寫回調(diào)函數(shù)的onMediaButtonEvent()方法,使用intent.getparcelableextra (Intent.EXTRA_KEY_EVENT)提取KeyEvent,自己處理事件,并返回true。

總結(jié)

要正確處理Android所有版本中的媒體按鈕事件,必須在創(chuàng)建媒體會(huì)話時(shí)指定FLAG_HANDLES_MEDIA_BUTTONS。

此外,根據(jù)您計(jì)劃支持的Android版本,您還必須滿足以下要求:

運(yùn)行Android 5.0或更高版本時(shí):

  • 從媒體控制器onConnected()回調(diào)中調(diào)用MediaControllerCompat.setMediaController()
  • 要允許媒體按鈕重新啟動(dòng)非活動(dòng)會(huì)話,可以通過調(diào)用setMediaButtonReceiver()并傳遞PendingIntent動(dòng)態(tài)創(chuàng)建MediaButtonReceiver

當(dāng)系統(tǒng)運(yùn)行時(shí)間早于Android 5.0時(shí):

  • 重寫活動(dòng)的onKeyDown()以處理媒體按鈕
  • 靜態(tài)創(chuàng)建一個(gè)MediaButtonReceiver通過添加它到應(yīng)用程序的清單
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容