在做voip通话的过程中,会频繁使用到免提播放和听筒接听的功能,而如何正确的切换,和AudioManager的调度是分不开的,直接上代码:
//获取AudioManager服务
private val audioManager =
AppUtils.getApplication().getSystemService(Context.AUDIO_SERVICE) as AudioManager
/**
* 扬声器切换
* true: 打开
*/
fun setSpeakerPhoneOn(on: Boolean) {
if (on) {
//设置mode
audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
//设置音量,解决有些机型切换后没声音或者声音突然变大的问题
audioManager.setStreamVolume(
AudioManager.STREAM_VOICE_CALL,
audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL),
AudioManager.FX_KEY_CLICK
)
//扬声器开启,此方法调用之前需要先设置好mode
audioManager.isSpeakerphoneOn = true
} else {
//5.0以上
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//设置mode
audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
//设置音量,解决有些机型切换后没声音或者声音突然变大的问题
audioManager.setStreamVolume(
AudioManager.STREAM_VOICE_CALL,
audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL),
AudioManager.FX_KEY_CLICK
)
} else {
//设置mode
audioManager.mode = AudioManager.MODE_IN_CALL
audioManager.setStreamVolume(
AudioManager.STREAM_VOICE_CALL,
audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL),
AudioManager.FX_KEY_CLICK
)
}
//扬声器关闭,此方法调用之前需要先设置好mode
audioManager.isSpeakerphoneOn = false
}
}
/**
* 麦克风开关
* RINGER_MODE_SILENT 静音,且无振动
* RINGER_MODE_VIBRATE 静音,但有振动
* RINGER_MODE_NORMAL 正常声音,振动开关由setVibrateSetting决定.
* true:静音
*/
fun setVoiceOn(on: Boolean) {
audioManager.isMicrophoneMute = on
// ToastUtils.shortBottom(if (on) "麦克风已关闭" else "麦克风已启用")
}
/**
* 重设audioManager状态
* 扬声器切换为NORMAL && 打开麦克风
*/
fun resetAudioState() {
//设置mode 为喇叭播放
audioManager.mode = AudioManager.MODE_NORMAL
//设置音量,解决有些机型切换后没声音或者声音突然变大的问题
audioManager.setStreamVolume(
AudioManager.STREAM_MUSIC,
audioManager.getStreamVolume(AudioManager.STREAM_MUSIC),
AudioManager.FX_KEY_CLICK
)
audioManager.isSpeakerphoneOn = true
setVoiceOn(false)
}
方法调用代码如上,下面来分析一下使用中要重点注意的元素:
1.audioManager.mode
AudioManager中给出了如下mode种类,正确的选择mode进行配置,才能提升用户体验;
/**
* Invalid audio mode.
*/
public static final int MODE_INVALID = AudioSystem.MODE_INVALID;
/**
* Current audio mode. Used to apply audio routing to current mode.
*/
public static final int MODE_CURRENT = AudioSystem.MODE_CURRENT;
/**
* Normal audio mode: not ringing and no call established.
*/
public static final int MODE_NORMAL = AudioSystem.MODE_NORMAL;
/**
* Ringing audio mode. An incoming is being signaled.
*/
public static final int MODE_RINGTONE = AudioSystem.MODE_RINGTONE;
/**
* In call audio mode. A telephony call is established.
*/
public static final int MODE_IN_CALL = AudioSystem.MODE_IN_CALL;
/**
* In communication audio mode. An audio/video chat or VoIP call is established.
*/
public static final int MODE_IN_COMMUNICATION = AudioSystem.MODE_IN_COMMUNICATION;
在VOIP场景中,主要就是为了通话服务,所以选择mode的时候,设置为MODE_IN_COMMUNICATION 就比较合适,如果设置为MODE_NORMAL 去开启扬声器,就可能会出现和其他音频播放声音混杂,甚至互相干扰啸叫严重的问题。