1. 程式人生 > >Android 多個應用之間聲音競爭之Android 系統處理音訊焦點(AudioFocus)

Android 多個應用之間聲音競爭之Android 系統處理音訊焦點(AudioFocus)

問題發現

最近在專案中發現我們的自己的apk和第三方的媒體apk會出現串音問題。即兩者之間的聲音會重疊在一起。

解決問題

1. 使用多媒體按鍵去控制第三方應用的聲音播放(無效果)

通過觸發媒體的按鈕來操作播放器狀態:KeyEvent.KEYCODE_MEDIA_PAUSE

public static void sendMediaButton(Context context, int keyCode) {
    AudioManager audioManager= (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
    //先判斷後臺是否再播放音樂
    if (audioManager.isMusicActive()){
        KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
        Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
        intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
        context.sendOrderedBroadcast(intent,null);

        keyEvent = new KeyEvent(KeyEvent.ACTION_UP, keyCode);
        intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
        intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
        context.sendOrderedBroadcast(intent,null);
    }
}

不知為什麼,使用後沒有效果。於是就有了以下的方法

2. 使用AudioFocus 音訊焦點(問題得到解決)

AudioFoucs 簡介

Android 開發中免不了需要播放視訊,音訊檔案,但是手機上可能有其他的一些軟體,在後臺播放音訊的時候,這個時候另外的軟體也需要播放音訊,這個時候就會出現倆個音訊同時播放的問題,在 Android2.2 之後提供了 audioFocus獲取音訊的焦點,但是這個並不是強制需要實現的,所以當你在測試的時候,有的應用沒有處理音訊焦點,所以會有和其他應用串音的現象。

個人認為這個 audiofocus 就類似於一個 flag 全域性變數一樣。然後各個應用根據這個值是設定自己的音訊要播放還是暫停。如果獲得了焦點,則可以播放,如果失去了焦點,則應該暫停正在播放的音訊。

AudioFocus 用法
AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
audioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC,AudioManager.AUDIOFOCUS_GAIN)

此處 requestAudioFocus後面第一引數傳null,是直接去請求音訊焦點的動作。當然這裡不建議這樣。這種太暴力。建議null這裡替換成一個listener監聽。然後通過去實現這個listener去監聽焦點的變化,從而去做一些暫停播放音樂的動作。

  audioManager.requestAudioFocus(mAudioFocusChange , AudioManager.STREAM_MUSIC,AudioManager.AUDIOFOCUS_GAIN)
private AudioManager.OnAudioFocusChangeListener mAudioFocusChange = new
AudioManager.OnAudioFocusChangeListener() {
@Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange){
    case AudioManager.AUDIOFOCUS_GAIN:
          //當其他應用申請焦點之後又釋放焦點會觸發此回撥
          //可重新播放音樂
         Log.d(TAG, "AUDIOFOCUS_GAIN");
         start();
         break;
    case AudioManager.AUDIOFOCUS_LOSS:
          //長時間丟失焦點,當其他應用申請的焦點為 AUDIOFOCUS_GAIN 時,
         //會觸發此回撥事件,例如播放 QQ 音樂,網易雲音樂等
         //通常需要暫停音樂播放,若沒有暫停播放就會出現和其他音樂同時輸出聲音
        Log.d(TAG, "AUDIOFOCUS_LOSS");
        stop();
       //釋放焦點,該方法可根據需要來決定是否呼叫
       //若焦點釋放掉之後,將不會再自動獲得
       mAudioManager.abandonAudioFocus(mAudioFocusChange);
       break;
    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
         //短暫性丟失焦點,當其他應用申請 AUDIOFOCUS_GAIN_TRANSIENT 或
         AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE 時,
        //會觸發此回撥事件,例如播放短視訊,撥打電話等。
         //通常需要暫停音樂播放
         stop();
        Log.d(TAG, "AUDIOFOCUS_LOSS_TRANSIENT");
        break;
    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
         //短暫性丟失焦點並作降音處理
       Log.d(TAG, "AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK");
       break;
                                       }
                  }
};

使用完後丟點焦點:

audioManager .abandonAudioFocus(mAudioFocusChange )