You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android新旧BLE扫描API返回不同广播数据问题求助

新旧BLE扫描API返回广播数据不一致的原因及解决办法

核心差异原因

  1. 系统对广播数据的处理逻辑不同
    旧API BluetoothAdapter.startLeScan() 直接返回BLE设备发送的原始广播字节数组,不会对数据做任何过滤或重组。而新API BluetoothLeScanner.startScan() 返回的 ScanResult.bytes 是经过Android系统处理后的结果:系统会识别标准化的广播结构(比如iBeacon),并返回重组后的标准化数据,而非原始自定义广播包。

    从你提供的十六进制数据就能看出:

    • 旧API数据包含厂商自定义AD段(ff030dff...,厂商ID为030d)
    • 新API数据是标准iBeacon结构(ff4c000215...,厂商ID4c00是苹果官方ID)
      这说明你的BLE设备同时发送了自定义广播帧和iBeacon帧,旧API捕获到自定义帧,新API默认返回了系统识别的iBeacon帧。
  2. 默认扫描过滤规则的影响
    新API默认会优先返回符合蓝牙标准规范的广播数据(比如iBeacon、标准服务UUID等),如果没有指定扫描过滤器,系统可能会过滤掉非标准的自定义广播帧,或者只返回优先级更高的广播包。

  3. 广播分段的处理差异
    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 12:15:56