You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 07:36:03