Android 11及以下版本AudioManager切换音频输入失效问题咨询
解决Android 11及以下版本音频输入切换失效问题
你的问题核心在于Android 11及以下版本的音频路由管理逻辑和高版本存在差异,原代码缺少关键的模式配置与设备路由指定步骤,以下是针对性修复方案:
1. 补充音频模式基础配置
在操作音频路由前,必须设置合适的音频模式,这是旧版本设备正确切换输入源的前提:
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
该模式专为语音通话/录音场景设计,系统会优先为其匹配对应的音频输入设备。
2. 修复蓝牙音频输入切换逻辑
原代码仅调用startBluetoothSco但未等待连接建立,且缺少模式支撑,修改后逻辑如下:
- 先设置通信模式,再启动SCO连接
- 新增广播监听SCO连接状态,确保连接成功后再生效
修改后的蓝牙分支代码
if (route.contains("Bluetooth")) { audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); audioManager.startBluetoothSco(); audioManager.setBluetoothScoOn(true); Log.d("setAudioRoute", "请求蓝牙SCO连接"); }
新增SCO连接状态监听(模块内实现)
private BroadcastReceiver scoReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1); if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) { Log.d("setAudioRoute", "蓝牙SCO连接成功,已切换到蓝牙麦克风"); } else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) { Log.d("setAudioRoute", "蓝牙SCO连接断开"); } } }; // 模块初始化时注册广播 context.registerReceiver(scoReceiver, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)); // 模块销毁时注销广播 // context.unregisterReceiver(scoReceiver);
3. 修复有线耳机输入切换逻辑
原代码仅遍历设备但未主动指定路由,Android 11及以下需调用setPreferredDevice明确切换输入设备:
else if (route.contains("Wired")) { audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); // 先关闭蓝牙SCO audioManager.setBluetoothScoOn(false); audioManager.stopBluetoothSco(); boolean foundWiredDevice = false; for (AudioDeviceInfo device : devices) { // 同时兼容带麦和不带麦的有线设备类型 if (device.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET || device.getType() == AudioDeviceInfo.TYPE_WIRED_HEADPHONE) { audioManager.setPreferredDevice(device); foundWiredDevice = true; Log.d("setAudioRoute", "已切换到有线耳机麦克风"); break; } } if (!foundWiredDevice) { Log.d("setAudioRoute", "未检测到有线耳机,切换回内置麦克风"); switchToBuiltInMic(); } }
4. 优化内置麦克风切换逻辑
需要明确清除自定义路由配置,让系统自动恢复默认内置麦克风:
private void switchToBuiltInMic() { audioManager.setMode(AudioManager.MODE_NORMAL); audioManager.setBluetoothScoOn(false); audioManager.stopBluetoothSco(); // 清除首选设备,触发系统默认路由 audioManager.setPreferredDevice(null); audioManager.setMicrophoneMute(false); Log.d("setAudioRoute", "已切换到内置麦克风"); } // 原else分支替换为调用该方法 else { switchToBuiltInMic(); }
5. 补充必要权限配置
确保AndroidManifest.xml中已添加对应权限:
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <!-- Android 11及以下蓝牙权限 --> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> <!-- Android 12+蓝牙连接权限 --> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" android:minSdkVersion="31" />
关键说明
MODE_IN_COMMUNICATION是旧版本设备切换语音输入的核心,系统会优先为该模式分配音频设备setPreferredDevice(API 23+)是Android 6.0及以上指定音频输入设备的标准接口,原代码未调用导致有线耳机切换失效- 蓝牙SCO连接是异步操作,必须等待连接成功后才能生效,否则会继续使用内置麦克风
内容的提问来源于stack exchange,提问作者vuminh
相关产品推荐
相关产品推荐

