Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android's BLE Service Discovery (BluetoothGatt#discoverServices()) and Low Energy vs BR/EDR

TLDR: Is it expected that service discovery results via discoverServices() will differ based on the underlying transport (LE vs. BR/EDR)?

I have a mixed-mode Bluetooth accessory that offers distinct features as a Bluetooth Classic device and as a Bluetooth LE Peripheral.

Android has trouble discovering the accessory's Bluetooth LE GATT services unless you use the hidden peerBluetoothDevice.connectGatt(context, autoConnect, gattCallback, BluetoothDevice.TRANSPORT_LE) API that allows you to force use of either TRANSPORT_LE or TRANSPORT_BREDR.

When I connected the device via peerBluetoothDevice.connectGatt(context, autoConnect, gattCallback) and then called discoverServices() I'd only discover the generic Service UUIDs (and only after many failed connection attempts with mysterious status 133 delivered to onConnectionStateChange).

  • “00001800-0000-1000-8000-00805f9b34fb” (Generic Access)
  • “00001801-0000-1000-8000-00805f9b34fb” (Generic Attribute).

However, when I invoke the hidden peerBluetoothDevice.connectGatt(context, autoConnect, gattCallback, BluetoothDevice.TRANSPORT_LE) and then called discoverServices() I get the full expected service discovery response:

  • "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" (My custom service)
  • “00001800-0000-1000-8000-00805f9b34fb” (Generic Access)
  • “00001801-0000-1000-8000-00805f9b34fb” (Generic Attribute).

Is this expected Android framework behavior (Doubt it, hence hidden API)? Is it bad form to design a peripheral device with this 'mixed mode' operation?

like image 719
dbro Avatar asked Jun 04 '15 21:06

dbro


People also ask

What is Android BLE only devices?

Android provides built-in platform support for Bluetooth Low Energy (BLE) in the central role and provides APIs that apps can use to discover devices, query for services, and transmit information. Common use cases include the following: Transferring small amounts of data between nearby devices.

How do I find a BLE device?

To find BLE devices, you use the startScan() method. This method takes a ScanCallback as a parameter. You must implement this callback, because that is how scan results are returned.

What are BLE services?

Data Broadcast (aka BLE beacons, aka connection-less communication) used for sensors broadcasting their data openly to any interested neighboring device. This is a one-way communication method where a device broadcasts its data to all neighbouring devices in RF range.

How do I turn off Bluetooth low energy Android?

Users can disable system-level Bluetooth background scanning by going to Settings > Security & Location > Location > Scanning and disabling the toggle for Bluetooth scanning. This does not affect BLE scanning for location or local devices.


1 Answers

The

BluetoothDevice.connectGatt(Context context, boolean autoConnect, android.bluetooth.BluetoothGattCallback callback, int transport)

method is public as of API 23, and so seems to be the sanctioned way of avoiding the problem described above.

The method appears to have been introduced to AOSP in the android-5.0.0_r1 release, and was present in every release leading up to it being made public in API 23. Therefore, it should be safe to invoke via reflection for devices with API levels 21 and 22. For devices with prior platform versions, it appears the Android framework does not provide tools to mitigate the issue.

like image 161
dbro Avatar answered Nov 10 '22 13:11

dbro