Search code examples
androidbluetooth-lowenergyuuidmac-address

Android BLE stack caching services?


I am developing a first app with Bluetooth low energy. I'm in control of both ends - the server is running on an Arduino Nano 33 BLE - which has an nRF chipset.

The server is a bit odd - it actually runs one of two sets of code depending on how it is started (largely because I've only got one Nano BLE). So it can be one of two servers (same MAC address), but server A supports one service and its set of characteristics, server B another service with its characteristics. Both services obviously have unique UUIDs.

The problem is, when the app has been connected to - say - A, and the server is turned off and back on again in guise B, on connection and discovering services, the app still 'discovers' the A service UUID, and not B.

Repeatedly power cycling the server makes no difference, nor does disabling and re-enabling Bluetooth on the Android device, or restarting the app. The only thing that works is a complete reboot of the Android device.

Seems to me the BLE stack is caching what it thinks the capabilities of a specific server MAC address are.

Cannot find a way round this (don't think I can change the Nano BLE MAC address), BUT when I run the nRF diagnostic Android app, it does find the right service, so it must be possible. What that does though is always go through a BLE scan process first so maybe that flushes any cache.

However, I really do not want to enforce a scan, and therefore would be grateful for any comments, or details on how to clear any cache.


Solution

  • STOP PRESS:

    Found an answer to this: 'Android Bluetooth not discovering the characteristic after changing UUID'

    It appears that the BLE stack does cache services etc for an indeterminate time, in order to speed up future service discovery. Bit of a problem if the services for a MAC address do change (like mine), but I suppose that is not really expected behaviour (though not forbidden as far as I know). Don't know how long it is cached for, but I noticed that overnight it sorted itself out - then got it wrong on the next change, of course.

    There is an internal BluetoothGatt.refresh() method that clears the cache - but it is not published. The link shows how to get at it with reflection, and it does appear to work. On an old Nexus 7 2013 running 6.0.1, that is. Not sure about later OSs as reflection seems to be frowned on by Google these days. About to try it on a Pixel 2 running Android 11.