Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

This page from Android's Developer site suggests the way to go about it is to test each in turn through the AudioManager.

if (isBluetoothA2dpOn()) {
    // Adjust output for Bluetooth.
} else if (isSpeakerphoneOn()) {
    // Adjust output for Speakerphone.
} else if (isWiredHeadsetOn()) {
    // Adjust output for headsets
} else { 
    // If audio plays and no one can hear it, is it still playing?
}

Alternatively you could write BroasdcastRecievers to listen for bluetooth and headset connect and disconnect events and perform some actions including saving the output stream target. If you go down this road be mindful of the case where the device has just powered on and there may have not have been a Broadcast triggered to have been received.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top