C#开发中如何区分Android.Bluetooth.LE的扫描响应与其他BLE广播类型
Android BLE 扫描时区分广播类型与扫描响应的实现方法
Android.Bluetooth.LE.ScanResult 并非仅返回扫描响应(SCAN_RSP)类型,所有合法的BLE广播包(含普通广播、扫描响应、定向广播等)都会通过扫描回调返回,可按以下方式区分类型:
高版本直接调用公开API(API 26+,Android 8.0及以上)
Android 8.0开始系统直接暴露了广播类型获取接口,和Windows平台的args.AdvertisementType逻辑完全一致,直接调用ScanResult实例的getEventType()方法即可拿到类型标识,返回值对应常量如下:
// 可连接非定向广播 public static final int EVENT_TYPE_ADV_IND = 0; // 可连接定向广播 public static final int EVENT_TYPE_ADV_DIRECT_IND = 1; // 可扫描非定向广播 public static final int EVENT_TYPE_ADV_SCAN_IND = 2; // 不可连接非定向广播 public static final int EVENT_TYPE_ADV_NONCONN_IND = 3; // 扫描响应(SCAN_RSP) public static final int EVENT_TYPE_SCAN_RSP = 4;
判断当前收到的是否为扫描响应,直接判断返回值是否等于EVENT_TYPE_SCAN_RSP即可,不需要额外解析广播载荷。
低版本兼容方案(API 21~25,Android 5.0~7.1)
这部分系统版本没有公开getEventType()接口,可选择两种方案实现:
- 反射取值(稳定性优先):该版本区间的
ScanResult内部已经持有事件类型字段,只是未标记为公开,反射即可拿到和高版本一致的类型值,示例代码:
这是工业界最常用的兼容方案,没有兼容性问题。private int getEventTypeCompat(ScanResult scanResult) { try { Field eventTypeField = ScanResult.class.getDeclaredField("mEventType"); eventTypeField.setAccessible(true); return (int) eventTypeField.get(scanResult); } catch (NoSuchFieldException | IllegalAccessException e) { return -1; } } - 特征匹配(无反射场景):如果不允许使用反射,可缓存最近100ms内同MAC地址的广播包,同一设备的普通广播和对应扫描响应会在极短时间内先后上报,后到的、携带完整设备名/服务数据的载荷即为扫描响应,该方案存在极低概率的误判,适合对精度要求不高的场景。
注意事项
- 启动扫描时只要不设置特殊过滤规则,所有类型的广播都会触发
onScanResult()回调,不需要额外配置即可拦截全类型广播。 - 只要将扫描模式设置为
SCAN_MODE_BALANCED或SCAN_MODE_LOW_LATENCY,系统检测到可扫描广播时会自动发送扫描请求,不需要开发者手动发起SCAN_REQ,拿到扫描响应后会通过同一个回调返回。
内容的提问来源于stack exchange,提问作者XDS
相关产品推荐
相关产品推荐

