如何将Flutter Blue的ScanResult转换为Android的scanRecord字节数组?
转换思路:将Flutter Blue的Map格式广告数据转为Android风格的scanRecord字节数组
刚好处理过类似的适配场景,给你分享个可行的解决方案。BLE广播包(也就是Android里的scanRecord)本质是由多个广告段拼接而成的,每个广告段的固定格式是:
[长度(1字节), 类型(1字节), 数据(N字节)]
其中「长度」= 1(类型字节的长度) + N(数据字节的长度)
Flutter Blue返回的Map其实是把每个广告段的「类型」和「数据」拆成了键值对,我们只需要把这些键值对重新还原成标准广告段格式,再拼接起来就能得到和Android一致的scanRecord字节数组了。
具体实现步骤(Dart代码)
- 初始化一个空的字节列表,用来存放最终的转换结果
- 遍历Flutter Blue返回的Map的每一个键值对:
- 把广告类型(Map的key)转成单个字节(注意:BLE标准广告类型是0-255的uint8范围,有些版本的Flutter Blue会用256表示制造商特定数据,这时候需要映射为标准的0xFF)
- 计算当前广告段的长度:
1(类型字节) + 数据长度,转成单个字节 - 把「长度字节」「类型字节」「数据字节数组」依次加入总列表
- 最终的总列表就是可以直接传入现有解析协议的
scanRecord字节数组
代码示例
假设你从Flutter Blue拿到的广告数据是这样的:
Map<int, List<int>> flutterAdvertData = {256: [0,0,0,16,1,57,33,18,0,0,154,10,0]};
转换代码如下:
List<int> convertToAndroidScanRecord(Map<int, List<int>> flutterAdvertData) { List<int> scanRecord = []; for (var entry in flutterAdvertData.entries) { int adType = entry.key; List<int> adData = entry.value; // 适配Flutter Blue的特殊类型映射:比如256对应标准制造商数据类型0xFF if (adType == 256) { adType = 0xFF; } // 计算广告段长度,不能超过BLE的最大限制255 int segmentLength = 1 + adData.length; if (segmentLength > 0xFF) { throw Exception("广告段长度超出BLE规范限制(最大255字节)"); } // 拼接成标准广告段,加入总列表 scanRecord.add(segmentLength); scanRecord.add(adType); scanRecord.addAll(adData); } return scanRecord; }
注意事项
- 不同版本的Flutter Blue对广告类型的key定义可能有差异,比如有些版本会用字符串key(比如
manufacturerData),你需要根据实际返回的Map结构调整类型映射逻辑 - 如果你的解析协议依赖设备名称、服务UUID等其他广播字段,要确保Flutter Blue返回的Map中包含这些条目,转换时一起处理进去
- 测试时可以对比Android端抓包的
scanRecord字节数组和转换后的结果,确保格式完全一致
内容的提问来源于stack exchange,提问作者Priadarshan Mega




