7

如何在 Android 中从配对的蓝牙音频设备(即Moster Clarity 蓝牙扬声器)录制语音。

我已在 Android 中与设备配对,我想从设备上的麦克风录制声音(而不是使用手机的内置麦克风)。

这是我用于录制的代码:

try {
    isRecording = true;

    recorder = new MediaRecorder();
    recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

    if (file == null) {
        File rootDir = Environment.getExternalStorageDirectory();
        file = File.createTempFile(PREFIX, EXTENSION, rootDir);
    }

    recorder.setOutputFile(file.getAbsolutePath());
    recorder.prepare();
    recorder.start();

    timDown = new RecordCountDown(10000, 1000);
    timDown.start();

} catch (Exception e) {
    Log.i("Error Message", "Error Message :" + e.getMessage());
}

我怎样才能做到这一点?

4

3 回答 3

9

试试这个代码可能对你有帮助..

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

registerReceiver(new BroadcastReceiver() {

@Override
public void onReceive(Context context, Intent intent) {
    int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
    Log.d(TAG, "Audio SCO state: " + state);

    if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) { 
        /* 
         * Now the connection has been established to the bluetooth device. 
         * Record audio or whatever (on another thread).With AudioRecord you can          record   with an object created like this:
         * new AudioRecord(MediaRecorder.AudioSource.MIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO,
         * AudioFormat.ENCODING_PCM_16BIT, audioBufferSize);
         *
         * After finishing, don't forget to unregister this receiver and
         * to stop the bluetooth connection with am.stopBluetoothSco();
         */
        unregisterReceiver(this);
    }

    }
}, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));

Log.d(TAG, "starting bluetooth");
am.startBluetoothSco();
于 2013-06-07T12:26:58.747 回答
4

从蓝牙耳机录音的代码

public class Recording {

static int count = 0;
static String Shared;
static String bFlag;
public static int TIMEOUT = 5000;
public static int COUNTDOWN_INTERVAL = 1000;
static Context context;

public static void checkAndRecord(Context context,
        OnBluetoothRecording BluetoothRecording, boolean resume) {

    // Check bluetooth flag And Bluetooth is ON or OFF
    if (getBluetoothFlag(context) && isBluetoothON()) {

        // Check for bluetooth and Record
        startBluetoothRecording(BluetoothRecording, resume, context);

    } else {

        // If Bluetooth is OFF Show Toast else Dont Show
        if (getBluetoothFlag(context) && !isBluetoothON()) {
            // false because recording not started
            Toast.makeText(context,
                    "Bluetooth is OFF. Recording from Phone MIC.",
                    Toast.LENGTH_SHORT).show();
            BluetoothRecording.onStartRecording(resume, false);
        } else {
            // false because recording not started
            BluetoothRecording.onStartRecording(resume, false);
        }
    }

}

private static void startBluetoothRecording(
        final OnBluetoothRecording BluetoothRecording,
        final boolean resume, Context context) {
    // TODO Auto-generated method stub

    final int MAX_ATTEPTS_TO_CONNECT = 3;
    final AudioManager audioManager = (AudioManager) context
            .getSystemService(Context.AUDIO_SERVICE);

    final CountDownTimer timer = getTimer(BluetoothRecording, audioManager,
            resume);

    context.registerReceiver(new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {

            int state = intent.getIntExtra(
                    AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
            if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) {
                // cancel Timer
                timer.cancel();
                context.unregisterReceiver(this);

                // pass through and true because
                // recording from bluetooth so set 8000kHz

                BluetoothRecording.onStartRecording(resume, true);

            } else if (AudioManager.SCO_AUDIO_STATE_DISCONNECTED == state) {
                if (count > MAX_ATTEPTS_TO_CONNECT) {
                    context.unregisterReceiver(this);
                    // Stop BluetoothSCO
                    audioManager.stopBluetoothSco();
                    // reset Counter
                    count = 0;
                    // stop timer
                    timer.cancel();
                    // false because still recording not started
                    BluetoothRecording.onStartRecording(resume, false);
                } else {
                    // Increment Disconnect state Count
                    count++;

                }
            }

        }
    }, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED));

    // Start the timer
    timer.start();
    audioManager.startBluetoothSco();

}

// set the Timeout
private static CountDownTimer getTimer(
        final OnBluetoothRecording BluetoothRecording,
        final AudioManager audioManager, final boolean resume) {
    // TODO Auto-generated method stub
    return new CountDownTimer(TIMEOUT, COUNTDOWN_INTERVAL) {

        @Override
        public void onTick(long millisUntilFinished) {
            // Do Nothing

        }

        @Override
        public void onFinish() {

            // stopBluetoothSCO() and start Normal Recording
            audioManager.stopBluetoothSco();

            // false because recording button is already clicked but still
            // not recording.
            BluetoothRecording.onStartRecording(resume, false);
        }
    };
}

// Return's the bluetooth state
private static boolean isBluetoothON() {

    BluetoothAdapter bluetoothAdapter = BluetoothAdapter
            .getDefaultAdapter();
    return bluetoothAdapter.isEnabled();
}

// Return's the bluetoothFlag state
private static boolean getBluetoothFlag(Context context) {

    // shared pref
    SharedPreferences sp = context.getSharedPreferences(Shared,
            Context.MODE_PRIVATE);
    return sp.getBoolean(bFlag, false);

}

}

接口 OnBluetoothRecording.java

public interface OnBluetoothRecording {

void onStartRecording(boolean state,boolean bluetoothFlag);
void onCancelRecording();
}
于 2014-08-28T06:28:14.997 回答
2

关键是调用audioManager.startBluetoothSco()

此方法可用于希望在电话未通话时向/从蓝牙 SCO 耳机发送和接收音频的应用程序。

这是一个异步操作,因此,您可以注册一个BroadcastReceiver以在开始通过蓝牙耳机录制音频时收到通知,就像这样

private BroadcastReceiver mBluetoothScoReceiver = 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) {
            // Start recording audio
        }
    }
};


@Override
protected void onResume() {
    super.onResume();

    IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
    registerReceiver(mBluetoothScoReceiver, intentFilter);

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

文档还提到了一些非常重要的事情

应用程序可以在调用 startBluetoothSco() 之前通过读取接收器注册返回的意图来检查 SCO 音频状态。如果状态已经 CONNECTED,则在调用 startBluetoothSco() 后不会通过意图接收到状态更改。

和...

然而,调用 startBluetoothSco() 很有用,以便在当前启动器停止连接的情况下连接保持活动状态。

这意味着如果 SCO 连接已经处于活动状态,您不必等待接收方被调用。这是更新的代码片段。

@Override
protected void onResume() {
    super.onResume();

    IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
    Intent intent = registerReceiver(mBluetoothScoReceiver, intentFilter);
    if (intent == null) {
        Log.e(TAG, "Failed to register bluetooth sco receiver...");
        return;
    }

    int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
    if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
        // Start recording
    }

    // Ensure the SCO audio connection stays active in case the
    // current initiator stops it.
    AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    audioManager.startBluetoothSco();
}

如果您不使用它,您应该停止 SCO 连接。

private void onPause() {
    super.onPause();

    unregisterReceiver(mBluetoothScoReceiver);

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

您的AndroidManifest.xml文件中还需要以下权限

<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
于 2016-03-17T22:42:15.497 回答