Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android 6.0 requests pairing with remote devices when fetching UUIDS

I'm trying to fetch the UUIDS from a remote bluetooth device like this:

        device.fetchUuidsWithSdp();

This will work silently and without user interaction on all devices except those with Android 6.0 which visibly ask with a pairing dialog to connect with the remote device to fetch the UUID. Is that an expected behaviour? Where is this documented? Is there a way to trigger UUID discovery without explicitly having to allow it from the other end?

like image 398
Roberto Betancourt Avatar asked Nov 11 '15 23:11

Roberto Betancourt


People also ask

What are Bluetooth UUIDs?

The UUID is used for uniquely identifying information. It identifies a particular service provided by a Bluetooth device. The standard defines a basic BASE_UUID: 00000000-0000-1000-8000-00805F9B34FB . Devices such as healthcare sensors can provide a service, substituting the first eight digits with a predefined code.

What is device pairing on Android?

Pairing is the process required to mutually register the information on BLUETOOTH devices to be connected wirelessly. It is necessary to pair BLUETOOTH devices to establish a BLUETOOTH connection.

What is service UUID?

“A UUID is a universally unique identifier that is guaranteed to be unique across all space and all time” (Bluetooth 4.2 spec, Vol 3, Part B, section 2.5. 1 UUID) A UUID is a 128-bit value. There are reserved UUIDs by the Bluetooth SIG that are generally represented by their 16-bit aliases.

How do I get a list of Bluetooth devices on my Android phone?

By using BluetoothAdapter method getBondedDevices(), we can get the Bluetooth paired devices list. Following is the code snippet to get all paired devices with name and MAC address of each device.


1 Answers

I've found a workaround to this by using the hidden sdpSearch method instead of fetchUuidsWithSdp. This requires a bit of reflection. This worked for me on android 6.0 and 5.1.1, without the devices trying to pair. Hope this helps, and feel free to improve the rather poor exception handling.

public class DeviceFinder{

public interface Callback{
    void onDeviceFound(BluetoothDevice bd);
    void onFinishedCallback();
    void onStartCallback();
}

private ArrayList<BluetoothDevice> tempDevices = new ArrayList<>();
private Callback mCallback;
private Context mContext;
private String ACTION_SDP_RECORD;
private String EXTRA_SDP_SEARCH_RESULT;

private BroadcastReceiver mReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (BluetoothDevice.ACTION_FOUND.equals(action)){
            // Aggregating found devices
            BluetoothDevice bd = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            tempDevices.add(bd);
        }else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){
            // Prepare for new search
            tempDevices = new ArrayList<>();
            mCallback.onStartCallback();
        }else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
            // Do a sdpSearch for all found devices
            for (BluetoothDevice bd : tempDevices){
                try {
                    Method m = bd.getClass().getDeclaredMethod("sdpSearch", ParcelUuid.class);
                    m.invoke(bd, new ParcelUuid(/* your uuid here */));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            mCallback.onFinishedCallback();
        }else if( ACTION_SDP_RECORD.equals(action)){
            // check if the device has the specified uuid
            BluetoothDevice bd = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if (intent.getIntExtra(EXTRA_SDP_SEARCH_RESULT, 1) == 0){
                mCallback.onDeviceFound(bd);
            }
        }
    }
};


public DeviceFinder(Context context, Callback mCallback){
    this.mCallback = mCallback;
    this.mContext = context;

    try {
        Field f = BluetoothDevice.class.getDeclaredField("ACTION_SDP_RECORD");
        ACTION_SDP_RECORD = ((String)f.get(null));
        f = BluetoothDevice.class.getDeclaredField("EXTRA_SDP_SEARCH_STATUS");
        EXTRA_SDP_SEARCH_RESULT = ((String)f.get(null));
    } catch (Exception e) {
        e.printStackTrace();
    }


    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
    intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
    intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
    intentFilter.addAction(ACTION_SDP_RECORD);
    context.registerReceiver(mReceiver, intentFilter);
    startScan();
}

public void startScan(){
    BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (!bluetoothAdapter.isDiscovering()) {
        bluetoothAdapter.startDiscovery();
    }
}

public void unregisterReciever(){
    mContext.unregisterReceiver(mReceiver);
}
}

edit: sdpSearch was added in android 6.0, so it does not work for earlier versions

like image 50
Alexander K Avatar answered Oct 23 '22 04:10

Alexander K