0

我们使用的是具有显着特征的 ble 设备,我们使用 EnableNotification 通过回调获取数据。我们实现了一个命令队列,我们​​达到了不再发出任何命令的状态,我们只听特征通知。

随机一段时间后,我们遇到蓝牙服务/适配器死机的错误,在 logcat 中我们发现了 DeadObjectException。这是一个很难复制和跟踪的错误,但它对我们的应用程序至关重要。在回调中,我们尝试处理所有可能的异常(在每个类方法中),但无法处理 DeadObjectException,它似乎是在另一个进程中抛出的。

我们使用的设备每次触发发送2个字节的数据,每秒可以发送大约20个包。

我们没有任何运气找到这方面的帮助。有人可以给我们一些建议吗?有什么方法可以捕获蓝牙绑定器或服务引发的异常?处理显着特征的正确方法是什么?

这是 logcat 输出:

    2022-02-22 13:16:50.125 5423-5910/? I/bt_stack: [INFO:gatt_main.cc(919)] gatt_data_process op_code = 27, msg_len = 4
2022-02-22 13:16:50.125 5423-5910/? E/bt_btif: bta_gattc_process_indicate, ignore HID ind/notificiation
2022-02-22 13:16:50.125 5423-5541/? E/JavaBinder: !!! FAILED BINDER TRANSACTION !!!  (parcel size = 152)
2022-02-22 13:16:50.126 5423-5541/? E/BtGatt.JNI: An exception was thrown by callback 'btgattc_notify_cb'.
2022-02-22 13:16:50.143 5423-5910/? I/bt_stack: [INFO:gatt_main.cc(919)] gatt_data_process op_code = 27, msg_len = 4
2022-02-22 13:16:50.143 5423-5910/? E/bt_btif: bta_gattc_process_indicate, ignore HID ind/notificiation
2022-02-22 13:16:50.171 17518-8879/---.---.--- I/SMNPlugin: Android [Main.cpp:763:_setStatePieceDetected()]     [Piece State Detection] PIECE_NO_CORRECT.
2022-02-22 13:16:50.180 5423-5541/? E/BtGatt.JNI: android.os.DeadObjectException: Transaction failed on small parcel; remote process probably died
        at android.os.BinderProxy.transactNative(Native Method)
        at android.os.BinderProxy.transact(BinderProxy.java:550)
        at android.bluetooth.IBluetoothGattCallback$Stub$Proxy.onNotify(IBluetoothGattCallback.java:561)
        at com.android.bluetooth.gatt.GattService.onNotify(GattService.java:1530)
2022-02-22 13:16:50.180 5423-5541/? E/JavaBinder: !!! FAILED BINDER TRANSACTION !!!  (parcel size = 152)
2022-02-22 13:16:50.180 5423-5541/? E/BtGatt.JNI: An exception was thrown by callback 'btgattc_notify_cb'.
2022-02-22 13:16:50.181 5423-5541/? E/BtGatt.JNI: android.os.DeadObjectException: Transaction failed on small parcel; remote process probably died
        at android.os.BinderProxy.transactNative(Native Method)
        at android.os.BinderProxy.transact(BinderProxy.java:550)
        at android.bluetooth.IBluetoothGattCallback$Stub$Proxy.onNotify(IBluetoothGattCallback.java:561)
        at com.android.bluetooth.gatt.GattService.onNotify(GattService.java:1530)

这是我们的回调示例:

