Android 10及以上系统非默认通话应用如何编程开启免提
Android 10开始对音频服务的通话相关操作做了权限限制,普通应用未持有通话音频焦点时,原有修改扬声器的逻辑会被系统拦截,无需设置为默认电话应用的可行方案如下:
前置权限配置
在AndroidManifest.xml中添加如下权限,其中危险权限需要在运行时动态申请:
<!-- 修改音频设置基础权限,安装即授予 --> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <!-- 读取通话状态权限,需动态申请 --> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- 若使用ACTION_CALL直接拨号,需添加该权限并动态申请 --> <uses-permission android:name="android.permission.CALL_PHONE" />
动态切换免提实现逻辑
Android 10及以上版本需要先申请通话类型的音频焦点,拿到焦点后再修改扬声器状态,适配代码如下:
/** * 动态切换免提状态 * @param enable true为开启免提,false为关闭 */ private void switchSpeaker(boolean enable) { AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // 构造通话类型的音频属性 AudioAttributes attrs = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) .build(); // 构造音频焦点请求 AudioFocusRequest focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT) .setAudioAttributes(attrs) .setAcceptsDelayedFocusGain(false) .build(); // 申请音频焦点 int focusResult = am.requestAudioFocus(focusRequest); if (focusResult == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { // 获得焦点后修改音频设置 am.setMode(AudioManager.MODE_IN_COMMUNICATION); am.setSpeakerphoneOn(enable); if (enable) { // 开启免提时设置通话音量为最大 am.setStreamVolume(AudioManager.STREAM_VOICE_CALL, am.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL), 0); } } } else { // Android 10以下沿用原有逻辑 am.setMode(AudioManager.MODE_IN_CALL); am.setSpeakerphoneOn(enable); if (enable) { am.setStreamVolume(AudioManager.STREAM_VOICE_CALL, am.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL), 0); } } }
调用时机与后续处理
- 必须在监听到通话已接通(
TelephonyManager.CALL_STATE_OFFHOOK)之后再调用上述方法,拨号刚发起时还未建立通话通道,修改会失效。 - 通话结束后需要重置音频状态、释放音频焦点,避免影响其他应用的音频功能:
private void resetAudioAfterCall() { AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); am.setMode(AudioManager.MODE_NORMAL); am.setSpeakerphoneOn(false); // Android 10及以上释放音频焦点 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { AudioAttributes attrs = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) .build(); AudioFocusRequest focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT) .setAudioAttributes(attrs) .build(); am.abandonAudioFocusRequest(focusRequest); } }
注意:该方案仅在应用主动触发拨号、系统处于通话状态时生效,无需将应用设置为系统默认电话应用。
内容的提问来源于stack exchange,提问作者lormiz
相关产品推荐
相关产品推荐

