Android中的Audio播放:控制Audio輸出通道切換
2012-04-03
Audio 輸出通道有很多,Speaker、headset、bluetooth A2DP等。通話或播放音樂等使用Audio輸出過程中,可能發生Audio輸出通道的切換。比如,插入有線耳機播放音樂時,聲音是從耳機發出的;而此時拔出耳機,Audio輸出通道會發生切換。如果音樂播放器不做處理,Audio輸出是被切換到揚聲器的,聲音直接從Speaker發出。我們在編寫程式時,要捕獲並按照需求來處理這樣的事,本文就是講解如何處理的。
Android中可以通過android.media.AudioManager查詢當前Audio輸出的情況,並且在Audio輸出發生變化時,捕獲並處理這種變化。
一、Audio輸出狀態查詢與控制
android.media.AudioManager提供的下列方法可以用來查詢當前Audio輸出的狀態:
- isBluetoothA2dpOn():檢查A2DPAudio是否通過藍芽耳機;
- isSpeakerphoneOn():檢查揚聲器是否開啟;
- isWiredHeadsetOn():檢查線控耳機是否連著;注意這個方法只是用來判斷耳機是否是插入狀態,並不能用它的結果來判定當前的Audio是通過耳機輸出的,這還依賴於其他條件。
另外還有一些設定這些Audio輸出的setXYZ()方法,這些方法在一般使用Audio輸出的應用程式不要直接呼叫,他們由系統來管理,實現Audio輸出通道的自動切換。除非,介面提供給使用者切換的選單或按鈕,而使用者選擇了卻換,比如要直接選擇揚聲器發聲,可直接呼叫setSpeakerphoneOn()。
二、Audio輸出通道切換的事件的捕獲與處理
因為耳機插拔、藍芽耳機的斷開,Audio輸出通路會自動切換。此時正在播放Audio的程式要獲得通知,知道這一事件的發生。Android中是通過廣播ACTION_AUDIO_BECOMING_NOISY這個Intent通知的。
處理廣播的較好的方式,是動態註冊/登出自己所關心的廣播。下面程式碼演示了,開始播放時註冊廣播的Receiver;停止播放時登出廣播的Receiver。對Audio輸出通道切換的處理是暫停當前的播放,不直接從新的通道里發出聲來。
private class NoisyAudioStreamReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) { // Pause the playback } } } private IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY); private void startPlayback() { registerReceiver(myNoisyAudioStreamReceiver(), intentFilter); } private void stopPlayback() { unregisterReceiver(myNoisyAudioStreamReceiver); }
三、Audio輸出通道切換的典型場景—— 用耳機聽音樂時,拔出耳機
聽耳機聽音樂時,耳機別拔出的時序圖如下:
圖中:
- AudioNoisy Client註冊了偵聽廣播AudioManager.ACTION_AUDIO_BECOMING_NOISY[Step#1 ~ #2];
- 用耳機一直在聽音樂;
- HeadsetObserver一直在監視耳機狀態的變化。檢測到耳機被拔出之後,發出廣播AudioManager.ACTION_AUDIO_BECOMING_NOISY[Step#3~4];
- AudioNoisy Client收到了廣播,傳送暫停命令給MediaPaybackService去暫停當前的播放 [Step#5~6]。
小結
Audio 輸出通道切換時,要根據具體需求來做相應的處理。