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.
Related
I am writing an application implementing the HF side of the Bluetooth Hands-free Protocol, and I need some advice as to how you are supposed to debug the SCO connections.
From my assumption and observation, the AG only establishes an SCO connection once a call has been answered (or when one is incoming due to In-band ringtone). This is hard to debug as I don't have a second mobile phone to call myself.
Is there some way to make the phone establish an SCO link without using some service to call the device, or without calling someone yourself?
I know that the HF can ask the AG to establish an SCO link through AT+BCC, but once the socket is open, the AG closes it fairly quickly, which doesn't happen when the AG opens the link on its own.
My approach thus far was an online service that calls me on my mobile phone, but that service only allows 5 calls a day, which I most of the time easily exceed.
The device is an Android phone.
I'm integration bluetooth support in my Android app for VOIP calling scenarios. Goal: display caller ID on bluetooth device, allow accept/reject of incoming/active calls through the BT peripheral. Without any work, everything works as expected when calling with the native dialer on Android but I can't find the appropriate APIs to implement the same behavior in our app - are these not exposed?
If a VOIP call is initiated through our app, we start the bluetooth SCO connection and listen for any media /state changes. Pressing the 'answer/reject' button results in a DISCONNECTED state change event (could use this to reject the call but that's not reliable as the same event is received if the BT device is disconnected). I haven't found any leads on displaying the appropriate caller ID (a custom string that I want to provide) or answering calls. Anyone been on this path and have some pointers?
Thanks!
I need to know from glass, if there is a phone call in process. I can made it easy on android device ... but I have problems with glass, the same code to telephonymanager and so on ... doesn't works on glass.
Any idea how to catch the broadcasting process or PhoneCallManager to know if the phone has is talking?
thanks for advice.
Glass works as a bluetooth headset when making a phone call (see user guide). It is not making the calls itself.
I think you'll have to use the BluetoothHeadset class which will allow you to interact with the Headset bluetooth profile. You can then retrieve the state of the headset connection.
How can I tell when a Bluetooth device connects to the phone, whether it's A2DP or not?
This tutorial gives a really easy-to-follow guide on listening for Bluetooth connections.
I want to use that to determine if any connected Bluetooth device is an A2DP type.
AudioManager has a method isBluetoothA2dpOn() but I don't think this will return true straight away, (or even for certain at all), since just because an A2DP device is connected, that doesn't mean the audio is being routed through it?
I would have thought the information on the type of device connected would be available in the intent received (see tutorial above) but I can't find any documentation on this?
I can get the BluetoothClass with this code:
BluetoothClass btClass = intent.getParcelableExtra(BluetoothDevice.EXTRA_CLASS);
but that doesn't help me determine if it is an A2DP profile, since the BluetoothClass documentation says:
BluetoothClass is useful as a hint to roughly describe a device (for
example to show an icon in the UI), but does not reliably describe
which Bluetooth profiles or services are actually supported by a
device. Accurate service discovery is done through SDP requests, which
are automatically performed when creating an RFCOMM socket with
createRfcommSocketToServiceRecord(UUID) and
listenUsingRfcommWithServiceRecord(String, UUID)
...which is pretty meaningless to me.
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...