2

I developed an App to connect to ble devices and exchange data. This works fine for my Smartphone (API Level 23). But when usind one with API leven 26, the onServiceDiscovered Callback never fires.gatt.discoverServices() returns true. I check with newState == BluetoothProfile.STATE_CONNECTEDwhether the connection was successful. After that I implemented a Delay before Starting de Service Discovery with

msecondHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    boolean state = gatt.discoverServices();
                    Log.d(TAG,"State Service Discovered: "+state);
                }
            },3000);

I changed the Delay withing 600 ms to 3000 ms but callback never fires.

Cœur
  • 37,241
  • 25
  • 195
  • 267
FishingIsLife
  • 1,972
  • 3
  • 28
  • 51
  • Why do you wait 3 seconds instead of calling it immediately? – Emil Feb 13 '18 at 13:09
  • Because without a delay, it also doesn't work and some other develovpers wrote in earlyer entries that sometimes this can help. – FishingIsLife Feb 13 '18 at 14:52
  • I've never heard of that service discovery would work better if you insert a delay. You should check the HCI log or use a BLE sniffer to see if there is any service discovery going on. Also check logcat what the Android BLE stack prints. – Emil Feb 13 '18 at 15:21
  • For example here https://stackoverflow.com/questions/41434555/onservicesdiscovered-never-called-while-connecting-to-gatt-server Ans yes, the next step an want to do is use the sniffer and wireshark. But it seems strange to me, that with Marshmallow everything works just finde and with Nougat I can't get any callback than onCennctionStateChanged(). I've read some articles that Nougat can cause some trouble by using ble but none of the given solutions work for me. – FishingIsLife Feb 14 '18 at 07:17

1 Answers1

3

I have observed this issue as well with a A&D UA-651BLE Blood Pressure meter in combination with a Nexus 5 running Android 6.0.1. If I don't add a delay the callback never occurs. I had to play a bit to find the exact delay that worked for this combination of phone and BLE peripheral. However, it only seems to occur for devices that are BOND_BONDED.

I did some test on other phones and with other devices. I never saw this issue with devices running Nougat or higher. The A&D BPM doesn't need a delay on devices with Nougat or Oreo, so I guess the issue was solved in later versions. And even on my Nexus 5 with Android 6.0.1 it only happens with the A&D BPM, while other devices I have also don't need a delay. So really an issue that only occurs with specific combinations. I guess the stack is still busy exchanging keys with the peripheral and discoverServices() doesn't work until that process has been completed.

The Nordic BLE manager code actually does the same thing although their code is not specific to any Android version, see Android-BLE-Library

So here is my code. I didn't bother to make the delay device specific so that I have a greater changes of success and it doesn't seem to bother devices that don't need the delay.

    // Take action depending on the bond state
    if(bondstate == BOND_NONE || bondstate == BOND_BONDED) {
        // Connected to device, now proceed to discover it's services but delay a bit if needed
        int delayWhenBonded = 0;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
             // It seems delays when bonded are only needed in versions below Nougat
             // This issue was observed on a Nexus 5 running Android 6.0.1 when connection to a A&D UA-651BLE
             // Strangely enough, it also is dependent on the peripheral as others don't seem to need a delay
             delayWhenBonded = 1000;
        }
        final int delay = bondstate == BOND_BONDED ? delayWhenBonded : 0;
        bleHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                HBLogger.i(TAG, String.format("Discovering services of '%s' with delay of %d ms", getName(), delay));
                boolean result = gatt.discoverServices();
                if (!result) {
                     HBLogger.i(TAG, "DiscoverServices failed to start");
                }
            }
        }, delay);
   } else if (bondstate == BluetoothDevice.BOND_BONDING) {
        // Apparently the bonding process has already started let it complete
        HBLogger.i(TAG, String.format("Wait for bonding to complete"));
   }