从 BluetoothGattCharacteristic 读取失败

Reading from a BluetoothGattCharacteristic is failing

我正在尝试读取存储在 BluetoothGattCharacteristic 中的值。以下是我的 BluetoothGattCallback 代码,其中发生了大部分操作:

 private final BluetoothGattCallback mGattCallback =
            new BluetoothGattCallback() {
                @Override
                public void onConnectionStateChange(BluetoothGatt gatt, int status,
                                                    int newState) {
                    if (newState == BluetoothProfile.STATE_CONNECTED) {
                        Log.i(TAG, "Connected to GATT server.");
                        Log.i(TAG, "Getting services....");
                        gatt.discoverServices();
                    } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                        Log.i(TAG, "Disconnected from GATT server.");
                    }
                }

                @Override
                public void onServicesDiscovered(BluetoothGatt gatt, int status) {
                    if (status == BluetoothGatt.GATT_SUCCESS) {
                        BluetoothGattService serv = gatt.getService(Constants.MY_UUID);
                        if (serv != null) {
                            BluetoothGattCharacteristic characteristic = serv.getCharacteristic(Constants.ANOTHER_UUID);
                            boolean res = gatt.readCharacteristic(characteristic);
                            if (res) {
                                Log.d(TAG, "res was true");
                            } else {
                                Log.d(TAG, "res was false");
                            }
                        }
                    } else {
                        Log.w(TAG, "onServicesDiscovered received: " + status);
                    }
                }

                @Override
                public void onCharacteristicRead(BluetoothGatt gatt,
                                                 BluetoothGattCharacteristic characteristic,
                                                 int status) {
                    if (status == BluetoothGatt.GATT_SUCCESS) {
                        Log.d(TAG, "Succesfully read characteristic: " + characteristic.getValue().toString());
                    } else {
                        Log.d(TAG, "Characteristic read not successful");
                    }
                }
            };

因此,为了从特征中读取,我正在尝试使用 gatt.readCharacteristic() 方法,该方法采用特征和 returns 指示操作成功与否的布尔值。此处,此方法返回 false(打印 "res was false"),表明它失败了。

没有正在打印的错误消息。读取特征的正确方法是什么?为什么这个方法会返回 false?

编辑: 按照 Inferno 的建议,继续下载所需的源,然后在 BluetoothGatt readCharacteristic() 方法中设置断点:

这里是android-23..\BluetoothGatt

中的readCharacteristic()方法
public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) {
        if ((characteristic.getProperties() &
                BluetoothGattCharacteristic.PROPERTY_READ) == 0) return false;

(characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_READ) 返回 0,因此 false 立即返回。现在根据调试器 characteristic.getProperties() 返回值 8,而 BluetoothGattCharacteristic.PROPERTY_READ 有一个静态 int 值 0x02

据我了解,0x08 & 0x02 == 0。由于 PROPERTY_READ 是一个硬编码值,我假设从 characteristic.getProperties() 返回的值有问题。这里可能出了什么问题?

What is the proper way to read a characteristic?

首先,您从 onServicesDiscovered() 回调内部调用 gatt.readCharacteristic(characteristic),这没问题。我看不出你的代码有任何严重的缺陷。

您可以在 onConnectionStateChange() 中添加的是 在您验证 newState == BluetoothProfile.STATE_CONNECTED:

之前 的额外检查
if (status == BluetoothGatt.GATT_SUCCESS) { ...

Why would this method be returning false?

我检查了 BluetoothGatt here 的 android 来源,结果 false 的 return 值是 returned在许多不同的情况下,您可以在下面的代码中看到:

public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) {
    if ((characteristic.getProperties() &
            BluetoothGattCharacteristic.PROPERTY_READ) == 0) return false;

    if (VDBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid());
    if (mService == null || mClientIf == 0) return false;

    BluetoothGattService service = characteristic.getService();
    if (service == null) return false;

    BluetoothDevice device = service.getDevice();
    if (device == null) return false;

    synchronized(mDeviceBusy) {
        if (mDeviceBusy) return false;
        mDeviceBusy = true;
    }

    try {
        mService.readCharacteristic(mClientIf, device.getAddress(),
            characteristic.getInstanceId(), AUTHENTICATION_NONE);
    } catch (RemoteException e) {
        Log.e(TAG,"",e);
        mDeviceBusy = false;
        return false;
    }

    return true;
}

所以我建议你做的是,在 Android Studio 中启动调试器并在 readCharacteristic() 方法(在 BluetoothGatt.java 中)和 中设置一个断点仔细 单步执行代码以查看 false 在哪里得到 returned。这样您就有望定位问题。除此之外,其他任何事情都是胡乱猜测。

当然,您需要下载资源才能查看 BluetoothGatt.java。但是 Android Studio 会在编辑器的顶部给你一个黄色的小条,询问你是否要下载和安装。下载完成后重启Android Studio就可以了。然后你应该可以在 BluetoothGatt.java.

中设置断点

更新:

As I understand, 0x08 & 0x02 == 0. Since the PROPERTY_READ is a hardcoded value, I assume something is wrong with the value returned from characteristic.getProperties(). What could be going wrong here?

根据蓝牙规范版本 4.2 [第 3 卷,G 部分] 第 533 页,0x8 的值由 characteristic.getProperties() return 表示,您的特性具有 只写权限。所有阅读尝试都失败也就不足为奇了。换句话说:您的蓝牙设备不允许您读取该特定特征。

引用自规范:

The Characteristic Properties bit field determines how the Characteristic Value can be used, or how the characteristic descriptors (see Section 3.3.3) can be accessed.

我正在尝试从带有 BLE 芯片的牛刷抓取器中读取数据。 它处于 BLE 模块的读取特性之下。 数据以十六进制形式返回,即 BRUSH_OFF 的 0x00 和 BRUSH_ON

的 0x01

我试图在我的 android 应用程序中读取这些数据,但它总是返回空白。

问题是 0x00 = NUll in ascii 和 0x01 = SOH ascii 无法在屏幕上显示。

0x30 = ascii 0x31 = ascii 1

可能您的转义字符以十六进制返回,但无法读取。

我花了几个月的时间试图找出为什么我无法读回这些值。 希望这对你有帮助。