I am trying to capture audio from a Bluetooth Headset paired with an Android Device.
Following is the relevant code:
Intent in=null;
final int bufferSize=BufferElements2Rec*BytesPerElement;
final BroadcastReceiver brr=new BroadcastReceiver()
{
@Override
public void onReceive(Context context,Intent intent)
{
int state=intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,-1);
Log.d(labelApp,"Audio SCO State = "+state);
if(AudioManager.SCO_AUDIO_STATE_CONNECTED==state)
{
Log.d(labelApp,"Entered and Starting Recording");
//recorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT,
// RECORDER_SAMPLERATE, RECORDER_CHANNELS,
// RECORDER_AUDIO_ENCODING, bufferSize);
recorder = new AudioRecord(android.media.MediaRecorder.AudioSource.MIC,
RECORDER_SAMPLERATE, RECORDER_CHANNELS,
RECORDER_AUDIO_ENCODING, bufferSize);
if(recorder==null)
{
Log.d(labelApp,"null");
}
else
{
Log.d(labelApp,"not null");
}
recorder.startRecording();
recordingThread=new Thread(new Runnable()
{
@Override
public void run() {
// TODO Auto-generated method stub
writeAudioDataToFile();
}
},"AudioRecorder Thread");
recordingThread.start();
Log.d(labelApp,"Launched Recording Thread");
}
}
};
try
{
Log.d(labelApp,"Initializing BT");
am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
//am.setMode(AudioManager.MODE_IN_CALL);
//in=registerReceiver(brr,new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));
//in=registerReceiver(brr,new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));
Log.d(labelApp,"Starting Bluetooth");
am.setStreamSolo(AudioManager.MODE_IN_CALL, true);
am.setBluetoothScoOn(true);
am.setMode(AudioManager.MODE_IN_CALL);
am.startBluetoothSco();
Log.d(labelApp,"Can BT record from mic? "+am.isBluetoothScoAvailableOffCall());
//in=registerReceiver(brr,new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));
in=registerReceiver(brr,new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED));
// The following line makes the audio go to hell
//am.setMode(AudioManager.MODE_IN_CALL);
//am.setStreamSolo(AudioManager.MODE_IN_CALL, true);
Log.d(labelApp,"Everything initializated");
Log.d(labelApp,"Recorder is...");
}
catch(Exception e)
{
Log.e(labelApp,"exception",e);
writeStack(e);
}
try
{
Log.d(labelApp,"Initializing BT");
am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
//am.setMode(AudioManager.MODE_IN_CALL);
//in=registerReceiver(brr,new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));
//in=registerReceiver(brr,new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));
Log.d(labelApp,"Starting Bluetooth");
am.setStreamSolo(AudioManager.MODE_IN_CALL, true);
am.setBluetoothScoOn(true);
am.setMode(AudioManager.MODE_IN_CALL);
am.startBluetoothSco();
Log.d(labelApp,"Can BT record from mic? "+am.isBluetoothScoAvailableOffCall());
//in=registerReceiver(brr,new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));
in=registerReceiver(brr,new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED));
// The following line makes the audio go to hell
//am.setMode(AudioManager.MODE_IN_CALL);
//am.setStreamSolo(AudioManager.MODE_IN_CALL, true);
Log.d(labelApp,"Everything initializated");
Log.d(labelApp,"Recorder is...");
}
catch(Exception e)
{
Log.e(labelApp,"exception",e);
writeStack(e);
}
The Manifest asks permissions for:
The typical Filtered LogCat output per the app is:
When the am.startBluetoothSco(); is invoked, I can hear a brief noise on the BT device, but then the app simply gets the audio from the Android Device's mic in place of the BT's one.
Any hint on what am I missing/doing wrong?
Thanks in advance for the attention
Most importantly, you need to set
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
in the manifest file. Without it, there will be no error message but the B/T state will refuse to change to connected.
Other relevant permissions include:
<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"/>
Edit: In addition to the comments, here is some sample code that I have used before:
am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
brr(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();
Credits for this code go to user Stephan