Due to some deprecated API, I'm looking for code to know which device is routing current audio Stream. I can list all devices, know if the headset is connected but the API says connected but not routing. Now, I want to check, how to check which one is routing audio at this time.
I found in documentation but don't know how to use: https://developer.android.com/reference/android/media/AudioRouting.html
Any ideas?
Related
I have a feature where I need to fetch current AND detect switch of the active audio output device of the system. Something like:
run app -> fetch current device (which might be embedded speakers)
connect bluetooth speaker -> detect switch to bluetooth speaker
connect audio jack -> detect switch from bluetooth speaker to audio jack
It seems to me there should be one API for this but it seems there are several. The one that makes the most sense seems to be MediaRouter but there are two large issues with it that prevent me from using it as described above:
There are at least 2 scenarios in which it fetches the wrong device as the active route and on other scenarios it straight up doesn't detect route switches at all. For details on this please check out the ticket I opened on the google issue tracker
I need certain information on the current active output device, most importantly a universal identifier. For bluetooth devices, the Complete Local Name can be used for this, which is available from BluetoothDevice types but this is not obtainable from the MediaRouter. Instead, MediaRouter makes a productName available, which sometimes can be an alias of the bluetooth devices, and not the static name.
I have since abandoned this API and moved on to find other solutions, let me know if anyone thinks there's a way around the problems above, most importantly the first one. I will note that I have used both the android.media.MediaRouter and the androidx one, they both have these issues.
I am now leveraging a combination of other APIs. It works but it is a far from acceptable solution:
Using AudioManager.registerAudioDeviceCallback(object : AudioDeviceCallback) for non-bluetooth devices detection (AudioDeviceInfo.TYPE_WIRED_HEADPHONES, AudioDeviceInfo.TYPE_BUILTIN_SPEAKER)). I'm getting callbacks when any of these devices get added or removed and then I can check if a wired type device is present then that's the active one 100% of the time, if it's not, then the embedded-type is active. It's kind of hacky but it works.
More interestingly, for detection of Bluetooth output devices I use a private API, that Android itself uses in the Settings app to display the current audio output device.
BluetoothA2dp::class.java.getDeclaredMethod("getActiveDevice") to get the current active output device. This is done by getting the profile proxy service bluetoothAdapter.getProfileProxy
register a receiver for this action BluetoothA2dp::class.java.getField("ACTION_ACTIVE_DEVICE_CHANGED").get(null) in order to detect switches of the bluetooth active audio device.
This solution works but also has a few limitations:
they are obvious private APIs, subjected to sudden change and potential breaks
the active device APIs mentioned above are not available < Android 9. I have yet to investigate what Android is using pre-Android9 in the Settings app
On Samsung devices the active device API works incorrectly.
So, the million dollar question. How do I fetch and detect the current audio route on Android, reliably?
I cant find anything online but how can i use a chrome tab web audio api in an android app so i can play sound during a phone call.
i went to this site but when i play the sound during a phone call the far end doens't here anything. I thought one feature of web audio was that it can play change the sound of someones voice in a phone call, so i thought it had access to the audio phone call stream.
even here the tech says its ready for android but i cant even get hte audio recorder demo to work on android.
While you do (with the user permission) have access to the input of the device you only have access to the main output of the device (internal speakers or headphones). This is represented as the AudioContext.destination. The buffers in a call is (probably) a different output that you simply don't have access to in Web Audio (and that's probably a good thing. Imagine the security issues we'd have if apps were allowed to hijack calls!).
I'm trying to send audio over my cars speakers without having the cars audio input set to bluetooth. It supports the A2DP profile, and I also managed to get it to work. But that only works when I manually set the input to Bluetooth.
But I would like to 'force' the audio being sent over the speakers.
I previously had an iPhone. The Google Maps app would 'call' itself everything it would pronounce the directions. So my car would see it is an incoming call and play the audio over the speakers.
I looked around the internet, and it seems I need to use the HSF profile to pull of the same trick.
The documentation states that HSF is supported, but it does not show me how to do it. I also found exactly what I needed in the documentation. It states the following:
NOTE: up to and including API version JELLY_BEAN_MR1, this method initiates a virtual voice call to the bluetooth headset. After API version JELLY_BEAN_MR2 only a raw SCO audio connection is established.
So initiating virtual voice calls was possible. I would like to know how to do that now. Any other ideas on how to do this would also be very helpfull.
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...
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.