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"));
}