Android <-> iOS蓝牙LE应用程序,无法写入特征

时间:2018-07-24 06:31:29

标签: bluetooth-lowenergy core-bluetooth android-bluetooth ios-bluetooth

我正在为Unity开发一个基于ble的本机本地多人插件(适用于Android和iOS)。我使用单一服务,具有具有rw权限的单一特征。我设法使Android <-> Android和iOS <-> iOS正常工作,但是我在使Android <-> iOS正常工作方面遇到了困难。特别是,“ iOS作为外围设备,Android作为中央系统”的组合使我无法入睡。经过数小时的摆弄,测试,谷歌搜索和尝试,我将问题归结为:

从Android方面来看,如果我不订阅该特征,则调用 BluetoothGatt#writeCharacteristic(characteristic),如下所示:

String str = "the data";

xferCharacteristic.setValue(str.getBytes("UTF-8"));
mGatt.writeCharacteristic(xferCharacteristic);

将返回'true'并成功,并且 peripheralManager:didReceiveWriteRequests:回调将在iOS端调用,在这里我可以根据需要操纵珍贵的接收数据。到目前为止,一切都很好。但是,如果我尝试从iOS端更新特性,则不会通知Android中心(应该调用回调 BluetoothGattCallback#onCharacteristicChanged ,但不是),因为它没有订阅该特征。

如果我通过以下代码段使Android中央系统订阅iOS外围设备提供的功能,则:

首先,使用

连接到iOS外设
public void onScanResult(int callbackType, ScanResult result) {

        BluetoothDevice btDevice = result.getDevice();
        mGatt = device.connectGatt(appContext, false, mGattCallback);
        ...
mGattCallback 一起 BLEGattCallback 的实例,该实例将处理 onServicesDiscovered 回调:

public class BLEGattCallback extends BluetoothGattCallback {

private static final UUID CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");

public void onServicesDiscovered(BluetoothGatt gatt, int status) {

    List<BluetoothGattService> services = gatt.getServices();

    for(BluetoothGattService s : services) { // foreach service...

        if(UUID.fromString(MyServiceUUID).equals(s.getUuid())) { // just the one I want...

            List<BluetoothGattCharacteristic> characteristics = s.getCharacteristics();
            for(BluetoothGattCharacteristic c : characteristics) { // foreach characteristic...

                if(c.getUuid().toString().equals(BLEManager.FGUUIDXferQueueString)) { // just the char. I want...

                    c.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);

                    for (BluetoothGattDescriptor descriptor : c.getDescriptors()) {

                        if(descriptor.getUuid().equals(CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID)) {

                            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                            gatt.writeDescriptor(descriptor);

                        }

                    }

                    gatt.setCharacteristicNotification(c, true);

                }
            }
        }
    }
}

这使Android中央系统正确地订阅了特征(在iOS外围设备上调用了回调方法 peripheralManager:central:didSubscribeToCharacteristic:),但如果我这样做,则对 mGatt.writeCharacteristic(xferCharacteristic)将返回“ false”,并且不会将任何数据写入外围设备,因此这是一种只能写入或只能通知更新的情况。

我没有设法找出writeCharacteristic返回“ false”的含义,但没有成功(严重的是,错误代码会很有帮助)。

我已经尝试了许多不同的组合,值等...但是,最重要的是:我调用 gatt.writeDescriptor 随后调用了 writeCharacteristic 将失败,并且如果我不致电 gatt.writeDescriptor ,则android Central将不会订阅。

我几乎被困在这里。任何帮助表示赞赏。非常感谢。

2 个答案:

答案 0 :(得分:1)

经典问题。您必须等待操作完成才能发出另一操作。参见Android BLE BluetoothGatt.writeDescriptor() return sometimes false

答案 1 :(得分:0)

由于收到提示,此问题已解决。这些是我对代码所做的更改:

在发出writeCharacteristic(...)命令之前,Android客户端必须等待writeDescriptor(...)请求完成。为此,我必须在BLEGattCallback类上@Override onDescriptorWrite方法,该方法将在writeDescriptor操作完成时调用。我在这里移动了我的第一个writeCharacteristic(...)调用,现在信息被发送到iOS端点(其余必须由流控制)。所以我很高兴。