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
相关产品推荐
相关产品推荐

