I'm trying to correctly setup bluetooth SCO in my app. After many attempts it seems that I've found a way to enable it "almost" reliably, in the sense that it works almost always, but in one case: if I launch my app and AFTER this I pair the headset, the headset mic is not picked (the phone mic is picked instead), while the headset earphones are correctly picked.
If instead I pair the headset BEFORE launching the app, everything seems to work fine.
The strange thing is that, even when the phone mic is picked, calling getRoutedDevice() on my AudioRecord object returns the bluetooth headset.
I tried to use SetPreferredDevice on the AudioRecord object, but apparently it has no effect.
The only way I found to ALWAYS pick the headset microphone is to call
audioManager.setMode(AudioManager.MODE_NORMAL);
However in this case, the output comes from the phone speaker and not from the BT headset earphones!
If instead i call:
audioManager.setMode(AudioManager.MODE_IN_CALL);
the output comes consistently (and correctly) from the BT headset earphones, but I have the above mentioned mic issue (pairing the headset after launching the app, the phone mic is picked instead of the BT headset one).
The sequence I am using is:
I have a thread that checks if a bluetooth headset is connected and works pretty much reliably.
When isHeadsetConnected is true I do:
arec.stop(); // my AudioRecord object
atrack.stop(); // my AudioTrack object
audioManager.setMode(AudioManager.MODE_IN_CALL);
audioManager.startBluetoothSco();
In the listener of AudioManager.EXTRA_SCO_AUDIO_STATE, when I receive SCO_AUDIO_STATE_CONNECTED) I do:
audioManager.setBluetoothScoOn(true);
atrack.play();
arec.startRecording();
After struggling a lot, this seems to be the "almost" perfect sequence, with the caveat that it does not work fully if the first pairing is made with the application running.
I've made an attempt to pair the same headset during a Whatsapp call, and the bluetooth headset starts without any problem both input and output, so THERE MUST be a way to accomplish this!
I have read tons of questions/answers but none of these seems to consistently solve my problem.
I am using Android 11 on a CAT S62 Pro.
Related
I've implemented this solution to get AudioRecord working with bluetooth earpieces.
This works well until no sound is transferred to and from the bluetooth device, however if there is no sound output, and no microphone output for a few seconds, the micro
phone stops listening.
I tried to listen almost all intent actions, but I have nothing when the microphone stops.
How could I get a message on this kind of timeout, or how could I keep this connection on ?
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 have an AudioTrack streaming via headphones. I have to send a SoundPool to built-in speakers only, without interrupting the AudioTrack playing over the headphones. Any hacks gangsters?
Many Android devices use a single output thread in the AudioFlinger / audio HAL for all local playback (earpiece, speaker, wired headset/headphones), making different routing of two tracks simultaneously impossible (which is why on many devices the media streams are forcibly muted if a notification is played and you've got a wired headset attached; because otherwise you'd hear the music in the loudspeaker while the notification is played).
On some devices it might be possible to do what you're looking for if you manage to do a setForceUse(FOR_MEDIA, FORCE_SPEAKER) and use the MUSIC stream type for the stuff you want to play in the loudspeaker, and the VOICE_CALL stream type for the stuff that you want to play in the wired headset.
I'm not sure if there's any way for an application to perform that setForceUse call though. Perhaps you can get at the handleMessage method of the AudioService class through reflection and send it an MSG_SET_FORCE_USE message.. I've never tried it myself so it might fail miserably.
EDIT: I've now tested the setForceUse way of forcing MEDIA streams to the loudspeaker while a wired headset is attached on an actual device, and it does work (though I can't guarantee that it will work across all devices). The implementation was slightly different from what I described above. See my answer to how to turn speaker on/off programatically in android 4.0 for the code I used.
My problem is - how to set up bluetooth incall audio volume.
Since there some apps for this, no one of them works.
Anyway - no app - create one for yourself. I'm very begginer in android development, so i've tried use audioManager.setStreamVolume(), but without any luck - only internal audio has changed after this.
Even playing with startBluetoothSCO() wasn't the answer.
After looking in logcat, how os responds to pressing volume keys, i found out, that after startBluetoothSCO() volume keys in my phone sends AT commands instead of mangling streams (AT+VGM=0...15).
So my code should look something like this:
AudioManager audioManager = (AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
audioManager.startBluetoothSco();
// send AT commands
audioManager.stopBluetoothSco();
Crawling thru web provide me answer that there's no way to directly access modem (and propably other comm ports) from Android API.
So, maybe someone has any goddamn idea how to prevent resetting BT volume on each connect/disconnect to headset? Using code that i could use by myself, or using some 3-rd party app that is available somewhere.
OS: GB 2.3.4, SGS
Thanks for any ideas.
You can send AT commands via RFCOMM connection. But you must do this before the Android has created Headset/Handsfree Profile connection (Called Phone audio in bluetooth settings menu), or at least disconnect the HSP/HFP then connect via RFCOMM on either of the two (Both HSP and HFP should work with unsolicited +VGS commands), set the volume, and then reconnect.
Is it possible to record an audio (not a phone call) using the bluetooth input and not the device microphone?
I am able to playback whatever am saying through device's mic but not able to figure out how to use the bluetooth mic instead.
Any assistance would be greatly appreciated.
(Edited)
I got it working by using following two lines of code
startBluetoothSco();
setBluetoothScoOn(true);
Got the bluetooth headset play back whatever am saying by using
STREAM_VOICE_CALL in audioTrack initialization.