当writeDescriptor接收到true时,不会触发BLE onDescriptorWrite [英] BLE onDescriptorWrite is not trigger when writeDescriptor receive true

查看:532
本文介绍了当writeDescriptor接收到true时,不会触发BLE onDescriptorWrite的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

It's my code to enable characteristic notification.

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代码,如果执行该代码,无论如何都会有一些日志.

As we can see, writeDescriptor return true, but the onDescriptorWrite() method is not trigger, and the BluetoothGatt shows the log onConnectionUpdated(). If someone could tell why my notify have no trigger. the following is my onDescriptorWrite code in BluetoothGattCallback, if the code executed, in any case there will have some logs.

@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代码如下

my BluetoothGattCallback code as follows

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是这样的接口

in this code connectCallback is a interface like this

    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发送命令

I only send command to ble when I onDescriptorWrite success(notify success)

以下是我的连接代码

    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代码,并在这样的活动中使用

I write all the ble code in Service and use it in an activity like this

 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()隐藏在源代码中,我不知道它为什么会发生以及如何处理.

What I know now is that after run the enableNotification() method and the writeDescriptor() return true, the onConnectionUpdated() happened and I lose my connection. The onConnectionUpdated() is hide in souce code, and I don't know why it occurs and how to deal with it.

推荐答案

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

It seems your app is not connected to your BLE device.

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

To know whether the connection is succesful, you need to check the given status is equal to BluetoothGatt.GATT_SUCCESS in onConnectionStateChange().

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

Also, check for possible 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");
     }
}

这篇关于当writeDescriptor接收到true时,不会触发BLE onDescriptorWrite的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