I faced problem with bluetooth SCO audio in my android app.
I registered a receiver for actions ACL_CONNECTED and ACL_DISCONNECTED to capture the bluetooth SCO device connection and disconnection. On receive of ACL_CONNECTED I am checking whether bluetooth device has Audio service (headset) or not, if has AUDIO service, I am instantiating AudioTrack (new AudioTrack(....)) and starting bluetooth SCO (startBluetoothSco(); setBluetoothScoOn(true);).
I have a button in my app to write pcm data to AudioTrack. In this app I am not able to hear sound of PCM data i written.
I tried without any receiver and in onCreate() only I instantiated AudioTrack and started bluetooth SCO. Before launching app, I connected headset to my device and tested, it is working fine.
But, why my app is not working when established bluetooth SCO connection at run-time depending on ACL_CONNECTED intent.
If anybody know the solution please reply me. I added all required permissions BLUETOOTH, BLUETOOTH_ADMIN, MODIFY_AUDIO_SETTINGS (don't report about spelling mistakes in these permissions).
Using what version API?
When creating your receiver use BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED instead of ACL_CONNECTED.
intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); // API 11
intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); // API 8
intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); // API 14
Related
Overview
I'm currently working on an android app that supports VoIP calls (using webrtc). Everything's working perfectly, but now I'm trying to add support for bluetooth headsets. I want the calls to be answered/hangup automatically (without the user touching the device's screen) if:
The user has a bluetooth headset connected to his device
The Answer/Hangup button was pressed
Problem
I'm still struggling to make this work. I've read all related stack overflow questions (like this and this), but still no luck.
What I've tried:
Obtain the bluetooth profile proxy using bluetoothAdapter.getProfileProxy(context, serviceListener, BluetoothProfile.HEADSET).
On the service listener (a BluetoothProfile.ServiceListener) check if the obtained BluetoothHeadset has a connected bluetooth device. If true, register a BroadcastReceiver with an IntentFilter that has the actions android.intent.action.MEDIA_BUTTON, android.media.ACTION_SCO_AUDIO_STATE_UPDATED and android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED and call audioManager.startBluetoothSco().
I'm only receiving broadcasts for the android.media.ACTION_SCO_AUDIO_STATE_UPDATED action. What's wrong with my approach?
Any help would be appreciated.
I have not developed VoIP apps, so I am not sure about correct sequence of events and control calls in this case. Not sure that this can help, just some notes from Bluetooth point of view. Intents BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED (android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED) are about BluetoothHeadset's RFCOMM connection, it is kept alive if Handsfree/Headset profile is enabled for specific Handsfree unit and Handsfree unit is in use. You need these intents to detect if you need to look after BluetoothHeadset state or not, so you will not receive them during calls.
You can also register a receiver for BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED intents (android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED). In BluetoothHeadset source and accordingly in Android documentation it described as "Audio Connection state of the A2DP profile", but this is wrong. This is state of Handsfree/Headset physical audio SCO connection. This connection is active during voice calls, Bluetooth voice recognition and ringing (if In Band Ringing feature is supported and enabled). I do not remember how BluetoothHeadset audio state concerns AudioManager's SCO state.
I tested few things on Android mobiles with bluetooth headset.I have few questions regarding the same.
Device Specifications :
Android 2.3 above
Headset Blue tooth profiles : HFP,A2DP
I accepted a call from accept button from the android mobile and I was able to hear the call from the bluetooth headset.After that I moved android device out of range and accepted the call from android and when the android mobile entered bluetooth range bluetooth headset connected automatically.Is it universal, I mean all the bluetooth headsets support the same or are there any deviations?
I would like to know what will happen when we accept the call from headset or Android mobile.Is it something like Android OS is going to create a call session/audio session and transfer this to headset when accept button is pressed from the headset.If a call is already received and when the headset is in bluetooth range,Android mobile is going to route the volume to headset. In both the cases the same thing happens(just routing the audio).I would like to know the call handling in detail both the cases.Could some one help me on this.
How the call process is different in iOS?
Edit
Is any call session like AVAudoioSession is getting created when we accept a call ?
#jjv360:
"An app can manually assign a route even though a bluetooth headset is connected, in which case it's up to the app to handle what happens when a new route is detected..."
Is it possible to route the call session to headset(from microphone to headset sco) in an iOS app?Could you please give some pointers on this.
On iOS if you connect a bluetooth headset while an audio session is active the current audio app(s) get notified and by default will transfer the session's route to the headset. An app can manually assign a route even though a bluetooth headset is connected, in which case it's up to the app to handle what happens when a new route is detected...
Also, AFAIK the reconnect is attempted by both the device (for a very short time) and the headsets, so it's mainly up to the headset to attempt reconnecting when it goes out of range. Almost all headsets should do this though.
It doesn't matter which button was used to accept the call (on device or on headset), if the bluetooth headset is connected it will be used, unless an app has specified that it doesn't want to use that route.
The call process AFAIK is the same for Android and iOS.
With the protocol used, A2DP is the high-quality protocol used when listening to music. It supports high-quality audio, but is one-way, so only works if the bluetooth headset is not recording from the mic. HFP is used when recording is also needed, but the quality is less. That is why you will notice on iOS if you're listening to music on bluetooth headset and then start a recording app, the sound quality will become worse until you stop the recording...
I am using following code in my application to use bluetooth headset for audio IN and OUT. It is working fine.
AudioManager am = (AudioManager)getSystemService(AUDIO_SERVICE);
am.startBluetoothSco();
am.setBluetoothScoOn(true);
But, When I played song using Music Player app, along with my application also running, the song is coming in bluetooth headset. This is because I changed the Audio Manager of android system to Bluetooth SCO.
But my requirement is the audio IN and OUT must work with bluetooth headset to my application only and it should not disturb other apps, Is it possible ?? or not ??
Please provide your valuable suggestions. Any help will be appreciated. Thanks.
When you add a SCO channel you are essentially adding an audio channel. Think of it like a wired handsfree. When you connect the handsfree all audio is routed to it and not just one specific applications's audio. To use the BT headset only for your app, connect the SCO channel when the app starts and disconnect when the app is exited or goes into background.
I've managed to get text-to-speech audio streaming through my SCO headset using startBluetoothSco(), but it's not interrupted by incoming phone calls, as documented at http://developer.android.com/reference/android/media/AudioManager.html:
Note that the phone application always has the priority on the usage of the SCO connection for telephony. If this method is called while the phone is in call it will be ignored. Similarly, if a call is received or sent while an application is using the SCO connection, the connection will be lost for the application and NOT returned automatically when the call ends.
When a call comes in, I can hear both the phone call audio and my text-to-speech audio at the same time. Has anyone successfully gotten the correct behavior with incoming phone calls? I'm testing on a Samsung Captivate running Android 2.2. Thanks!
What stream are you using? Make sure you are not using VOICE_CALL stream.
I have a broadcast receiver in my app that logs every connection of a BT device by tracking the android.bluetooth.device.action.ACL_CONNECTED broadcast. But I need to know if the BT device isa headset, and more importantly, if it's an SCO or an A2DP headset. I can find out what services the connected device supports using BluetoothClass.Service, but I don't know which services are supposed to correspong to each type of headset. Here are the ones listed:
AUDIO
CAPTURE
INFORMATION
LIMITED_DISCOVERABILITY
NETWORKING
OBJECT_TRANSFER
POSITIONING
RENDER
TELEPHONY
Can anyone tell me which of these determiny the headset profile type (headset, hands-free, or A2DP?
You can use BluetoothProfile.ServiceListener and listen for onServiceConnetced and you will get notifications for A2DP or SCO connected.
See here