android - 从 BluetoothGattCharacteristic 读取失败

标签 android bluetooth-lowenergy android-bluetooth android-ble

我正在尝试读取存储在 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() 方法,该方法采用特征并返回一个 bool 值,指示操作是否成功。在这里,此方法返回 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 的 android 源 here事实证明,false 的返回值在许多不同的情况下都会返回,如下面的代码所示:

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 中)和 < em>仔细 逐步检查代码以查看返回false 的位置。这样您就有望定位问题。除此之外,其他任何事情都是胡乱猜测。

当然,您需要下载源代码才能查看 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 页,characteristic.getProperties() 返回的 0x8 的值意味着,您的特性具有只写 权限。所有阅读尝试都失败也就不足为奇了。换句话说:您的蓝牙设备不允许您读取该特定特征。

引用自规范:

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.

关于android - 从 BluetoothGattCharacteristic 读取失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39736475/

相关文章:

android - 每次检测到信标信号时自动启动应用程序信标

Android 蓝牙设备类型 DUAL

java - 蓝牙 socket 未连接,无法配对设备

java - getGlobalVisibleRect 当前可见屏幕

ios - Ble广告数据慢间隔时间

android - 音频无法在APK中运行

Android 7.0 ble扫描无结果

arduino - HM10 ble改变特征值AT命令Arduino

android - 为什么在停止录制音频时会出现 IllegalStateException?

android - 是否可以通过 firebase auth 仅使用短信服务和离线注册用户,即没有互联网