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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 12:40:21