Android BLE - 外设| onCharacteristicRead返回错误的值或部分值(但重复)

时间:2015-04-08 10:35:33

标签: android android-bluetooth

我对这个问题失去了理智。

事实是,一个Android设备正在宣传一个字符串值:" 78d89537-4309-4728-87f6-3ab2bbe231d8" (36个字节)。我使用了定义为

的特征
 anonIdCharacteristic = new BluetoothGattCharacteristic(TippeeBluetoothManager.UUID_READ_CHARACTERISTIC,
            BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_BROADCAST,
            BluetoothGattCharacteristic.PERMISSION_READ  );
    anonIdCharacteristic.setValue(idToAdvertise);

你可以看到我在" READ"模式,不通知。

当另一个Android设备连接并尝试读取特征时,onCharacteristicRead方法被称为,但传递的值是错误的。更具体地说是:

" 78d89537-4309-4728-87f678d89537-4309-4728-87f678d89537-4309-4728-87f6 ..." (600字节)

这是预期值的一部分,但重复。

如果我把自己放在调试"服务器端"看到发送的字节数是正确的。在调试"客户端"字节是600

我做错了什么?

提前致谢

----编辑---

我发现了更多信息。

使用新月偏移重复调用onCharacteristicReadRequest,导致"脏"缓冲现在我以这种方式回应:

if (BluetoothManager.UUID_READ_CHARACTERISTIC.equals(characteristic.getUuid())) { mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, getStoredValue()); return; }

使用偏移值。还没有工作,但它是一些东西。

我想知道是什么告诉应用程序有多长时间的响应..

2 个答案:

答案 0 :(得分:4)

好的,我知道了,所以我会留下我的回复,以帮助其他人在我的情况。

正确的解决方案是

@Override
        public void onCharacteristicReadRequest(BluetoothDevice device,
                                                int requestId,
                                                int offset,
                                                BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
            Log.i(TAG, "onCharacteristicReadRequest " + characteristic.getUuid().toString());

            byte[] fullValue = getStoredValue();

            //check
            if (offset > fullValue.length) {
                mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, new byte[]{0} );
                return;

            }


            int size = fullValue.length - offset;
            byte[] response = new byte[size];

            for (int i = offset; i < fullValue.length; i++) {
                response[i - offset] = fullValue[i];
            }



            if (MYBluetoothManager.UUID_READ_CHARACTERISTIC.equals(characteristic.getUuid())) {
                mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, response);
                return;
            }



            mGattServer.sendResponse(device,
                    requestId,
                    BluetoothGatt.GATT_FAILURE,
                    0,
                    null);
        }

    };

使用偏移重复调用回调,这很清楚。什么不清楚它我应该用一个包含从该偏移量开始的所有数据的数组作出响应。

所以我首先准备一个包含所有数据的数组。如果请求的偏移超过数据的长度,我只返回一个0字节的数组。

如果不是这样,我从回调请求的偏移量开始准备原始数组的一部分,直到我有一些信息。因此,如果数组包含很多信息,那么并不重要,在第二个,第三个回调中,我知道从哪里开始返回数据。

抱歉,如果不清楚,但启用日志记录,你会理解我的意思。

祝每个人好运

答案 1 :(得分:1)

希望你还在为这个问题做准备,因为我在网上找不到任何答案,而且不得不挖掘污垢。自己。

所以我会尝试将其分解:

假设我们在两个Android BLE设备(中央和外围设备)之间建立了连接,

  1. 当BLE中心设备发出给定特性的characterRead(...)请求时,在外围设备中调用onReadCharacteristic(...)回调,并将相关特性作为参数。 正确的方法是发出sendResponse(...)方法,将值作为要读取的中心所需的值(您作为外设想要实际回答的内容)。 因此,我认为你的方法非常正确,一切都很顺利。

  2. 给定链接的MTU大小是默认值--20个字节。(实际上是23,但对于GATT协议,我们需要3个字节) 因此,任何大于20字节的缓冲区都将被android拆分为块(碎片)。 你有几个选择:

    2.1。学习使用给定的android机制并相应地将块发送到偏移量。

    2.2。使用来自中央的requestMtu(...)API更改链接的MTU大小,以便它可以支持更大的消息。

    2.3。知道链接的MTU,并自己构建一个碎片机制(每次调用都会使偏移量保持为0)。

  3. 总而言之,android有一个你不知道的碎片机制。