排查用于发现可用蓝牙设备的Broadcast Receiver故障
蓝牙设备扫描BroadcastReceiver代码问题分析及修复建议
你的BroadcastReceiver代码存在以下几个关键问题,导致蓝牙设备扫描功能异常:
1. 类名拼写错误
类名AvailableBroadcaseReciever存在两处拼写错误:
Broadcase应为BroadcastReciever应为Receiver
虽不会直接导致功能失效,但不符合Android命名规范,易引发代码混淆。
2. 权限检查逻辑缺陷
- 权限位置错误:你在获取
BluetoothDevice实例后才检查BLUETOOTH_CONNECT权限,但Android 12(API 31)及以上版本扫描蓝牙设备需要BLUETOOTH_SCAN权限,且必须在启动扫描前完成权限申请——onReceive生命周期极短,无法在此处理权限请求弹窗。 - 缺失必要权限:除
BLUETOOTH_CONNECT外,需在Manifest中声明并动态申请BLUETOOTH_SCAN权限:<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
3. 设备名称空指针风险
部分蓝牙设备未设置名称,调用device.getName()会返回null,直接添加到列表会导致UI显示异常。需增加非空判断,可使用设备MAC地址兜底:
String deviceName = device.getName() != null ? device.getName() : device.getAddress(); DevicesList.availableDevices.add(deviceName);
4. 静态列表的重复添加与线程安全问题
DevicesList.availableDevices作为静态ArrayList存在两个问题:
- 重复扫描时会重复添加同一设备,需先判断设备是否已存在:
String deviceId = device.getAddress(); // MAC地址唯一 boolean isExist = DevicesList.availableDevices.stream().anyMatch(item -> item.equals(deviceName) || item.equals(deviceId)); if (!isExist) { DevicesList.availableDevices.add(deviceName); adapter2.notifyDataSetChanged(); } - 蓝牙扫描回调可能在非主线程执行,直接操作ArrayList会引发线程安全问题,建议改用
CopyOnWriteArrayList这类线程安全集合。
5. Adapter引用导致的内存泄漏风险
BroadcastReceiver持有RecyclerView.Adapter的强引用,而Adapter又关联Activity,若BroadcastReceiver未及时注销,会导致Activity无法被GC回收,引发内存泄漏。建议改用弱引用持有Adapter:
private WeakReference<RecyclerView.Adapter> adapterRef; public AvailableBroadcastReceiver(RecyclerView.Adapter adapter) { this.adapterRef = new WeakReference<>(adapter); } // 在onReceive中使用 RecyclerView.Adapter adapter = adapterRef.get(); if (adapter != null) { adapter.notifyDataSetChanged(); }
6. 未处理扫描结束状态
可监听BluetoothAdapter.ACTION_DISCOVERY_FINISHED广播,在扫描结束后更新UI(比如提示用户扫描完成),完善体验:
@Override public void onReceive(Context context, @NonNull Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { // 原有设备发现逻辑 } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { Toast.makeText(context, "扫描完成", Toast.LENGTH_SHORT).show(); } }
额外注意事项
- 动态注册BroadcastReceiver时,需正确设置IntentFilter:
IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothDevice.ACTION_FOUND); filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); registerReceiver(availableBroadcastReceiver, filter); - 确保蓝牙适配器已开启,且启动扫描的代码正确:
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter != null && bluetoothAdapter.isEnabled()) { if (ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) { // 提前申请权限 return; } bluetoothAdapter.startDiscovery(); }
内容的提问来源于stack exchange,提问作者Shady Abdulmunim
相关产品推荐
相关产品推荐

