如何过滤并发现发送扩展广播消息的BLE设备?
解决BLE扩展广播设备扫描问题
一、修正扫描配置,开启扩展广播支持
你的扫描设置缺少对非传统(扩展)广播的支持,nRF默认会开启该模式,所以能正常发现设备。需要修改ScanSettings的配置:
private void scanLeDevice() { // 移除无效的空过滤器,避免过滤掉扩展广播设备 List<ScanFilter> filters = null; ScanSettings.Builder settingsBuilder = new ScanSettings.Builder(); // 支持所有PHY层 settingsBuilder.setPhy(ScanSettings.PHY_LE_ALL_SUPPORTED); // 设置为低延迟扫描模式,提升扫描灵敏度 settingsBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY); // 禁用传统广播模式,仅扫描扩展广播(若需兼容传统广播,可设为true) settingsBuilder.setLegacy(false); // 实时上报扫描结果(0表示无延迟) settingsBuilder.setReportDelay(0); final BluetoothLeScanner bluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); mHandler.postDelayed(() -> { bluetoothLeScanner.stopScan(mScanCallback); Log.d(TAG, "scanLeDevice stopScan called"); }, SCAN_PERIOD); bluetoothLeScanner.startScan(filters, settingsBuilder.build(), mScanCallback); }
关键修改说明:
- 移除空过滤器:你之前创建的空
ScanFilter会触发系统默认过滤规则,可能导致扩展广播设备被排除,直接传null表示不设置任何过滤。 setLegacy(false):明确告诉系统扫描非传统(扩展)广播设备;如果需要同时兼容传统和扩展广播,可保留默认值(或显式设为true)。SCAN_MODE_LOW_LATENCY:低延迟扫描模式优先分配扫描资源,更容易捕获扩展广播包。
二、在扫描回调中识别并过滤扩展广播设备
通过ScanResult的API可以直接判断设备是否支持扩展广播,修改你的ScanCallback逻辑:
private final ScanCallback mScanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { Log.d(TAG,"onScanResult: " + result.toString()); runOnUiThread(() -> { BluetoothDevice device = result.getDevice(); // 判断是否为扩展广播设备(API 26+支持) boolean isExtendedAdvertising = !result.isLegacy(); // 也可通过扩展广播独有SID判断:result.getAdvertisingSid() != -1 // 结合原有过滤条件,只添加扩展广播设备 if (isExtendedAdvertising && device.getName() != null && !getString(R.string.unknown_device_text).equals(device.getName().toLowerCase())) { mLeDeviceListAdapter.addDevice(device); mLeDeviceListAdapter.notifyDataSetChanged(); } }); super.onScanResult(callbackType, result); } @Override public void onBatchScanResults(List<ScanResult> results) { Log.d(TAG,"onBatchScanResults: " + results.toString()); // 批量结果遍历判断扩展广播 runOnUiThread(() -> { for (ScanResult result : results) { if (!result.isLegacy()) { BluetoothDevice device = result.getDevice(); if (device.getName() != null && !getString(R.string.unknown_device_text).equals(device.getName().toLowerCase())) { mLeDeviceListAdapter.addDevice(device); } } } mLeDeviceListAdapter.notifyDataSetChanged(); }); super.onBatchScanResults(results); } @Override public void onScanFailed(int errorCode) { Log.d(TAG,"onScanFailed: errorCode: " + errorCode); super.onScanFailed(errorCode); } };
关键判断逻辑:
result.isLegacy():返回false表示该广播是扩展广播(Android 8.0+ API 26支持)。result.getAdvertisingSid():扩展广播会携带SID(会话ID),返回值不为-1即为扩展广播(同样API 26+支持)。
三、额外注意事项
- 权限检查:确保已申请必要权限,Android 12+需要
BLUETOOTH_SCAN、ACCESS_FINE_LOCATION权限;低版本需要ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION。 - 设备兼容性:部分老旧Android设备可能不支持扩展广播扫描,需确保测试设备的Android版本≥8.0,且硬件支持BLE 5.0及以上。
内容的提问来源于stack exchange,提问作者Sazzad Hissain Khan
相关产品推荐
相关产品推荐

