自2013年/ API18 / 4.3以来,我一直在Android上做BLE 我知道我在做什么,但我无法弄清楚这个简单的问题。
我正在成功扫描BLE设备,并且在ScanCallback.onScanResult(...)中我记录了ScanRecord.getServiceUuids()(这里看到的是带有制造商特定数据的列索引标题):
01-19 18:04:57.633 10363-10442/com.foo E/MyBleScanner: T10442 parse: 0E:0E:00:00:00:57: 00-00-00-00-00-00-00-00-00-00-01-01-01-01
01-19 18:04:57.633 10363-10442/com.foo E/MyBleScanner: T10442 parse: 0E:0E:00:00:00:57: 00-01-02-03-04-05-06-07-08-09-00-01-02-03
01-19 18:04:57.633 10363-10442/com.foo E/MyBleScanner: T10442 parse: 0E:0E:00:00:00:57: manufacturerSpecificDataBytes[manufacturerId=0x0E0E](14)=[00-00-00-57-D6-40-00-1D-1F-00-F6-0A-BC-05]
01-19 18:04:57.634 10363-10442/com.foo E/MyBleScanner: T10442 parse: 0E:0E:00:00:00:57: serviceUuids=[0000fa25-0000-1000-8000-00805f9b34fb]
01-19 18:04:57.634 10363-10442/com.foo E/MyBleScanner: T10442 parse: 0E:0E:00:00:00:57: elapsedSinceLastScanTimeMillis=9
此扫描记录是一致的,并且可靠地显示已扫描的设备0E:0E:00:00:00:57具有serviceUuids = [0000fa25-0000-1000-8000-00805f9b34fb]。
扫描设备0E后不久:0E:00:00:00:57我使用BluetoothGatt连接到它并为0000fa25-0000-1000-8000-00805f9b34fb服务写一个特征。
这是我的GattHandler类的完整日志(我将很快有一天开源):
01-19 18:04:57.118 10363-10363/com.foo I/GattHandler: T10363 0E:0E:00:00:00:57 connect(autoConnect=false, timeoutMillis=10000)
01-19 18:04:57.119 10363-10451/com.foo V/GattHandler: T10451 0E:0E:00:00:00:57 +connect.run(): autoConnect=false, timeoutMillis=10000
01-19 18:04:57.120 10363-10451/com.foo V/GattHandler: T10451 0E:0E:00:00:00:57 connect.run: +bluetoothDevice.connectGatt(...)
01-19 18:04:57.128 10363-10451/com.foo V/GattHandler: T10451 0E:0E:00:00:00:57 connect.run: -bluetoothDevice.connectGatt(...) returned android.bluetooth.BluetoothGatt@ea75169
01-19 18:04:57.129 10363-10451/com.foo V/GattHandler: T10451 0E:0E:00:00:00:57 pendingOperationWait: operation=Connect, timeoutMillis=10000
01-19 18:04:58.108 10363-10376/com.foo V/GattHandler: T10376 0E:0E:00:00:00:57 onConnectionStateChange(gatt, status=0, newState=STATE_CONNECTED(2))
01-19 18:04:58.112 10363-10376/com.foo I/GattHandler: T10376 0E:0E:00:00:00:57 onConnectionStateChange: disconnect=false
01-19 18:04:58.122 10363-10375/com.foo V/GattHandler: T10375 0E:0E:00:00:00:57 onServicesDiscovered(gatt, status=0)
...在onServicesDiscovered中,我调用gatt.getServices()并将其报告回一个侦听器,MyBleDevice,它记录所有服务...
01-19 18:04:58.127 10363-10363/com.foo V/MyBleDevice: T10363 0E:0E:00:00:00:57 onServiceDiscovered(service="Generic Attribute Service"(0x1801))
... 请注意,在连接的设备上只报告发现了一项服务!
这是一台报告在扫描时有服务0000fa25-0000-1000-8000-00805f9b34fb的设备。
01-19 18:04:58.124 10363-10451/com.foo V/GattHandler: T10451 0E:0E:00:00:00:57 pendingOperationWait: operation=Connect, elapsedMillis=1004
01-19 18:04:58.124 10363-10451/com.foo V/GattHandler: T10451 0E:0E:00:00:00:57 pendingOperationWait: operation=Connect, elapsedMillis=1004; SIGNALED/COMPLETED
01-19 18:04:58.124 10363-10451/com.foo V/GattHandler: T10451 0E:0E:00:00:00:57 -connect.run(): autoConnect=false, timeoutMillis=10000
01-19 18:05:05.940 10363-10363/com.foo I/GattHandler: T10363 0E:0E:00:00:00:57 characteristicWrite(serviceUuid=0000fa25-0000-1000-8000-00805f9b34fb, characteristicUuid=00002c02-0000-1000-8000-00805f9b34fb, value=[1], characteristicWriteType=DefaultWithResponse, timeoutMillis=10000)
01-19 18:05:05.943 10363-10451/com.foo V/GattHandler: T10451 0E:0E:00:00:00:57 +characteristicWrite.run(): serviceUuid=0000fa25-0000-1000-8000-00805f9b34fb, characteristicUuid=00002c02-0000-1000-8000-00805f9b34fb, value=[1], characteristicWriteType=DefaultWithResponse, timeoutMillis=10000
01-19 18:05:05.944 10363-10451/com.foo E/GattHandler: T10451 0E:0E:00:00:00:57 characteristicWrite: gatt.getService(0000fa25-0000-1000-8000-00805f9b34fb) returned null; failing
01-19 18:05:05.964 10363-10451/com.foo V/GattHandler: T10451 0E:0E:00:00:00:57 -characteristicWrite.run(): serviceUuid=0000fa25-0000-1000-8000-00805f9b34fb, characteristicUuid=00002c02-0000-1000-8000-00805f9b34fb, value=[1], characteristicWriteType=DefaultWithResponse, timeoutMillis=10000
注意“getService(...)返回null;失败”。
这是在运行最新版本的Pixel XL上发布的Android 7.1 BLE设备是一种可在非Android BLE设备上正常工作的自定义设备 请注意,这在大多数情况下都有效,但还不足以舒适地运送产品。
任何想法WTH都会在这里发生?
以下是我的GattHandler.characteristicWrite(...)的代码:
public void characteristicWrite(final UUID serviceUuid, final UUID characteristicUuid,
final byte[] value,
final CharacteristicWriteType characteristicWriteType,
final long timeoutMillis)
{
Log.i(TAG, mDeviceAddressString +
" characteristicWrite(serviceUuid=" + serviceUuid +
", characteristicUuid=" + characteristicUuid +
", value=" + Arrays.toString(value) +
", characteristicWriteType=" + characteristicWriteType +
", timeoutMillis=" + timeoutMillis + ')');
if (serviceUuid == null)
{
throw new IllegalArgumentException("serviceUuid must not be null");
}
if (characteristicUuid == null)
{
throw new IllegalArgumentException("characteristicUuid must not be null");
}
if (value == null)
{
throw new IllegalArgumentException("value must not be null");
}
if (!connectIfDisconnected("characteristicWrite", timeoutMillis))
{
return;
}
final GattOperation operation = GattOperation.CharacteristicWrite;
final long startTimeMillis = timerStart(operation);
mHandlerBackground.post(new Runnable()
{
public void run()
{
try
{
Log.v(TAG, mDeviceAddressString +
" +characteristicWrite.run(): serviceUuid=" + serviceUuid +
", characteristicUuid=" + characteristicUuid +
", value=" + Arrays.toString(value) +
", characteristicWriteType=" + characteristicWriteType +
", timeoutMillis=" + timeoutMillis);
BluetoothGatt gatt = pendingOperationWaitReset("characteristicWrite", startTimeMillis);
if (gatt == null)
{
onDeviceCharacteristicWrite(serviceUuid, characteristicUuid, false);
return;
}
BluetoothGattService service = gatt.getService(serviceUuid);
if (service == null)
{
Log.e(TAG, mDeviceAddressString +
" characteristicWrite: gatt.getService(" + serviceUuid + ") returned null; failing");
onDeviceCharacteristicWrite(serviceUuid, characteristicUuid, false);
return;
}
BluetoothGattCharacteristic characteristic = service.getCharacteristic(characteristicUuid);
if (characteristic == null)
{
Log.e(TAG, mDeviceAddressString +
" characteristicWrite: service.getCharacteristic(" + characteristicUuid +
") failed");
onDeviceCharacteristicWrite(serviceUuid, characteristicUuid, false);
return;
}
if (characteristicWriteType != null)
{
int writeType;
switch (characteristicWriteType)
{
case WithoutResponse:
writeType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE;
break;
case Signed:
writeType = BluetoothGattCharacteristic.WRITE_TYPE_SIGNED;
break;
case DefaultWithResponse:
default:
writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT;
break;
}
characteristic.setWriteType(writeType);
}
if (!characteristic.setValue(value))
{
Log.e(TAG, mDeviceAddressString +
" characteristicWrite: characteristic.setValue(" + Arrays.toString(value) +
" failed for characteristic " + characteristicUuid);
onDeviceCharacteristicWrite(serviceUuid, characteristicUuid, false);
return;
}
if (!gatt.writeCharacteristic(characteristic))
{
Log.e(TAG, mDeviceAddressString +
" characteristicWrite: gatt.characteristicWrite(...) failed for characteristic " +
characteristicUuid);
onDeviceCharacteristicWrite(serviceUuid, characteristicUuid, false);
return;
}
pendingOperationWait(operation, timeoutMillis);
}
finally
{
Log.v(TAG, mDeviceAddressString +
" -characteristicWrite.run(): serviceUuid=" + serviceUuid +
", characteristicUuid=" + characteristicUuid +
", value=" + Arrays.toString(value) +
", characteristicWriteType=" + characteristicWriteType +
", timeoutMillis=" + timeoutMillis);
}
}
});
}