前兩天在項目上做了對音頻焦點使用方法的一個總結(jié),記錄在下面。
在Android設(shè)備上,默認可以有多個應(yīng)用同時播放音頻,但是,這種處理帶來的用戶體驗并不好,為了解決這個問題,Android引入了音頻焦點機制,一次只能有一個App持有音頻焦點。
一般情況下,當(dāng)一個App失去音頻焦點時,為了有較好的用戶體驗,它應(yīng)該主動暫停播放,從而使新獲得音頻焦點的App可以清晰的播放音頻,避免混音的情況。
處理音頻焦點一些規(guī)則
以下是官方建議的處理音頻焦點應(yīng)該遵循的一些規(guī)則:
- 在開始播放之前,調(diào)用requestAudioFocus()方法,并檢查返回值是否是AUDIOFOCUS_REQUEST_GRANTED,若成功獲取,則開始播放。
- 當(dāng)App失去音頻焦點時,根據(jù)失去的焦點類型,應(yīng)該暫停播放,或者將音量調(diào)低。
- 當(dāng)播放結(jié)束時,釋放音頻焦點。
如何處理音頻焦點
處理音頻焦點都是通過AudioManager這個類,如下是獲得該類實例的方法:
AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
下面介紹音頻焦點處理相關(guān)的一些方法(不同的Android版本處理音頻焦點的方式略有差別,以下內(nèi)容基于Android 4.4)。
- requestAudioFocus():用于申請音頻焦點
- abandonAudioFocus():用于釋放音頻焦點
- AudioManager.OnAudioFocusChangeListener接口,提供了onAudioFocusChange()方法來監(jiān)聽音頻焦點變化
下面進行詳細介紹。
-
requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint)
參數(shù):- AudioManager.OnAudioFocusChangeListener l
用于監(jiān)聽音頻焦點變化,從而可以進行適當(dāng)?shù)牟僮?,例如暫停播放等?/li> -
streamType
申請音頻焦點處理的音頻類型,例如,當(dāng)播放音樂時,可以傳入STREAM_MUSIC;當(dāng)播放鈴聲時,可以傳入STREAM_RING。表中列出了所有的可選值:
streamType可選類型 - durationHint
可選值有以下五個:
(1) AUDIOFOCUS_GAIN: 此參數(shù)表示希望申請一個永久的音頻焦點,并且希望上一個持有音頻焦點的App停止播放;例如在需要播放音樂時。
(2) AUDIOFOCUS_GAIN_TRANSIENT:表示申請一個短暫的音頻焦點,并且馬上就會被釋放,此時希望上一個持有音頻焦點的App暫停播放。例如播放一個提醒聲音。
(3) AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:效果同AUDIOFOCUS_GAIN_TRANSIENT,只是希望上一個持有焦點的App減小其播放聲音(但仍可以播放),此時會混音播放。例如導(dǎo)航播報。
(4) AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE: 表示申請一個短暫的音頻焦點,并且會希望系統(tǒng)不要播放任何突然的聲音(例如通知,提醒等),例如用戶在錄音。
返回值:
AUDIOFOCUS_REQUEST_GRANTED或者AUDIOFOCUS_REQUEST_FAILED
- AudioManager.OnAudioFocusChangeListener l
2. abandonAudioFocus(OnAudioFocusChangeListener l)
參數(shù)同上。
返回值同上。
3. AudioManager.OnAudioFocusChangeListener
當(dāng)音頻焦點發(fā)生變化時,可以在OnAudioFocusChangeListener的onAudioFocusChange(int focusChange)方法中監(jiān)聽到,下面詳細說明該方法。
onAudioFocusChange(int focusChange)
參數(shù):focusChange可以表明當(dāng)前音頻焦點發(fā)生的是何種變化,需要根據(jù)該參數(shù)狀態(tài)做出正確的響應(yīng)。
分為獲得和丟失兩種情況:
- 獲得:AUDIOFOCUS_GAIN
表示獲得音頻焦點,此時應(yīng)該開始播放 - 丟失音頻焦點,這時分為以下兩種情況:
- 短暫的丟失:
如果focusChange的值是AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK 或者 AUDIOFOCUS_LOSS_TRANSIENT時,你的App需要降低播放音量 或者暫停播放(但是需要記錄當(dāng)前的播放狀態(tài),以便后續(xù)恢復(fù)播放)。
在短暫丟失焦點期間,你的App應(yīng)該持續(xù)關(guān)注音頻焦點的變化,當(dāng)再次獲得焦點時,恢復(fù)播放。 - 永久的丟失
若值為AUDIOFOCUS_LOSS,你的App應(yīng)該立即停止播放,并且當(dāng)再次獲得音頻焦點時,也不會恢復(fù)播放,只有當(dāng)用戶主動播放時,再開始播放。
- 短暫的丟失:
示例
下面是一個申請長音頻焦點,播放音樂的例子:
AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
AudioManager.OnAudioFocusChangeListener afChangeListener =
new AudioManager.OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
// Permanent loss of audio focus
// Pause playback immediately
mediaController.getTransportControls().pause();
mediaController.getTransportControls().stop();
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
// Pause playback
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
// Lower the volume, keep playing
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
// Your app has been granted audio focus again
// Raise volume to normal, restart playback if necessary
}
}
};
...
...
// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
// Use the music stream.
AudioManager.STREAM_MUSIC,
// Request permanent focus.
AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
// Start playback
}
// 當(dāng)播放完成時,建議調(diào)用abandonAudioFocus()方法來釋放音頻焦點,
// 通知系統(tǒng)當(dāng)前App不再需要音頻焦點,解除OnAudioFocusChangeListener的注冊。
// Abandon audio focus when playback complete
am.abandonAudioFocus(afChangeListener);
以上
