Android: Playing sound over Sco Bluetooth headset
For the past few days I have been trying to play any sound over my sco bluetooth headset from my android phone. My final goal with this project is to eventually make a garage door opener, but first I need to be able to play sound over the headset. Here is the basis of the current code I’m using:
==Manifest== ==Code== audioManager = (AudioManager) getSystemService(AUDIO_SERVICE); audioManager.setMode(AudioManager.MODE_IN_CALL); audioManager.startBluetoothSco(); audioManager.setBluetoothScoOn(true); short[] soundData = new short [8000*20]; for (int iii = 0; iii < 20*8000; iii++) < soundData[iii] = 32767; iii++; soundData[iii] = -32768; >audioTrack = new AudioTrack(AudioManager.STREAM_VOICE_CALL, 8000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, soundData.length * Short.SIZE, AudioTrack.MODE_STATIC); audioTrack.write(soundData, 0, soundData.length); audioTrack.play();
Before I run this, I pair my bluetooth headset to my phone and have it connected. I have verified it works by calling my voicemail. When I run my code however, no sound comes from anywhere. Here are the effects of the different lines of code: When I’m just running my app:
audioManager.setMode(AudioManager.MODE_IN_CALL);
audioManager.startBluetoothSco(); audioManager.setBluetoothScoOn(true);
These two lines make the sound stop coming out of the front speaker and make my headset click and hiss like it’s turned on but there’s no output.
AudioManager.STREAM_VOICE_CALL
This is part of my call to the AudioTrack constructor, but it makes quite a difference. Since this is set to STREAM_VOICE_CALL the sound comes out of the front speaker, if I set this to STREAM_MUSIC, the sound comes out the back speaker instead. When I open my app during a call:
audioManager.setMode(AudioManager.MODE_IN_CALL);
During a call, this line has no effect because MODE_IN_CALL was already set. But what’s different however is that my sound is mixed with the phone call, whereas normally it doesn’t play at all.
audioManager.startBluetoothSco(); audioManager.setBluetoothScoOn(true);
These, with their counterpart off halves, control where the audio is coming from. If I turn these off, my sound and the telephone call come from the front speaker, with these on, the telephone call comes from my headset and my sound is lost. As to why my code is not working, I honestly have no idea. I believe I have fulfilled the checklist for using startBluetoothSco().
Even if a SCO connection is established, the following restrictions apply on audio output streams so that they can be routed to SCO headset: - the stream type must be STREAM_VOICE_CALL - the format must be mono - the sampling must be 16kHz or 8kHz
So, does anyone have an idea of what I am doing wrong? There was one time that I managed to get my sound to play through the headset, but it was only a short tone when I forgot to stop() my AudioTrack so I have to assume it was a glitch.
4 Answers 4
I found the solution on this page. You have to call audioManager.setMode(AudioManager.MODE_IN_CALL); only after the socket is connected, i.e., you received AudioManager.SCO_AUDIO_STATE_CONNECTED . I could hear the TTS on my Spica running android 2.2.2.
Edit: Here is my (old) implementation:
public class BluetoothNotificationReceiver extends BroadcastReceiver < /** * */ public BluetoothNotificationReceiver(Handler h) < super(); bnrHandler = h; >/* (non-Javadoc) * @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent) */ @Override public void onReceive(Context arg0, Intent arg1) < String action = arg1.getAction(); if (action.equalsIgnoreCase(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED)) < int l_state = arg1.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1); Log.d("bnr", "Audio SCO: " + AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); switch(l_state) < case AudioManager.SCO_AUDIO_STATE_CONNECTED: < Log.i("bnr", "SCO_AUDIO_STATE_CONNECTED"); >break; case AudioManager.SCO_AUDIO_STATE_DISCONNECTED: < Log.e("bnr", "SCO_AUDIO_STATE_DISCONNECTED"); >break; default: Log.e("bnr", "unknown state received:"+l_state); > > else Log.e("bnr", "onReceive:action mt24">)" data-controller="se-share-sheet" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f3.0%2f" data-se-share-sheet-license-name="CC BY-SA 3.0" data-s-popover-placement="bottom-start">Share)" title="">Improve this answer)">edited Nov 1, 2014 at 14:14answered Jul 5, 2012 at 16:50 Fabien RFabien R6851 gold badge8 silver badges24 bronze badges