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

Android应用如何通过Bluetooth SCO同时实现耳机麦克风输入与音频输出?

实现蓝牙SCO双向音频(采集+播放)的可行方案

你已经开启了Bluetooth SCO,但要实现同时采集和播放,还需要完善音频模式配置、设备路由以及监听连接状态,以下是具体步骤:

1. 完善AudioManager配置

仅调用audiomanager.setBluetoothScoOn(true)不足以建立稳定的SCO连接,还需要启动SCO并切换到通信音频模式:

AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

// 设置音频模式为通信模式,强制系统使用蓝牙SCO的双向通道
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
// 请求启动SCO连接(系统会异步建立连接)
audioManager.startBluetoothSco();
// 开启SCO音频
audioManager.setBluetoothScoOn(true);

2. 监听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) {
            // SCO连接成功,初始化录音和播放
            initAudioRecordAndTrack();
        }
    }
};

// 在onCreate中注册广播
registerReceiver(scoReceiver, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));

3. 初始化AudioRecord(采集)和AudioTrack(播放)

确保两者都路由到蓝牙SCO通道,参数要匹配:

private AudioRecord audioRecord;
private AudioTrack audioTrack;
private boolean isRunning = false;

private void initAudioRecordAndTrack() {
    int sampleRate = 8000; // 多数蓝牙SCO设备支持的采样率
    int channelConfig = AudioFormat.CHANNEL_IN_MONO;
    int audioFormat = AudioFormat.ENCODING_PCM_16BIT;

    // 计算录音最小缓冲区
    int recordBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
    // 使用VOICE_COMMUNICATION音频源,强制调用SCO麦克风
    audioRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION,
            sampleRate, channelConfig, audioFormat, recordBufferSize);

    // 初始化播放组件,使用VOICE_CALL流(对应SCO输出)
    int playBufferSize = AudioTrack.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_OUT_MONO, audioFormat);
    audioTrack = new AudioTrack.Builder()
            .setAudioAttributes(new AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
                    .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
                    .build())
            .setAudioFormat(new AudioFormat.Builder()
                    .setSampleRate(sampleRate)
                    .setEncoding(audioFormat)
                    .setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
                    .build())
            .setBufferSizeInBytes(playBufferSize)
            .build();

    // 启动录音和播放线程
    startAudioLoop();
}

4. 同时运行录音与播放

如果需要采集环境音的同时播放提示音,可在录音线程中混入预加载的提示音PCM数据,或单独启动提示音播放线程(确保使用相同的音频属性),以下是实时采集+播放的基础示例:

private void startAudioLoop() {
    isRunning = true;
    new Thread(() -> {
        audioRecord.startRecording();
        audioTrack.play();

        byte[] buffer = new byte[1024];
        while (isRunning) {
            int readSize = audioRecord.read(buffer, 0, buffer.length);
            if (readSize > 0) {
                // 此处可混入提示音PCM数据后再写入播放组件
                audioTrack.write(buffer, 0, readSize);
            }
        }

        audioRecord.stop();
        audioTrack.stop();
        audioRecord.release();
        audioTrack.release();
    }).start();
}

5. 权限配置

在AndroidManifest.xml中添加必要权限:

<!-- 录音权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- Android 12+蓝牙连接权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- Android 11及以下蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

注意事项

  • 部分设备的蓝牙SCO仅支持8000Hz采样率,使用更高采样率可能导致功能失效;
  • 当系统来电或其他应用抢占SCO通道时,需监听广播重新建立连接;
  • 应用退出时记得停止SCO连接:audioManager.stopBluetoothSco(); audioManager.setBluetoothScoOn(false);,并注销广播。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 13:15:54