public BluetoothDeviceInterface(final BluetoothDevice device, final int arrayIndex) {
    _device = device;
    _internalArrayIndex = arrayIndex;
    _gatt = null;

    _gattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            Log.i(LOGTAG, "On Connection State Change. Status: " + status + ". New state: " + newState);
            try {
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    if (newState == BluetoothProfile.STATE_CONNECTED) {
                        Log.i(LOGTAG, "Connected to device: " + GetAddress());
                        _gatt = gatt;
                        _gatt.discoverServices();
                    } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                        Log.i(LOGTAG, "Disconnected from device: " + GetAddress());
                        _gatt.close();
                        _gatt = null;
                    }
                } else {
                    Log.i(LOGTAG, "Error connecting GATT.");
                    _gatt.close();
                    _gatt = null;
                }
                _callback.OnStateChanged(status, newState);
            } catch (Exception e) {
                Log.e(LOGTAG, "Exception in onConnectionStateChange: " + e.toString());
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            Log.i(LOGTAG, "On Services Discovered. Status: " + status);

            try {
                Log.i(LOGTAG, "Services of device " + GetAddress() + " discovered. Total number of: " + gatt.getServices().size());
                _callback.CleanServices();

                for(BluetoothGattService service : gatt.getServices()) {
                    String serviceUUID = service.getUuid().toString();

                    _callback.AddNewService(service.getType(), serviceUUID);

                    for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
                        String characteristicUUID = characteristic.getUuid().toString();
                        int characteristicProperties = characteristic.getProperties();
                        boolean isReadable = (characteristicProperties & BluetoothGattCharacteristic.PROPERTY_READ) != 0;
                        boolean isWritable = (characteristicProperties & BluetoothGattCharacteristic.PROPERTY_WRITE) != 0;
                        boolean isWritableWithoutResponse = (characteristicProperties & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) != 0;
                        boolean isIndicateable = (characteristicProperties & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0;
                        boolean isNotifiable = (characteristicProperties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0;

                        _callback.AddNewCharacteristic(serviceUUID, characteristicUUID, isReadable, isWritable,
                                isWritableWithoutResponse, isIndicateable, isNotifiable);
                    }
                }

                _callback.OnServiceDiscoveryEnd();
            } catch (Exception e) {
                Log.e(LOGTAG, "Exception in onServicesDiscovered: " + e.toString());
            }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            Log.i(LOGTAG, "On Characteristic Read. Status: " + status);

            try {
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    _callback.OnCharacteristicRead(characteristic.getService().getUuid().toString(), characteristic.getUuid().toString(), characteristic.getValue());
                } else if (status == BluetoothGatt.GATT_READ_NOT_PERMITTED) {
                    _callback.OnCharacteristicReadError(characteristic.getService().getUuid().toString(), characteristic.getUuid().toString(), "Read not permitted.");
                } else {
                    _callback.OnCharacteristicReadError(characteristic.getService().getUuid().toString(), characteristic.getUuid().toString(), "Status error: " + status);
                }
            } catch (Exception e) {
                Log.e(LOGTAG, "Exception in onCharacteristicRead: " + e.toString());
            }
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            Log.i(LOGTAG, "On Characteristic Write. Status: " + status);

            try {
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    _callback.OnCharacteristicWrite(characteristic.getService().getUuid().toString(), characteristic.getUuid().toString());
                } else if (status == BluetoothGatt.GATT_WRITE_NOT_PERMITTED) {
                    _callback.OnCharacteristicWriteError(characteristic.getService().getUuid().toString(), characteristic.getUuid().toString(), "Write not permitted.");
                } else {
                    _callback.OnCharacteristicWriteError(characteristic.getService().getUuid().toString(), characteristic.getUuid().toString(), "Status error: " + status);
                }
            } catch (Exception e) {
                Log.e(LOGTAG, "Exception in onCharacteristicWrite: " + e.toString());
            }
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            Log.i(LOGTAG, "On Descriptor Write. Status: " + status);

            try {
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    _callback.OnDescriptorWrite(descriptor.getCharacteristic().getService().getUuid().toString(), descriptor.getCharacteristic().getUuid().toString());
                } else if (status == BluetoothGatt.GATT_WRITE_NOT_PERMITTED) {
                    _callback.OnDescriptorWriteError(descriptor.getCharacteristic().getService().getUuid().toString(), descriptor.getCharacteristic().getUuid().toString(), "Write not permitted.");
                } else {
                    _callback.OnDescriptorWriteError(descriptor.getCharacteristic().getService().getUuid().toString(), descriptor.getCharacteristic().getUuid().toString(), "Status error: " + status);
                }
            } catch (Exception e) {
                Log.e(LOGTAG, "Exception in onDescriptorWrite: " + e.toString());
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            Log.i(LOGTAG, "On Characteristic Changed.");

            try {
                Log.i(LOGTAG, characteristic.getService().getUuid().toString() + characteristic.getUuid().toString() + characteristic.getValue().toString());
                _callback.OnCharacteristicChange(characteristic.getService().getUuid().toString(), characteristic.getUuid().toString(), characteristic.getValue());
            } catch (Exception e) {
                Log.e(LOGTAG, "Exception in onCharacteristicChanged: " + e.toString());
            }
        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
            Log.i(LOGTAG, "On Read Remote Rssi. Status: " + status + ". Rssi: " + rssi);


            try {
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    _callback.OnRssiRead(rssi);
                } else {
                    _callback.OnRssiRead(-1);
                }
            } catch (Exception e) {
                Log.e(LOGTAG, "Exception in onReadRemoteRssi: " + e.toString());
            }
        }
    };

使用空回调它仍然失败:

public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
    Log.i(LOGTAG, "On Characteristic Changed: " + characteristic.getStringValue(0));
}

这是我们用于启用通知的代码:

public boolean EnableNotifications(String serviceUUID, String characteristicUUID) {
    if (!IsConnected())
        return false;

    BluetoothGattService service = _gatt.getService(UUID.fromString(serviceUUID));
    if (service == null)
        return false;

    BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(characteristicUUID));
    if (characteristic == null)
        return false;

    int properties = characteristic.getProperties();
    byte[] payload;

    if ((properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0) {
        payload = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;
    } else if ((properties & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0) {
        payload = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE;
    } else {
        return false;
    }

    BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIGURATION_UUID);
    if (descriptor == null)
        return false;

    if (!_gatt.setCharacteristicNotification(characteristic, true))
        return false;

    descriptor.setValue(payload);
    return _gatt.writeDescriptor(descriptor);
}
4

0 回答 0