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

Android 11 通话中调用setSpeakerphoneOn开启扬声器失效求助

Android 11 调用AudioManager.setSpeakerphoneOn不生效解决方案

根因说明

Android 11(API 30)对音频路由策略做了权限和逻辑变更,setSpeakerphoneOn不再对普通应用无条件生效,只有同时满足以下条件才会触发实际的路由切换:

  • 应用已声明MODIFY_AUDIO_SETTINGS权限
  • 应用当前持有音频焦点,且音频流类型为STREAM_VOICE_COMMUNICATION
  • 当前音频模式设置为MODE_IN_COMMUNICATION

修复方案

首先在AndroidManifest.xml中添加必备权限:

<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

修正后的代码逻辑:

AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
// 1. 先申请通话类型音频焦点
AudioAttributes audioAttributes = new AudioAttributes.Builder()
        .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
        .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
        .build();
AudioFocusRequest focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT)
        .setAudioAttributes(audioAttributes)
        .setAcceptsDelayedFocusGain(true)
        .setOnAudioFocusChangeListener(focusChange -> {})
        .build();
int focusRes = audioManager.requestAudioFocus(focusRequest);
if (focusRes != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    // 音频焦点申请失败可自行添加异常处理逻辑
    return;
}
// 2. 先设置音频模式
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
// 3. 再设置扬声器开关
if (!mSpeakerOn) {
    audioManager.setSpeakerphoneOn(true);
} else {
    audioManager.setSpeakerphoneOn(false);
}

// 退出当前音频场景时要恢复状态、释放资源
// audioManager.setMode(AudioManager.MODE_NORMAL);
// audioManager.abandonAudioFocusRequest(focusRequest);

适配注意事项

  • 如果你使用的是第三方实时音视频SDK(如WebRTC、TRTC等),不要直接调用系统AudioManager接口,要使用SDK提供的扬声器切换方法,避免和SDK内部的音频逻辑冲突
  • 三星、LG部分定制系统对音频路由做了额外限制,切换完成后可以调用audioManager.isSpeakerphoneOn()校验是否生效,如果未生效可以延迟200ms重试一次
  • 针对Android 12及以上系统,推荐使用AudioManager.setPreferredDevice()方法直接指定音频输出设备,兼容性更好

内容的提问来源于stack exchange,提问作者xiaolin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 09:24:03