贝利信息

如何在 Android 中正确启用蓝牙 SCO 音频通道进行录音

日期:2025-12-29 00:00 / 作者:花韻仙語

本文详解 `audiomanager.startbluetoothsco()` 失效的常见原因及完整解决方案,重点说明必须通过 `action_sco_audio_state_updated` 广播监听状态变更,而非直接读取 `extra_sco_audio_state`,并提供可运行的 broadcastreceiver 实现与关键注意事项。

在 Android 中通过蓝牙耳机(如蓝牙耳麦)进行高质量音频录制时,AudioManager.startBluetoothSco() 是启用单声道语音通信通道(SCO)的核心方法。但许多开发者发现该方法“不生效”——调用后 AudioManager.EXTRA_SCO_AUDIO_STATE 始终返回 -1,SCO_AUDIO_STATE_CONNECTED 从未触发。根本原因在于:SCO 状态并非主动可查,而是必须通过系统广播异步通知;且必须先注册监听 AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED,再在接收到该广播时解析状态值。

✅ 正确实现步骤

  1. 注册正确的广播动作
    AndroidManifest.xml 中仅声明 ACTION_SCO_AUDIO_STATE_UPDATED(注意不是 android.media.extra.SCO_AUDIO_STATE —— 后者是额外字段名,非广播 Action):

    
        
    

⚠️ 注意:android:exported="true" 在 Android 12+ 要求显式声明,且该广播为系统内部广播,无需动态注册(但需确保应用有 BLUETOOTH 权限)。

  1. 在 BroadcastReceiver 中精准响应广播
    必须首先校验 intent.getAction() 是否为 AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED,再提取状态值。切勿在任意广播中直接读取 EXTRA_SCO_AUDIO_STATE(如来电或媒体按键广播中读取将始终返回 -1):
public class CallReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (!AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED.equals(intent.getAction())) {
            Log.w("CallReceiver", "Ignored non-SCO action: " + intent.getAction());
            return;
        }

        int scoState = intent

.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1); Log.d("CallReceiver", "SCO state received: " + scoState); switch (scoState) { case AudioManager.SCO_AUDIO_STATE_CONNECTED: enableBluetoothSco(context); break; case AudioManager.SCO_AUDIO_STATE_DISCONNECTED: Log.i("CallReceiver", "Bluetooth SCO disconnected"); // 可选:恢复默认音频模式 restoreAudioMode(context); break; default: Log.w("CallReceiver", "Unknown SCO state: " + scoState); } } private void enableBluetoothSco(Context context) { AudioManager audioManager = context.getSystemService(AudioManager.class); // 关键:必须设置为 MODE_IN_CALL(或 MODE_IN_COMMUNICATION)才能启用 SCO audioManager.setMode(AudioManager.MODE_IN_CALL); audioManager.setBluetoothScoOn(true); // 启用蓝牙 SCO 支持 audioManager.startBluetoothSco(); // 触发连接流程(异步) Log.i("CallReceiver", "Bluetooth SCO enabled successfully"); } private void restoreAudioMode(Context context) { AudioManager audioManager = context.getSystemService(AudioManager.class); audioManager.setBluetoothScoOn(false); audioManager.stopBluetoothSco(); audioManager.setMode(AudioManager.MODE_NORMAL); } }

⚠️ 关键注意事项

✅ 验证是否生效

遵循以上规范,startBluetoothSco() 将稳定触发蓝牙音频通道,为高质量语音采集奠定基础。