Bluetooth LE ScanResult 返回 null,但我知道我的外围设备正在广播心率服务 UUID(由第 3 方 BLE 应用程序验证)。为什么?

Bluetooth LE ScanResult is returning null, but I know my peripheral is broadcasting a heart rate Service UUID (as verified by 3rd-party BLE app). Why?

我对 BLE 扫描没有返回 GATT 服务 UUID(即 scanRecord.getServiceUUIDs() returns null)感到沮丧。但是,我知道我的心率外围设备正在正常工作和广告,因为心率服务已被 LightBlue 应用程序发现(并且可读)。 这是我的 ScanCallback 对象中的函数:

override fun onScanResult(callbackType: Int, result: ScanResult?) {
    super.onScanResult(callbackType, result)
    // This log shows that result.mServiceUuids is null
    Log.i(TAG, "BLEDeviceManager.ScanCallback.onScanResult: ${result.toString()}")

    // TODO: handle null ScanResult
    val parcelUuids = if (result.getScanRecord() != null) result.getScanRecord()!!.getServiceUuids() else null
    if (parcelUuids == null) {
        Log.i(TAG, "parcelUUids was null for scanRecord = ${result.getScanRecord()!!.toString()}")
        return
    }
    val serviceList = ArrayList<UUID>()
    for (i in parcelUuids.indices) {
        val serviceUUID = parcelUuids.get(i).getUuid()
        if (!serviceList.contains(serviceUUID))
            serviceList.add(serviceUUID)
    }
    Log.i(TAG, "Here is a list of the service UUIDs: $serviceList")
}

这是日志:

I/BLEDeviceManager: parcelUUids was null for scanRecord = ScanRecord [mAdvertiseFlags=6, mServiceUuids=null, mServiceSolicitationUuids=null, mManufacturerSpecificData={}, mServiceData={}, mTxPowerLevel=3, mDeviceName=blehr_sensor_1.0]

我做错了什么,mServiceUuids 总是空的?

根据您输出的 ScanRecord,您的设备没有发布任何服务 UUID。这并不意味着它没有该服务....它只是不做广告。

您可能想要连接到它,然后调用 discoverServices() 以获取它真正拥有的服务列表...

可能是您的设备公布了无效数据。如果是这样,Android 将 return 一个空的服务列表,即使无效数据位于不相关的字段中也是如此。

所以分析广告数据并检查它是否有你要找的UUID。一旦你明白这是怎么回事,你就可以自己解析数据了。

(以下代码是 Java 而不是 Kotlin。但是 Android Studio 应该会自动转换它。)

@Override
public void onScanResult(int callbackType, ScanResult result) {
    super.onScanResult(callbackType, result);
    ScanRecord scanRecord = result.getScanRecord();
    byte[] advertisementData = scanRecord.getBytes();
    Log.i(TAG, "advertisement data: " + bytesToHex(advertisementData));
}

private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();

public static String bytesToHex(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];
    for (int j = 0; j < bytes.length; j++) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = HEX_ARRAY[v >>> 4];
        hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
    }
    return new String(hexChars);
}