針對問題:使用雲信IM, 帶耳機時,來電鈴聲還是會外放
本文主要内容
1.如何通過耳機播放來電鈴聲
2.如果來電鈴聲播放之前,耳機播放音樂,如何解決鈴聲和音樂同時播放的問題
問題一:
首先雲信IM來電鈴聲是通過AVChatSoundPlayer來播放的,
解決外放問題,需要将
SoundPool
初始化的傳參從
AudioManager.STREAM_RING
改成
AudioManager.STREAM_MUSIC
因為系統鈴聲模式,預設就是外放的
而音樂模式,連接配接了耳機會通過耳機播放鈴聲
代碼
private void initSoundPool() {
stop();
if (soundPool == null) {
soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
soundPool.setOnLoadCompleteListener(onLoadCompleteListener);
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
ringMode = audioManager.getRingerMode();
}
registerVolumeReceiver(true);
}
問題二:
如果來電之前,耳機播放音樂,
我們可以通過設定目前
AudioManager
擷取焦點
當鈴聲播放時,我們就能停止音樂,或者音樂作為背景音播放
設定代碼
audioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
參數1:
OnAudioFocusChangeListener
我們沒有焦點監聽需求,直接傳null
參數2:
streamType
哪種音頻類型擷取焦點(因為我們
SoundPool
使用了
STREAM_MUSIC
我們這裡也指定
STREAM_MUSIC
類型)
參數3: 擷取焦點的音頻通過哪種方式播放(請參考文末屬性表)
如果通話完成,或者拒絕接聽後,還想繼續自動播放耳機的音樂
可以通過
audioManager.abandonAudioFocus(null);
放棄音頻焦點。使上一個焦點所有者(如果有)接收焦點,這樣音樂就會自動播放了
參數也是
OnAudioFocusChangeListener
我修改的完整代碼
public void stop() {
LogUtil.d(TAG, "stop");
if (soundPool != null) {
if (streamId != 0) {
soundPool.stop(streamId);
streamId = 0;
}
if (soundId != 0) {
soundPool.unload(soundId);
soundId = 0;
}
}
if (isRingModeRegister) {
registerVolumeReceiver(false);
}
if (audioManager != null) {
audioManager.abandonAudioFocus(null);
}
}
private void initSoundPool() {
stop();
if (soundPool == null) {
soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
soundPool.setOnLoadCompleteListener(onLoadCompleteListener);
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
ringMode = audioManager.getRingerMode();
}
audioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
registerVolumeReceiver(true);
}
代碼中
audioManager != null
判斷,是因為第一次進來audioManager還沒有建立,會報錯。
下表就是對應的幾種類型
類型 | 方法or屬性 | 最低API要求 | 使用效果 |
---|---|---|---|
int | AUDIOFOCUS_NONE 用于表示音頻焦點增強或音頻焦點請求。 | API 26 | 1.停止其他音頻播放 2.本音頻播放完畢或者暫停,其他音頻也不會恢複播放 |
int | AUDIOFOCUS_GAIN 用于表示持續時間未知的音頻焦點增強或音頻焦點請求。 | 1.停止其他音頻播放 2.本音頻播放完畢或者暫停,其他音頻也不會恢複播放 | |
int | AUDIOFOCUS_GAIN_TRANSIENT 用于表示暫時的增強或音頻聚焦的請求,預期持續很短的時間。臨時更改的示例:播放行駛方向或事件通知 | 1.停止其他音頻播放 2.本音頻播放完畢或者暫停,其他音頻恢複播放 | |
int | AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE 用于表示對音頻焦點的臨時請求,預計會持續很短的時間,在此期間,其他應用程式或系統元件不應播放任何内容。 獨占和瞬态音頻焦點請求的示例:語音備忘錄錄制、語音識别. *在此期間系統不應播放任何通知,媒體播放應暫停。 | API 19 | 1.停止其他音頻播放 2.本音頻播放完畢或者暫停,其他音頻恢複播放 |
int | AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK 用于表示對音頻焦點的臨時請求,預期持續很短的時間,并且其他音頻應用程式可以在降低輸出音量後繼續播(也稱為“降級”) | 其他音頻播放音量降低,本音頻正常音量播放 | |
int | abandonAudioFocus(AudioManager.OnAudioFocusChangeListener l)This method was deprecated in API level 26. use abandonAudioFocusRequest(android.media.AudioFocusRequest) | 放棄音頻焦點。使上一個焦點所有者(如果有)接收焦點。 |