前兩天在項目上做了對音頻焦點使用方法的一個總結,記錄在下面。
在Android裝置上,預設可以有多個應用同時播放音頻,但是,這種處理帶來的使用者體驗并不好,為了解決這個問題,Android引入了音頻焦點機制,一次隻能有一個App持有音頻焦點。
一般情況下,當一個App失去音頻焦點時,為了有較好的使用者體驗,它應該主動暫停播放,進而使新獲得音頻焦點的App可以清晰的播放音頻,避免混音的情況。
處理音頻焦點一些規則
以下是官方建議的處理音頻焦點應該遵循的一些規則:
在開始播放之前,調用requestAudioFocus()方法,并檢查傳回值是否是AUDIOFOCUS_REQUEST_GRANTED,若成功擷取,則開始播放。
當App失去音頻焦點時,根據失去的焦點類型,應該暫停播放,或者将音量調低。
當播放結束時,釋放音頻焦點。
如何處理音頻焦點
處理音頻焦點都是通過AudioManager這個類,如下是獲得該類執行個體的方法:
AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
下面介紹音頻焦點處理相關的一些方法(不同的Android版本處理音頻焦點的方式略有差别,以下内容基于Android 4.4)。
requestAudioFocus():用于申請音頻焦點
abandonAudioFocus():用于釋放音頻焦點
AudioManager.OnAudioFocusChangeListener接口,提供了onAudioFocusChange()方法來監聽音頻焦點變化
下面進行詳細介紹。
requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint)
參數:
AudioManager.OnAudioFocusChangeListener l
用于監聽音頻焦點變化,進而可以進行适當的操作,例如暫停播放等。
streamType
申請音頻焦點處理的音頻類型,例如,當播放音樂時,可以傳入STREAM_MUSIC;當播放鈴聲時,可以傳入STREAM_RING。表中列出了所有的可選值:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI3EWO5QzYwYTYlZjMvwFcvwVbvNmL1h2cuFWaq5yd3d3Lc9CX6MHc0RHaiojIsJye.jpg)
streamType可選類型
durationHint
可選值有以下五個:
(1) AUDIOFOCUS_GAIN: 此參數表示希望申請一個永久的音頻焦點,并且希望上一個持有音頻焦點的App停止播放;例如在需要播放音樂時。
(2) AUDIOFOCUS_GAIN_TRANSIENT:表示申請一個短暫的音頻焦點,并且馬上就會被釋放,此時希望上一個持有音頻焦點的App暫停播放。例如播放一個提醒聲音。
(3) AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:效果同AUDIOFOCUS_GAIN_TRANSIENT,隻是希望上一個持有焦點的App減小其播放聲音(但仍可以播放),此時會混音播放。例如導航播報。
(4) AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE: 表示申請一個短暫的音頻焦點,并且會希望系統不要播放任何突然的聲音(例如通知,提醒等),例如使用者在錄音。
傳回值:
AUDIOFOCUS_REQUEST_GRANTED或者AUDIOFOCUS_REQUEST_FAILED
2. abandonAudioFocus(OnAudioFocusChangeListener l)
參數同上。
傳回值同上。
3. AudioManager.OnAudioFocusChangeListener
當音頻焦點發生變化時,可以在OnAudioFocusChangeListener的onAudioFocusChange(int focusChange)方法中監聽到,下面詳細說明該方法。
onAudioFocusChange(int focusChange)
參數:focusChange可以表明目前音頻焦點發生的是何種變化,需要根據該參數狀态做出正确的響應。
分為獲得和丢失兩種情況:
獲得:AUDIOFOCUS_GAIN
表示獲得音頻焦點,此時應該開始播放
丢失音頻焦點,這時分為以下兩種情況:
短暫的丢失:
如果focusChange的值是AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK 或者 AUDIOFOCUS_LOSS_TRANSIENT時,你的App需要降低播放音量 或者暫停播放(但是需要記錄目前的播放狀态,以便後續恢複播放)。
在短暫丢失焦點期間,你的App應該持續關注音頻焦點的變化,當再次獲得焦點時,恢複播放。
永久的丢失
若值為AUDIOFOCUS_LOSS,你的App應該立即停止播放,并且當再次獲得音頻焦點時,也不會恢複播放,隻有當使用者主動播放時,再開始播放。
示例
下面是一個申請長音頻焦點,播放音樂的例子:
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
}
// 當播放完成時,建議調用abandonAudioFocus()方法來釋放音頻焦點,
// 通知系統目前App不再需要音頻焦點,解除OnAudioFocusChangeListener的注冊。
// Abandon audio focus when playback complete
am.abandonAudioFocus(afChangeListener);
以上