This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Trouble finding characteristics using android nRF toolbox, while the nRF Connect android app finds it ok

Okay so the issue is a little more complicated than this.

Phones used for testing were htc m8 (android 6.0) and lg g5 (android 7.0).

Ble chip running on a linux OS using BlueZ stack.

I've modified two nRF toolbox apps to test the problem. The first one is BMP that uses a static reference to the BLEManager class, and the CSC which runs the BLEManager as a service. The behaviour is the same on both apps. My modifications consisted of:

  1. Added my custom UUID to the ble scan filter.
  2. Added a log that will print available services in onServicesDiscovered() callback.

Now the procedure and observations:

After resetting ble chip, and all app settings.

Step 1

  1. Start nRF toolbox app and select bmp or csc app (with modified UUIDs by me). Run BLE scan with the service filter. The device is found.
  2. Connect to the device and initiate the service discovery
  3. print all services in onServicesDiscovered().
  4. The primary service used in the filter is not displayed in the log.

Note: I have tried this with multiple connections tries, multiple discoverServices calls including using the hidden android ble refresh() method. Results are the same.

Step 2

  1. Run nRF android app downloaded from the google store.
  2. Connect to BLE chip
  3. The service is instantly found.

Note: Same can be achieved running boilerplate BLE code on an iOS device.

Step 3

  1. Disconnect from the device in the nRF android app and go back to the nRF toolbox app.
  2. Repeat step 1
  3. Now the service is displayed in the list of available services and can be used for communication.

Observations:

The service used to filter the scanned devices works, but then that service is not displayed in the onServicesDiscovered() until we run the nRF Connect Android app. I'm having trouble coming up with any reason for this. What is the nRF Connect app doing differently?

  • Hi,

    First of all, service UUIDs used in the adv packet don't need to be present in the device database. You may advertise with whatever, and what services you have on the device is a different thing. Of course it's good to expose what you have, not cheat, but it's practically possible to do this.

    I think your issue may be related to the Android device caching services. In nRF Connect we used to (before Nougat) clear cache every time you disconnect from a device and close the tab (it's shown on the log, can be viewed in nRF Logger as this is the last thing nRF Connect does before closing the tab and the built-it log). We did it not to keep cache clear, but it made the next connection more stable and reliable. Since Nougat we assume that the BLE is mature enough, and if user want's to refresh cache, there is an option in the menu for that.

    In nRF Toolbox we don't clear cache, so it may be that when you connected to a device before you flashed the current firmware, the old services were cached and now the app displays the old ones. Opening nRF Connect clears cache on disconnect, so next time you open nRF Toolbox it will do the proper service discovery.

    This explanation is not completely compatible with your issue, but please check if it's correct. Perhaps when you flash BPM/CSC on the same device it caches them and when you try a different profile with different fw it still shows the old ones? In real life devices very rarely change their databases.

    BR, Aleksander

  • I tried clearing the device cache, but that didn't turn out to be the issue. After further investigation on the hardware side the BlueZ chip would go into BR / EDR mode. This allowed for a successful GATT connection on the Android side, but the services did not exist in onServicesDiscovered. In order for the services to show up, the connection had to explicitly specify a BLE connection.

    NRFToolbox connection code:

    device.getDevice().connectGatt(applicationContext, false, mGattCallback);

    The fix:

    device.getDevice().connectGatt(applicationContext, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);

    Note: this method call requires Android API 23.

  • You may call this method in previous APIs as well, since 19 or 20, afair, just using reflections as it's hidden with @hide.

  • We will have it fix on nRF Toolbox soon. Thanks for pointing it out.

Related