12
votes

Following a lot of answers here, I am able to build the list of connected bluetooth devices with the help of a BroadcastReceiver. Now my question is how do I know which device supports which profile. I want to be able to pick the devices based on the profile, for example, get a list of currently connected devices and their profile, and pick one of them. I don't see how I can get such info if I have the instance of BluetoothDevice.

On this page there are some codes illustrating how to work with a bluetooth headset profile: http://developer.android.com/guide/topics/connectivity/bluetooth.html#Profiles. But it doesn't solve my problem. If you think I am missing anything, please help me and point it out.

Thanks a lot in advance.

2

2 Answers

4
votes

I've run into the same problem. It doesn't appear that you can get the available profiles from the BluetoothDevice class. But there is a long way around by getting a List of BluetoothDevices from the getDevicesMatchingConnectionStates method in the BluetoothProfile class.

For example if you want to find which BluetoothDevices support A2DP, first create a custom BluetoothProfile.ServiceListener

public class cServiceListener implements BluetoothProfile.ServiceListener {
private static final int[] states={ BluetoothProfile.STATE_DISCONNECTING,
                                    BluetoothProfile.STATE_DISCONNECTED,
                                    BluetoothProfile.STATE_CONNECTED,
                                    BluetoothProfile.STATE_CONNECTING};
@Override
public void onServiceConnected(int profile, BluetoothProfile bluetoothProfile) {
List<BluetoothDevice> Devices=bluetoothProfile.getDevicesMatchingConnectionStates(states);
    for (BluetoothDevice loop:Devices){
        Log.i("myTag",loop.getName());
    }
}

@Override
public void onServiceDisconnected(int profile) {
}

}

Then attach it to the profile you want to check, in this example A2DP

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
cServiceListener mServiceListener=new cServiceListener();
mBluetoothAdapter.getProfileProxy(thisContext,mServiceListener, BluetoothProfile.A2DP);

This will logcat all the bluetooth devices that support A2DP which are in the requested states. In this example it includes all devices which are currently connected and previously paired devices which are disconnected.

2
votes

Looking at the Android source code, you can guess which profiles are available for a device by looking at its UUIDs, and then connect each profile one by one.

Step 0 : Copy the _PROFILE_UUIDS constants from there : https://android.googlesource.com/platform/packages/apps/Settings/+/9ad703cdb9a8d0972c123b041d18aa7bbeb391a4/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java

Step 1 : get your BluetoothDevice, via scanning for instance. Assure that it's properly bonded.

Step 2 : register a BroadcastReceiver for the android.bluetooth.BluetoothDevice.ACTION_UUID action intent

Step 3 : on your device, call the fetchUuidsWithSdp method

Step 4 : you will recieve a ACTION_UUID broadcast : in the onReceive method you can unregister the receiver, and get the list of profiles like so :

ArrayList<Integer> profiles = new ArrayList<>();

ParcelUuid[] uuids = device.getUuids();

if (BluetoothUuid.containsAnyUuid(uuids, HEADSET_PROFILE_UUIDS))
{
    profiles.add(BluetoothProfile.HEADSET);
}

if (BluetoothUuid.containsAnyUuid(uuids, A2DP_PROFILE_UUIDS))
{
    profiles.add(BluetoothProfile.A2DP);
}

if (BluetoothUuid.containsAnyUuid(uuids, OPP_PROFILE_UUIDS))
{
    //OPP doesn't have any BluetoothProfile value
}

if (BluetoothUuid.containsAnyUuid(uuids, HID_PROFILE_UUIDS))
{
    //You will need system privileges in order to use this one
    profiles.add(BluetoothProfile.INPUT_DEVICE);
}

if (BluetoothUuid.containsAnyUuid(uuids, PANU_PROFILE_UUIDS))
{
    profiles.add(BluetoothProfile.PAN);
}

Step 5 : get the proxies for the profiles, one by one :

for (int profile : profiles)
{
    if (!adapter.getProfileProxy(context, listener, profile))
    {
        //Do something
    }
}

Step 6 : do anything with each proxy retrieved in the onServiceConnected method of your listener. You can access the connect method using relfection.