Android 1大意模拟规范 risks筛选 enum Avoid...依班 这条 (修正为)Android 13下BluetoothLeScanner无扫描结果,AltBeacon触发回调求助
问题概述
- 测试设备:三星M33 5G
- 系统版本:Android 13
- 核心问题:使用Android原生
BluetoothLeScanner初始化扫描时,注册的ScanCallback完全收不到扫描结果,但相同代码在Android 13以下版本运行正常。已确认授予「查找附近设备」ACCESS_FINE_LOCATION、ACCESS_COARSE_LOCATION等所有必要权限,排除权限问题。 - 特殊现象:当在应用其他类中初始化并运行第三方库AltBeacon的
BeaconManager后,原本无法收到回调的BluetoothLeScanner突然能正常获取扫描结果,二者运行在不同线程,不清楚AltBeacon是如何触发系统让所有BluetoothLeScanner回调生效的。
相关代码
public class BLEScanner { private BluetoothLeScanner Scanner; private BleAdapter adapter; private Timer RemoveTimer; private Context ctx; private Handler mHandler = new Handler(Looper.getMainLooper()); private Timer mTimer; private boolean isSortingScheduled = false; public BLEScanner(Context mctx, BleAdapter ade) throws Exception { ctx = mctx; adapter = ade; ResumeScanning(); } public void PauseScanning() { try { if (Scanner != null) { Scanner.stopScan(mScanCallback); Scanner = null; } } catch (SecurityException ex) { Log.e("BLEScanner", ex.getMessage()); } } public void ResumeScanning() throws Exception { final BluetoothManager bluetoothManager = (BluetoothManager) ctx.getApplicationContext().getSystemService(Context.BLUETOOTH_SERVICE); BluetoothAdapter adepter = BluetoothAdapter.getDefaultAdapter(); if (adepter != null) { Scanner = null; Scanner = adepter.getBluetoothLeScanner(); if (Scanner != null) { try { // 创建扫描过滤器 ScanSettings settings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) .build(); ArrayList<ScanFilter> filters = new ArrayList<ScanFilter>(); ScanFilter filter1 = new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString("XXXXXXXX-0000-1000-8000-0080XXXXXXXX")).build(); filters.add(filter1); Scanner.startScan(filters, settings, mScanCallback); if (RemoveTimer != null) { RemoveTimer.cancel(); RemoveTimer = null; } RemoveTimer = new Timer(); RemoveTimer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { adapter.Remove(); } }, 500, 500); } catch (SecurityException ex) { Log.d("Scanner", ex.getMessage()); } } } else { throw new Exception(); } } public ScanCallback mScanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { try { if (callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES) { BluetoothDevice dev = result.getDevice(); String address = dev.getAddress(); for (BLEModel m : adapter.SynList) { if (m.getAddress().equalsIgnoreCase(address)) { m.updateDevice(result); startOrScheduleSortingTask(); return; } } BLEModel model = new BLEModel(); model.updateDevice(result); if (Globals.isAccessCardAPPDevice(model.getType())) { adapter.SynList.add(model); Collections.sort(adapter.SynList, (model1, model2) -> { double distance1 = model1.getDistance(); double distance2 = model2.getDistance(); return Double.compare(distance1, distance2); }); adapter.notifyDataSetChanged(); } else model = null; } else //if (callbackType == ScanSettings.CALLBACK_TYPE_MATCH_LOST) { Log.d("Scanner", String.valueOf(callbackType)); } } catch (Exception e) { e.printStackTrace(); } } }; private void startOrScheduleSortingTask() { if (!isSortingScheduled) { // 立即在主线程执行排序 performSortingTask(); // 每500毫秒重复执行排序任务 mHandler.postDelayed(sortingRunnable, 500); isSortingScheduled = true; } } private Runnable sortingRunnable = new Runnable() { @Override public void run() { // 在主线程执行排序 performSortingTask(); // 500毫秒后调度下一次排序 mHandler.postDelayed(this, 500); } }; private void performSortingTask() { Collections.sort(adapter.SynList, (model1, model2) -> { double distance1 = model1.getDistance(); double distance2 = model2.getDistance(); return Double.compare(distance1, distance2); }); adapter.notifyDataSetChanged(); } }
问题分析与解决思路
1. Android 13 BLE扫描的隐性限制
Android 13对BLE扫描新增了更严格的行为限制,即便权限齐全,也可能因为以下原因导致扫描失败:
- 扫描过滤器匹配严格:代码中使用了
ScanFilter过滤特定服务UUID,Android 13对UUID匹配的校验逻辑更苛刻,若广播包中的UUID格式(比如大小写、字节序)不符合要求,会直接被过滤掉。可以先移除过滤器测试,看是否能收到扫描结果。 - 后台扫描资源限制:
SCAN_MODE_LOW_LATENCY优先级虽高,但Android 13对后台扫描的系统资源调度限制更严。尝试在前台启动扫描,或者将扫描逻辑放入前台服务(添加前台通知),确保扫描任务处于活跃状态。
2. AltBeacon触发扫描恢复的原因
AltBeacon库内部的适配逻辑间接修复了扫描问题,可能的原因包括:
- 系统BLE服务唤醒:AltBeacon初始化时会主动触发系统BLE扫描服务的初始化,而之前你的代码可能因某些原因未正确唤醒该服务,导致扫描回调无响应。
- 兼容性扫描参数配置:AltBeacon使用的扫描设置(比如无严格过滤器、不同的回调类型组合)符合Android 13的调度要求,触发系统扫描服务正常工作后,你的扫描器也能共享这个状态。
- 权限适配补充:AltBeacon内部针对Android 13做了额外的权限处理逻辑,间接解决了扫描的隐性权限问题。
3. 修复建议
- 临时方案:如果不想依赖AltBeacon,可以参考其逻辑,在启动目标扫描前,先启动一次无过滤的临时扫描(持续1-2秒后停止),唤醒系统BLE服务后再启动你的扫描任务。
- 排查过滤器问题:移除
ScanFilter测试,若能收到结果,再检查目标UUID的格式是否完全匹配广播包中的UUID,或尝试使用模糊匹配方式。 - 切换为前台扫描:将扫描逻辑放入前台服务,添加前台通知,避免系统因后台资源限制暂停扫描。
- 确认蓝牙状态:启动扫描前,通过
BluetoothAdapter.isEnabled()确认蓝牙已完全开启,必要时监听蓝牙状态广播,待蓝牙稳定后再启动扫描。
内容的提问来源于stack exchange,提问作者Spectra
相关产品推荐
相关产品推荐

