双蓝牙连接服务使用相同SPP UUID时广播接收触发异常如何解决?
问题成因
- 系统发送的
BluetoothDevice.ACTION_ACL_CONNECTED、BluetoothDevice.ACTION_ACL_DISCONNECTED属于全局广播,所有注册了对应Action的BroadcastReceiver都会收到触发回调,和你连接用的UUID、获取设备的API无关,这是安卓蓝牙广播的正常机制,所以你两个接收器都会被触发属于预期内的情况。 - 你遇到的“单台设备断开、收到两台都断开的通知”问题,和UUID完全无关,广播携带的
BluetoothDevice.EXTRA_DEVICE参数就是触发本次事件的对应设备,不会出现地址混淆,问题出在你自己的状态维护逻辑:要么是两个接收器共用了同一个连接状态变量,要么是状态更新分支写错,才会出现误判。
解决办法
第一步:补全基础校验
你现有代码缺少空值判断,某些系统场景下广播可能不携带设备参数,直接调用方法会触发空指针,先补全判空逻辑:
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (device == null || TextUtils.isEmpty(device.getAddress())) { return; }
第二步:合并重复的广播接收器
两个接收器逻辑完全重复,不需要注册两次,合并为一个接收器统一处理两台设备的状态更新,避免状态变量被重复修改的问题:
// 全局状态变量分开维护,不要共用 private boolean isPrinterConnected = false; private boolean isSecondDeviceConnected = false; private BroadcastReceiver bluetoothStateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // 空值校验 if (TextUtils.isEmpty(action) || device == null || TextUtils.isEmpty(device.getAddress())) { return; } String devAddress = device.getAddress(); // 匹配打印机MAC if (devAddress.equals(PrinterConnectionService.PRINTER_MAC_ADDRESS)) { if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) { Log.d("TAG", "打印机已连接"); isPrinterConnected = true; // 此处可加你自己的连接后逻辑 } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) { Log.d("TAG", "打印机已断开"); isPrinterConnected = false; // 此处可加你自己的断开后逻辑 } } // 匹配第二台外设MAC else if (devAddress.equals(DEV2_MAC_ADDRESS)) { if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) { Log.d("TAG", "第二台外设已连接"); isSecondDeviceConnected = true; // 此处可加你自己的连接后逻辑 } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) { Log.d("TAG", "第二台外设已断开"); isSecondDeviceConnected = false; // 此处可加你自己的断开后逻辑 } } } }; // 只需要注册一次接收器即可 private void initBluetoothReceiver() { IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); registerReceiver(bluetoothStateReceiver, filter); }
第三步:加兜底校验逻辑
不要完全依赖系统广播的结果,需要用到连接状态时,优先从你自己实现的两个连接服务里取socket的连接状态,比系统广播更准确,示例参考:
// 从服务获取真实连接状态,避免广播延迟/丢失导致的误判 public boolean getPrinterConnectState() { if (printerConnectionService != null) { return printerConnectionService.getSocket().isConnected(); } return false; } public boolean getSecondDeviceConnectState() { if (secondDeviceConnectionService != null) { return secondDeviceConnectionService.getSocket().isConnected(); } return false; }
内容的提问来源于stack exchange,提问作者Shqipdon
相关产品推荐
相关产品推荐

