iOS:如何实现BLE设备连接/断开状态的全局通知?
iOS BLE 后台连接通知问题解决方案
问题核心
需求是监听选中BLE设备的连接/断开事件,在APP前台、后台、终止状态下都发送通知。当前前台正常,后台仅能接收断开事件,已开启Uses Bluetooth LE accessories和Acts as a Bluetooth LE accessory权限。
iOS BLE 后台行为限制
iOS对BLE中心设备的后台操作有严格约束:
- 前台状态:主动发起连接的
didConnect回调正常触发,断开事件didDisconnectPeripheral也能正常接收。 - 后台状态:仅能接收已连接设备的断开事件;主动发起连接的操作会被系统挂起,
didConnect不会触发。 - 终止状态:仅当已配对的外围设备主动发起重连时,系统会唤醒APP并触发状态恢复回调。
必要配置调整
- 修正后台模式权限:
你的APP是BLE中心设备,不需要Acts as a Bluetooth LE accessory(该权限用于APP作为外围设备),确保Background Modes中仅勾选Bluetooth LE accessories即可。 - 请求通知权限:
必须获取用户的通知弹窗权限,否则后台无法展示自定义通知,在APP启动时添加权限请求:func requestNotificationPermission() { UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, error in if granted { DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() } } } }
代码逻辑修正
1. 修复状态恢复逻辑
当前willRestoreState仅通过设备名称判断,易出错(设备名称可修改),改为用唯一标识符identifier判断,同时遍历所有恢复的设备:
public func centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any]) { if let restoredPeripherals = dict[CBCentralManagerRestoredStatePeripheralsKey] as? [CBPeripheral] { for peripheral in restoredPeripherals { // 检查是否为用户选中过的设备 if selectedPeripheralUUIDs.contains(peripheral.identifier) { sendNotification(title: "连接恢复", body: "已恢复与\(peripheral.name ?? "未知设备")的连接") connectedCBperipheral = peripheral peripheral.delegate = self } } } }
2. 保存选中设备的唯一标识
APP重启后,CBPeripheral对象会失效,改为保存设备的UUID:
// 新增:保存用户选中设备的UUID数组 @Published var selectedPeripheralUUIDs: [UUID] = [] // 修改选择设备方法 public func selectPeripheralToObserveConnection(_ item: CBPeripheral) { if !selectedPeripheralUUIDs.contains(item.identifier) { selectedPeripheralUUIDs.append(item.identifier) } connectingCBperipheral = item }
3. 修正连接逻辑
添加后台连接通知选项,确保外围设备主动重连时能触发通知:
func connect(to peripheral: CBPeripheral) { guard peripheral.state != .connected else { return } peripheral.delegate = self // 开启后台连接通知选项 myCentral.connect(peripheral, options: [CBConnectPeripheralOptionNotifyOnConnectionKey: true]) }
4. 修复代码语法错误
- 方法名拼写错误:
disconect改为disconnect - 补全
didDisconnectPeripheral的方法括号:
public func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: (any Error)?) { print("已断开与\(peripheral.name ?? "未知设备")的连接", error?.localizedDescription ?? "") connectedCBperipheral = nil sendNotification(title: "已断开连接", body: "已与\(peripheral.name ?? "未知设备")断开连接") }
终止状态下的处理
APP完全终止后,无法主动扫描连接设备,但如果设备已配对,当外围设备主动发起重连时:
- 系统会弹出蓝牙连接的系统通知
- 系统会唤醒APP并触发
willRestoreState回调,此时可在该方法中发送自定义通知
核心限制说明
iOS不允许BLE中心设备在后台/终止状态下主动扫描并连接设备,只能被动处理已配对/已连接设备的断开或重连事件。要实现后台连接通知,必须依赖外围设备主动发起重连,同时配置正确的权限和连接选项。
内容的提问来源于stack exchange,提问作者Tung Vu Duc
相关产品推荐
相关产品推荐

