当writeDescriptor接收到true时,不会触发BLE onDescriptorWrite

时间:2019-10-25 09:30:13

标签: android bluetooth-lowenergy

这是我启用特征通知的代码。

private void enableNotification(BluetoothGattCharacteristic characteristic) {
    boolean s = bluetoothGatt.setCharacteristicNotification(characteristic, true);
    Log.d(TAG, "enableNotification: setCharacteristicNotification " + s);
    List<BluetoothGattDescriptor> descriptors = characteristic.getDescriptors();
    if (null != descriptors && descriptors.size() > 0) {
        for (BluetoothGattDescriptor descriptor : descriptors) {
            Log.d(TAG, "enableNotification: " + descriptor.getUuid());
            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            boolean s1 = bluetoothGatt.writeDescriptor(descriptor);
            Log.d(TAG, "enableNotification: writeDescriptor " + s1);
        }
    } else {
        Log.d(TAG, "enableNotification: descriptors is null");
    }
}

以下是日志

BluetoothGatt: setCharacteristicNotification() - uuid: 00002a4d-0000-1000-8000-00805f9b34fb enable: true
BleService: enableNotification: setCharacteristicNotification true
BleService: enableNotification: 00002902-0000-1000-8000-00805f9b34fb
BleService: enableNotification: writeDescriptor true
BluetoothGatt: onConnectionUpdated() - Device=5C:B6:CC:00:1E:23 interval=40 latency=4 timeout=600 status=0

我们可以看到, writeDescriptor返回true,但是不会触发onDescriptorWrite()方法,并且BluetoothGatt显示日志onConnectionUpdated()。如果有人可以说出为什么我的通知没有触发器。以下是我在BluetoothGattCallback中的onDescriptorWrite代码,如果执行了该代码,无论如何都会有一些日志。

@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
    super.onDescriptorWrite(gatt, descriptor, status);
    if (status == BluetoothGatt.GATT_SUCCESS) {
        Log.d(TAG, "onDescriptorWrite: GATT_SUCCESS");
        connectCallback.readMeterId();
    } else if (status == BluetoothGatt.GATT_FAILURE) {
        Log.d(TAG, "onDescriptorWrite: GATT_FAILURE");
    } else {
        Log.d(TAG, "onDescriptorWrite: something");
    }
}

我的BluetoothGattCallback代码如下

private BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                bluetoothGatt.discoverServices();
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                gatt.close();
                Log.d(TAG, "onConnectionStateChange: DISCONNECTED");
            } else {
                Log.d(TAG, "onConnectionStateChange: FAIL");
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            if (status == BluetoothGatt.GATT_SUCCESS) {
                //print all the service and characteristic
                for (BluetoothGattService service : bluetoothGatt.getServices()) {
                    Log.d(TAG, "onServicesDiscovered: service ->" + service.getUuid());
                    for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
                        Log.d(TAG, "onServicesDiscovered: characteristic ->" + characteristic.getUuid());
                    }
                }

                BluetoothGattService service = bluetoothGatt.getService(UUID.fromString(BleConstant.SERVICE_UUID.SERVICE));
                characteristics = service.getCharacteristics().subList(0, 2);
//                enableNotification(characteristics.get(0));
                for (BluetoothGattCharacteristic characteristic : characteristics) {
                    Log.d(TAG, "onServicesDiscovered: Properties -> " + characteristic.getUuid() + " " + characteristic.getProperties());
                    enableNotification(characteristic);
                }
            } else {
                Log.d(TAG, "onServicesDiscovered received: " + status);
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            Log.d(TAG, "onCharacteristicChanged: " + Arrays.toString(characteristic.getValue()));
            Log.d(TAG, "onCharacteristicChanged: string -> " + characteristic.getStringValue(0));

            String callbackDataString = characteristic.getStringValue(0);
            byte[] callbackDataByte = characteristic.getValue();
//            boolean checkData = CRC16Util.getInstance().verification(callbackDataString);

            dosomething with the response date

            if (CRC16Util.getInstance().verification(callbackDataString)) {
                connectCallback.crcError();
            }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            Log.d(TAG, "onCharacteristicRead: " + Arrays.toString(characteristic.getValue()));
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            Log.d(TAG, "onCharacteristicWrite: " + Arrays.toString(characteristic.getValue()));
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorWrite(gatt, descriptor, status);
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.d(TAG, "onDescriptorWrite: GATT_SUCCESS");
                connectCallback.readMeterId();
            } else if (status == BluetoothGatt.GATT_FAILURE) {
                Log.d(TAG, "onDescriptorWrite: GATT_FAILURE");
            } else {
                Log.d(TAG, "onDescriptorWrite: something");
            }
        }
    };

此代码connectCallback中的接口是这样的

    public interface ConnectCallback {
        /**
         * It needs to be triggered after notify successful
         */
        void readMeterId();

        /**
         * callback of CRC ERROR
         */
        void crcError();

        /**
         * callback of Transmission completed
         */
        void onComplete();

        /**
         * callback of Read MeterId Error
         */
        void onReadMeterIdError();

    }

