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

nRFToobox on Android not recognizing changes in application type running on Nordic pcb

Today nRF Toolbox App on my Android 5.0 phone is only recognizing HRM code running on my nRF5182-mkit, not other examples.

  • Today nRFToobox and nRFUART2.0 Apps both report "The Device Does not have the required services" when I try anything other than HRM code yesterday and today.

  • Two days ago it was allowing me to easily switch between code on the mkit, but then something changed. It was about same time as the latest nRFToolbox update on playstore. Funnily enough it was just after the previous Nordic updates on playstore that this all started working, as two weeks ago it wasn't working with similar issue. Did a fix get undone?

  • nRF-MCP App is shows changes in Device Name when I run other sample code on my mkit (Thermometer, UART Loopback, HRM, etc.)

  • I tried wiping the cache in the Android 5.0 phone, no effect

  • I can capture with nRF-MCP or Sniffer if that will help (just tell me what you need, I'm not very familiar with either of those)

Any help appreciated! Paul

Parents
  • Hi,

    There are 4 ways to clear the attribute cache on Android:

    1. Using Service Changed characteristic - the proper solution:

    a) when not bonded - android should never cache services if such characteristic is present in Generic Attribute service. However it always does - this is the Android bug, reported here: code.google.com/.../detail

    b) when bonded - a device may enable CCCD indications on Service Changed char. Whenever Android receives this indication it will perform service rediscovery automatically. When writing Android code make sure that you give ~2 sec after you get onConnectionStateChange(Connected) event before calling gatt.discoverServices() when you expect that the indication may be received. If you call it immediately, inside the onConnStateCh callback, you'll get old services as this callback is called immediately when you connect but before the bond has been re-established and the indication was sent.


    When you don't use bonding or you don't want to use Service Changed indications, or when you are flashing your board with different firmwares you may find useful this:

    1. Using Android hack - there is a hidden method refresh() on the Android API. It works since Android 4.3 but it may be removed in any new release. I'm calling it when you disconnect from the DFU in nRF Toolbox and whenever you disconnect from the device in MCP. In the upcomming version MCP 2.1 (release tomorrow(?)) there will be an option to change in MCP settings (connectivity): refresh always (after disconnection), refresh only when not bonded (also only after diconnnecting), refresh never (actually it will refresh when an error occur)

    2. Use different device address when services are different. When you design a firmware that has different modes with different services consider using different device address in every of them. In that case the cache will not be a problem.

    3. On older versions of Android (f.e. 4.3) restarting Bluetooth adapter was also clearing the cache. As we can observe now this no longer works which is OK (cache shouldn't be cleared unless services are changed). This no longer works.


    So.. if you want to use different firmware on the same device use the trick with the nRF MCP. As I've written before it refreshes the cache every time it disconnects from the device. If you check the log on DEBUG level you will see the gatt.refresh() method being called.

Reply
  • Hi,

    There are 4 ways to clear the attribute cache on Android:

    1. Using Service Changed characteristic - the proper solution:

    a) when not bonded - android should never cache services if such characteristic is present in Generic Attribute service. However it always does - this is the Android bug, reported here: code.google.com/.../detail

    b) when bonded - a device may enable CCCD indications on Service Changed char. Whenever Android receives this indication it will perform service rediscovery automatically. When writing Android code make sure that you give ~2 sec after you get onConnectionStateChange(Connected) event before calling gatt.discoverServices() when you expect that the indication may be received. If you call it immediately, inside the onConnStateCh callback, you'll get old services as this callback is called immediately when you connect but before the bond has been re-established and the indication was sent.


    When you don't use bonding or you don't want to use Service Changed indications, or when you are flashing your board with different firmwares you may find useful this:

    1. Using Android hack - there is a hidden method refresh() on the Android API. It works since Android 4.3 but it may be removed in any new release. I'm calling it when you disconnect from the DFU in nRF Toolbox and whenever you disconnect from the device in MCP. In the upcomming version MCP 2.1 (release tomorrow(?)) there will be an option to change in MCP settings (connectivity): refresh always (after disconnection), refresh only when not bonded (also only after diconnnecting), refresh never (actually it will refresh when an error occur)

    2. Use different device address when services are different. When you design a firmware that has different modes with different services consider using different device address in every of them. In that case the cache will not be a problem.

    3. On older versions of Android (f.e. 4.3) restarting Bluetooth adapter was also clearing the cache. As we can observe now this no longer works which is OK (cache shouldn't be cleared unless services are changed). This no longer works.


    So.. if you want to use different firmware on the same device use the trick with the nRF MCP. As I've written before it refreshes the cache every time it disconnects from the device. If you check the log on DEBUG level you will see the gatt.refresh() method being called.

Children
Related