Android新旧BLE扫描API返回不同广播数据问题求助
新旧BLE扫描API返回广播数据不一致的原因及解决办法
核心差异原因
系统对广播数据的处理逻辑不同
旧APIBluetoothAdapter.startLeScan()直接返回BLE设备发送的原始广播字节数组,不会对数据做任何过滤或重组。而新APIBluetoothLeScanner.startScan()返回的ScanResult.bytes是经过Android系统处理后的结果:系统会识别标准化的广播结构(比如iBeacon),并返回重组后的标准化数据,而非原始自定义广播包。从你提供的十六进制数据就能看出:
- 旧API数据包含厂商自定义AD段(
ff030dff...,厂商ID为030d) - 新API数据是标准iBeacon结构(
ff4c000215...,厂商ID4c00是苹果官方ID)
这说明你的BLE设备同时发送了自定义广播帧和iBeacon帧,旧API捕获到自定义帧,新API默认返回了系统识别的iBeacon帧。
- 旧API数据包含厂商自定义AD段(
默认扫描过滤规则的影响
新API默认会优先返回符合蓝牙标准规范的广播数据(比如iBeacon、标准服务UUID等),如果没有指定扫描过滤器,系统可能会过滤掉非标准的自定义广播帧,或者只返回优先级更高的广播包。广播分段的处理差异
BLE单包广播最大长度为31字节,若设备广播数据超长会拆分多包发送。旧API可能自动合并分段数据返回,而新API可能仅返回其中一个分段,导致数据不完整。
解决办法
1. 针对性设置扫描过滤器
创建匹配你自定义广播的ScanFilter,让系统只返回你需要的广播帧:
// 匹配厂商ID为0x030d的自定义广播 val filter = ScanFilter.Builder() .setManufacturerData(0x030d, null, null) // 只过滤厂商ID,不限制数据内容 .build() // 启动扫描时传入过滤器 bluetoothAdapter.bluetoothLeScanner.startScan(listOf(filter), ScanSettings.Builder().build(), scanCallback)
2. 从ScanRecord中提取原始自定义数据
即使ScanResult.bytes返回的是标准化数据,你也可以通过ScanRecord直接提取厂商自定义数据:
override fun onScanResult(callbackType: Int, result: ScanResult) { val scanRecord = result.scanRecord ?: return // 获取厂商ID为0x030d的自定义数据 val customData = scanRecord.getManufacturerSpecificData(0x030d) customData?.let { val hexStr = it.toHex() // 这里得到的就是你预期的自定义广播数据 } }
3. 调整ScanSettings参数
如果需要获取所有广播帧,可以关闭系统的过滤逻辑:
val settings = ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) .build() bluetoothAdapter.bluetoothLeScanner.startScan(null, settings, scanCallback)
注意:这种方式会接收所有广播数据,需要自己在回调中筛选目标设备。
内容的提问来源于stack exchange,提问作者Chris Wagner
相关产品推荐
相关产品推荐

