天天看点

Anddroid IM来电铃声通过耳机播放

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