I am talking about STREAM_VOICE_CALL
The scenario is as follows: 1. Connect wired headset to the phone 2. Connect bluetooth headset to the phone 3. Start application that plays audio to STREAM_VOICE_CALL
The OS redirects audio of this stream automatically - to the last device that connected. So, if bluetooth headset connected after wired headset, audio will be played to the bluetooth headset, and vice versa.
So the question is: how can I know what device was most recently connected, before my app was running.
I want to mention that I have no issues with manipulations with audio devices while my app is running - I know to get all the OS events and know exactly where the audio is redirected to. The only issue is as I mentioned - how to determine what the state is.
There was a deprecated method - Audiomanager.getRouting(stream) This is exactly what I need, but I didn't find any alternative.
Thank you in advance.
May be a little late for you, but here is the API 11+ approach that has worked best for me:
private static BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
private static BluetoothProfile mBtProfile;
public BluetoothInformationClass() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
mBluetoothAdapter.getProfileProxy(context, getServiceListneer(), BluetoothProfile.HEADSET);
}
}
/**
* Tries to get the name of the audio route device we're being played back through.
* There are some important behaviors to note:
* 1) Headphones are always the audio route when plugged in.
* 2) BT will be the audio route whenever ever possible except where 1 is relevant.
* BT can be on, but not the audio routd. In that case we allow BT to try and fail
* we check its result, if it was a failure we do the final stab at things.
*
* @return
*/
public static String getAudioRouteDeviceName() {
AudioManager audioManager = (AudioManager)
context.getSystemService(Context.AUDIO_SERVICE);
BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();
String audioRoute = "";
if (audioManager.isWiredHeadsetOn()) {
audioRoute = "Wired Headset";
} else if (audioManager.isBluetoothA2dpOn()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
audioRoute = getApiElevenPlusName(bluetooth);
}
}
if (audioRoute.equals("")) {
if (audioManager.isSpeakerphoneOn()) {
audioRoute = "Phone Speaker";
} else {
audioRoute = "Phone";
}
}
return audioRoute;
}
/**
* 11+ api's have this fancy mechanism for figuring out connected devices. Pre 11 its a lot less stable and for now we're going to ignore it.
* @return
*/
@TargetApi(11)
private BluetoothProfile.ServiceListener getServiceListneer() {
return new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
mBtProfile = proxy;
}
public void onServiceDisconnected(int profile) {
if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = null;
}
mBtProfile = null;
}
};
}
/**
* Tries to locate the currently connected device.
* @param bluetooth
* @return
*/
@TargetApi(11)
private static String getApiElevenPlusName(BluetoothAdapter bluetooth) {
String ret = "";
BluetoothDevice[] devices = bluetooth.getBondedDevices().toArray(new BluetoothDevice[bluetooth.getBondedDevices().size()]);
if (mBtProfile != null) {
for (BluetoothDevice device : devices) {
if (mBtProfile.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED) {
ret += device.getName();
}
}
}
return ret;
}
Some assumptions here:
1) Wired Headphones will generally always be preferred as an Audio Route based on my testing. Even when paired to BT headphones/car stereos etc... once you plug a wired headset in that becomes the audio route.
2) If you can't get a name of a BT device, this approach assumes that you are not using a BT device. That assumption isn't strictly true, however this approach works on all 11+ devices, and since thats 90+% of the market it should be sufficient.