我正在为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将不会订阅。
我几乎被困在这里。任何帮助表示赞赏。非常感谢。
答案 0 :(得分:1)
经典问题。您必须等待操作完成才能发出另一操作。参见Android BLE BluetoothGatt.writeDescriptor() return sometimes false。
答案 1 :(得分:0)
由于收到提示,此问题已解决。这些是我对代码所做的更改:
在发出writeCharacteristic(...)命令之前,Android客户端必须等待writeDescriptor(...)请求完成。为此,我必须在BLEGattCallback类上@Override onDescriptorWrite方法,该方法将在writeDescriptor操作完成时调用。我在这里移动了我的第一个writeCharacteristic(...)调用,现在信息被发送到iOS端点(其余必须由流控制)。所以我很高兴。