仅在onDescriptorWrite成功(通知成功)时才向ble发送命令

以下是我的连接代码

    public boolean connectToDevice(final String address, ConnectCallback connectCallback) {
        if (null == bluetoothAdapter || null == address) {
            Log.d(TAG, "BluetoothAdapter not initialized or unspecified address.");
            return false;
        }

        if (null != bluetoothGatt) {
            bluetoothGatt = null;
        }

        final BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
        if (device == null) {
            Log.d(TAG, "Device not found.  Unable to connect.");
            return false;
        }
        Log.d(TAG, "Trying to create a new connection.");
        this.connectCallback = connectCallback;
        bluetoothGatt = device.connectGatt(this, false, bluetoothGattCallback);
        return true;
    }

我在Service中编写所有ble代码,并在这样的活动中使用

 private void bindBleService() {
        serviceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                BleService.LocalBinder binder = (BleService.LocalBinder) service;
                bleService = binder.getService();

                if (!bleService.init()) {
                    Log.e(TAG, "Unable to initialize Bluetooth");
                    finish();
                }

                boolean isConn = bleService.connectToDevice(deviceAddress, new BleService.ConnectCallback() {

                    @Override
                    public void readMeterId() {
                        notifySuccess = true;
                        runOnUiThread(() -> {
                            waitBleDialog.setTitle(getString(R.string.edit_read_meter_id));
                            waitBleDialog.show();
                        });
                        bleService.sendDataToBle(READ_METER_ID.OCP);
                        meterIdUsed.put(READ_METER_ID.OCP, true);
                    }

                    @Override
                    public void crcError() {
                        if (waitBleDialog.isShowing()) {
                            waitBleDialog.cancel();
                        }
                        runOnUiThread(() -> {
                            Toast.makeText(BleResultActivity.this, getString(R.string.ble_crc_error), Toast.LENGTH_SHORT).show();
                            finish();
                        });
                    }


                    @Override
                    public void onComplete() {
                        if (recordList.size() == 0) {
                            if (waitBleDialog.isShowing()) {
                                waitBleDialog.cancel();
                            }
                            runOnUiThread(() -> Toast.makeText(BleResultActivity.this, getString(R.string.edit_no_new_record), Toast.LENGTH_SHORT).show());
                            recordTestButton.setOnClickListener(v -> runOnUiThread(() -> Toast.makeText(BleResultActivity.this, getString(R.string.edit_no_new_record), Toast.LENGTH_SHORT).show()));
                        } else {
                            runOnUiThread(() -> {
                                recordTestButton.setEnabled(true);
                                Toast.makeText(BleResultActivity.this, getString(R.string.edit_transmit_finish), Toast.LENGTH_SHORT).show();
                            });
                            recordTestButton.setOnClickListener(recordTest);
                        }
                    }


                    @Override
                    public void onReadMeterIdError() {
                        boolean haveCommendNotUsed = true;
                        for (String command : meterIdUsed.keySet()) {
                            Boolean commandUsed = meterIdUsed.get(command);
                            if (null == commandUsed) {
                                commandUsed = false;
                            }
                            if (!commandUsed) {
                                haveCommendNotUsed = true;
                                bleService.sendDataToBle(command);
                                meterIdUsed.put(command, true);
                                break;
                            } else {
                                haveCommendNotUsed = false;
                            }
                        }
                        if (!haveCommendNotUsed) {
                            waitBleDialog.cancel();
                            runOnUiThread(() -> Toast.makeText(BleResultActivity.this, getString(R.string.edit_read_meter_id_failed), Toast.LENGTH_SHORT).show());
                            finish();
                        }
                    }
                });
                if (!isConn) {
                    Log.d(TAG, "onServiceConnected: false");
                }
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                bleService = null;
            }
        };
        final Intent intent = new Intent(this, BleService.class);
        bindService(intent, serviceConnection, Service.BIND_AUTO_CREATE);
    }

我现在所知道的是,运行enableNotification()方法并且writeDescriptor()返回true之后,发生了onConnectionUpdated()并失去了连接。 onConnectionUpdated()隐藏在源代码中,我不知道为什么会发生以及如何处理。

1 个答案:

答案 0 :(得分:0)

您的应用似乎未连接到BLE设备。

要知道连接是否成功,您需要检查给定的status等于BluetoothGatt.GATT_SUCCESS中的onConnectionStateChange()

另外,检查是否可能有GATT_CONN_TIMEOUT:

@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

     super.onConnectionStateChange(gatt, status, newState);

     if ((newState == BluetoothProfile.STATE_CONNECTED) && (status == BluetoothGatt.GATT_SUCCESS)) {
           bluetoothGatt.discoverServices();
     } else if ((newState == BluetoothProfile.STATE_DISCONNECTED) && (status == BluetoothGatt.GATT_SUCCESS)) {
           gatt.close();
           Log.d(TAG, "onConnectionStateChange: DISCONNECTED");
     } else if (status == GATT_CONN_TIMEOUT) {
           Log.e(TAG, "GATT_CONN_TIMEOUT !");  
     } else {
           Log.e(TAG, "onConnectionStateChange: FAIL");
     }
}