什么叫音頻焦點 (audio focus)?
android系統是一個多任務操作系統,因此同一時刻允許許多任務同時工作。但是這對音頻類應用來說是個挑戰,因為如果多個音頻同時播放的話,很多情況下用戶體驗會相當的差!比如聽音樂時,來了個電話,這時你的耳機里就是電話和音樂共同工作,絕對是個悲劇!
為了解決這個問題從android2.2開始引入audio focus的概念。當你需要播放音樂或者發送一個通知的時候,你可以去要求獲得音頻焦點。一旦獲得,就可以自由的使用音頻輸出設備。但是同時它也在時時刻刻的監聽着音頻焦點的變化。當音頻焦點變化時,你需要去合適的處理你的音頻輸出。
音頻焦點工作的示例:
第一步
首先你要獲得一個音頻管理服務AudioManager
mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
這個通常在service的oncreate中完成。
第二步
然后在合適的地方,比如播放音樂的按鈕中放置獲得音頻焦點的代碼
mAudioManager.requestAudioFocus(mAudioFocusListener,
AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
requestAudioFocus方法可以獲得音頻焦點,其有三個參數,解釋如下:
第一個參數 OnAudioFocusChangeListener:就是音頻焦點變化時的監聽器,這是音頻焦點控制的重點。
第二個參數streamType:焦點獲得之后的數據傳輸類型,這里是AudioManager.STREAM_MUSIC
第三個參數durationHint :告知系統,你要求獲得音頻焦點的用途,系統根據你所要求的類型來給其他監聽者發出相應的焦點控制參數。有三種可選
AUDIOFOCUS_GAIN_TRANSIENT:只是短暫獲得,一會就釋放焦點,比如你只是想發個notification時用下一秒不到的鈴聲。
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:只是背景獲得,之前的音頻焦點使用者無需釋放焦點給我,我將與其共同使用。
AUDIOFOCUS_GAIN:我要求完全獲得焦點,其他人需要釋放焦點。比如我要播放音樂了,這時就要搶占整個音頻焦點。
第三步
實現音頻焦點監聽器OnAudioFocusChangeListener,這個監聽器會根據當前音頻焦點的變化,調用onAudioFocusChange(int focusChange)方法,focusChange主要有以下四種參數:
AUDIOFOCUS_AGIN:你已經完全獲得了音頻焦點
AUDIOFOCUS_LOSS:你會長時間的失去焦點,所以不要指望在短時間內能獲得。請結束自己的相關音頻工作並做好收尾工作。比如另外一個音樂播放器開始播放音樂了(前提是這個另外的音樂播放器他也實現了音頻焦點的控制,baidu音樂,天天靜聽很遺憾的就沒有實現,所以他們兩個是可以跟別的播放器同時播放的)
AUDIOFOCUS_LOSS_TRANSIENT:你會短暫的失去音頻焦點,你可以暫停音樂,但不要釋放資源,因為你一會就可以奪回焦點並繼續使用
AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:你的焦點會短暫失去,但是你可以與新的使用者共同使用音頻焦點
具體示例如下:
private OnAudioFocusChangeListener mAudioFocusListener = new OnAudioFocusChangeListener(){ public void onAudioFocusChange(int focusChange) { switch(focusChange){ case AudioManager.AUDIOFOCUS_LOSS: if(isPlaying()){ //we do not need get focus back in this situation //會長時間失去,所以告知下面的判斷,獲得焦點后不要自動播放 mPausedByTransientLossOfFocus = false; pause();//因為會長時間失去,所以直接暫停 } break; case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: if(isPlaying()){ //短暫失去焦點,先暫停。同時將標志位置成重新獲得焦點后就開始播放 mPausedByTransientLossOfFocus = true; pause(); } break; case AudioManager.AUDIOFOCUS_GAIN: //重新獲得焦點,且符合播放條件,開始播放 if(!isPlaying()&&mPausedByTransientLossOfFocus){ mPausedByTransientLossOfFocus = false; resume(); } break; } }};
最后
在適當的時候注銷掉這個監聽器比如在onDestroy()中
mAudioManager.abandonAudioFocus(mAudioFocusListener);
到此整個音頻焦點的控制就完成了
講一個自己的故事,mPausedByTransientLossOfFocus 這個參數一開始沒理解有什么作用,就沒寫。直到發現,我的音樂播放器在我已經手動暫停的情況下,總是在我打完電話后自動播放音樂,才發現他的作用。打完電話,手機就這么一路唱着歌在我的口袋里二逼呵呵的歡樂着。自己還不知道,等再要用手機的時候發現電都被搞掉了不少,且無數人側目看我是一個怎樣的二貨喜歡外放音樂.....慶幸手機里沒有鳳凰傳奇的歌曲。
其實這個參數的作用就是可以讓播放器僅僅在短暫失去音頻焦點並重新獲得后才開始播放音樂。而不是任何時候重新獲得焦點都開始播放。
from :https://blog.csdn.net/codemydream/article/details/53434891