Android BLE: onServicesDiscovered never fires on N

2020-06-04 08:45发布

问题:

I am developing an Android app that connects to a custom Bluetooth device. A number of posts have been very helpful (such as this and this), but I am experiencing an issue not solved by any if those suggestions.

After a successful Bluetooth connection, I call BluetoothGatt.discoverServices, which on most devices performs correctly. On the Nexus 5 and Samsung Note 3, I never receive any response (onServicesDiscovered), either successful or otherwise. This occurs on the very first connection attempt and no combination of disconnect() or close() seems to fix it.

I have anecdotal evidence for this being an Android OS bug; only our Nexus 5 that was still on 4.4.2 experienced this problem, and upgrading to 4.4.3 seems to have fixed it. This isn't yet an option for the Samsung however and I'd like to find a workaround if possible. I know we've connected to Nexus 5 without these problems in the past; while I'm trying to track down what might have changed I'd appreciate any thoughts.

Samsung Note 3 Logs:

07-02 17:29:54.891 I/PeripheralManager( 8282): Connect has been called on HFEC161332B90C15C29E DF:5F:C8:DF:04:35 -43 , shouldPair = true
07-02 17:29:54.891 I/PeripheralManager( 8282): BTSTATE acquiring new gatt and connecting...
07-02 17:29:54.891 D/BluetoothGatt( 8282): connect() - device: DF:5F:C8:DF:04:35, auto: false
07-02 17:29:54.891 D/BluetoothGatt( 8282): registerApp()
07-02 17:29:54.896 D/BluetoothGatt( 8282): registerApp() - UUID=2fc3ce73-c50c-4cda-8b82-1532a5dccb14
07-02 17:29:54.896 D/BtGatt.GattService( 3434): registerClient() - UUID=2fc3ce73-c50c-4cda-8b82-1532a5dccb14
07-02 17:29:54.896 D/BtGatt.btif( 3434): btif_gattc_register_app
07-02 17:29:54.896 D/BtGatt.btif( 3434): btgattc_handle_event: Event 1000
07-02 17:29:54.896 D/BtGatt.btif( 3434): btif_gattc_upstreams_evt: Event 0
07-02 17:29:54.901 D/BtGatt.GattService( 3434): onClientRegistered() - UUID=2fc3ce73-c50c-4cda-8b82-1532a5dccb14, clientIf=5
07-02 17:29:54.901 I/BluetoothGatt( 8282): Client registered, waiting for callback
07-02 17:29:54.901 D/BluetoothGatt( 8282): onClientRegistered() - status=0 clientIf=5
07-02 17:29:54.901 D/BtGatt.GattService( 3434): clientConnect() - address=DF:5F:C8:DF:04:35, isDirect=true
07-02 17:29:54.901 D/BtGatt.btif( 3434): btif_gattc_open
07-02 17:29:54.901 D/BluetoothAdapter( 8282): stopLeScan()
07-02 17:29:54.906 D/BtGatt.btif( 3434): btgattc_handle_event: Event 1004
07-02 17:29:54.906 D/BtGatt.btif( 3434): btif_get_device_type: Device [df:5f:c8:df:04:35] type 2, addr. type 1
07-02 17:29:54.906 D/BtGatt.btif( 3434): btif_gattc_upstreams_evt: Event 2
07-02 17:29:54.906 D/BtGatt.GattService( 3434): onConnected() - clientIf=5, connId=5, address=DF:5F:C8:DF:04:35
07-02 17:29:54.906 D/BluetoothGatt( 8282): onClientConnectionState() - status=0 clientIf=5 device=DF:5F:C8:DF:04:35
07-02 17:29:54.906 I/PeripheralManager( 8282): Gatt State Connected
07-02 17:29:54.906 D/BluetoothGatt( 8282): discoverServices() - device: DF:5F:C8:DF:04:35
07-02 17:29:54.911 D/BtGatt.GattService( 3434): discoverServices() - address=DF:5F:C8:DF:04:35, connId=5
07-02 17:29:54.911 D/BtGatt.btif( 3434): btif_gattc_search_service
07-02 17:29:54.911 I/PeripheralManager( 8282): Gatt Service Discovery Started
07-02 17:29:54.911 D/BtGatt.btif( 3434): btgattc_handle_event: Event 1006
…
07-02 17:30:24.901 W/PeripheralManager( 8282): Connection time out hard
07-02 17:30:24.921 I/PeripheralManager( 8282): canceling connection

Connect Code:

public void connect(final Peripheral peripheral, boolean pair) {
    Log.i(TAG,  "Connect has been called on " + peripheral.toString() + ", shouldPair = " + pair);
    this.shouldPair = pair;
    bluetoothHandler.post(new Runnable() {
         @Override
         public void run() {
            if(isConnected) {
                Log.w(TAG, "Connecting when already connected!");
                return;
            }
            if (mBluetoothAdapter == null || peripheral == null || peripheral.getAddress() == null) {
                Log.e(TAG, "BluetoothAdapter not initialized or unspecified address.");
                return;
            }
            final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(peripheral.getAddress());
            if (device == null) {
                Log.e(TAG, "Device not found.  Unable to connect.");
                return;
            }
            if(mBluetoothGatt != null) { // use existing gatt if present and not closed
                Log.i(TAG, "connecting to existing gatt...");
                mBluetoothGatt.connect();
            } else {
                Log.i(TAG, "acquiring new gatt and connecting...");
                mBluetoothGatt = device.connectGatt(context, false, mGattCallback);
            }
         }
    });

    lastConnectedPeripheral = peripheral;
}

Discovering Services:

private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            if (newState == BluetoothGatt.STATE_CONNECTED) {
                Log.i(TAG,"Gatt State Connected");
                isBluetoothConnected = true;
                tryDiscoveringServices();
                ...

Please let me know what additional information might shed light on this. Thanks!

EDIT: After a change in our firmware, the problem has lessened: instead of never connecting, it takes just over one minute to connect. This indicates the problem is at least partially due to our particular bluetooth device in addition to whatever Android OS changes. I will update if I discover how to solve this related problem.