7

How can I record the voice from a paired Bluetooth audio device (i.e. Moster Clarity Bluetooth Speaker) in Android.

I've paired with the device from within Android, and I'd like to record the voice from the microphone on the device (as opposed to using the phone's built-in microphone).

Here's the code I'm using for recording:

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());
}

How can I do this?

ampledata
  • 135
  • 1
  • 7
Prashant
  • 1,351
  • 3
  • 20
  • 32
  • possible duplicate of [How to record sound using bluetooth headset](http://stackoverflow.com/questions/4026002/how-to-record-sound-using-bluetooth-headset) – mad Mar 22 '14 at 13:11

3 Answers3

9

Try this code maybe helpful for you..

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();
RaviPatidar
  • 1,438
  • 1
  • 18
  • 29
  • 5
    Would you consider adding some narrative to explain why this code works, and what makes it an answer to the question? This would be very helpful to the person asking the question, and anyone else who comes along. – Andrew Barber Jun 11 '13 at 05:48
  • 1
    This works, but it's worth mentioning that it requires the following permissions: BLUETOOTH, MODIFY_AUDIO_SETTINGS, and BROADCAST_STICKY. – Dmitry Brant Sep 05 '13 at 19:51
4

code to voice recording from bluetooth headset

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);

}

}

Interface OnBluetoothRecording.java

public interface OnBluetoothRecording {

void onStartRecording(boolean state,boolean bluetoothFlag);
void onCancelRecording();
}
Shivaraj Patil
  • 8,186
  • 4
  • 29
  • 56
2

The key thing is to call audioManager.startBluetoothSco().

This method can be used by applications wanting to send and received audio to/from a bluetooth SCO headset while the phone is not in call.

This is an asynchronous operation, as such, you can register a BroadcastReceiver to be notified once audio will start being recorded through the bluetooth headset like so

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();
}

The docs also mention something very important

the application can check the SCO audio state before calling startBluetoothSco() by reading the intent returned by the receiver registration. If the state is already CONNECTED, no state change will be received via the intent after calling startBluetoothSco().

And...

It is however useful to call startBluetoothSco() so that the connection stays active in case the current initiator stops the connection.

This means you do not have to wait for the receiver to be called if the SCO connection is already active. Here is the updated code snippet.

@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();
}

You should stop the SCO connection if you are not using it.

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

    unregisterReceiver(mBluetoothScoReceiver);

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

You will also need the following permissions in your AndroidManifest.xml file

<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"/>
rperryng
  • 3,233
  • 3
  • 22
  • 35