针对问题:使用云信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) | 放弃音频焦点。使上一个焦点所有者(如果有)接收焦点。 |