You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS:如何实现BLE设备连接/断开状态的全局通知?

iOS BLE 后台连接通知问题解决方案

问题核心

需求是监听选中BLE设备的连接/断开事件,在APP前台、后台、终止状态下都发送通知。当前前台正常,后台仅能接收断开事件,已开启Uses Bluetooth LE accessories和Acts as a Bluetooth LE accessory权限。

iOS BLE 后台行为限制

iOS对BLE中心设备的后台操作有严格约束:

  • 前台状态:主动发起连接的didConnect回调正常触发,断开事件didDisconnectPeripheral也能正常接收。
  • 后台状态:仅能接收已连接设备的断开事件;主动发起连接的操作会被系统挂起,didConnect不会触发。
  • 终止状态:仅当已配对的外围设备主动发起重连时,系统会唤醒APP并触发状态恢复回调。

必要配置调整

  1. 修正后台模式权限:
    你的APP是BLE中心设备,不需要Acts as a Bluetooth LE accessory(该权限用于APP作为外围设备),确保Background Modes中仅勾选Bluetooth LE accessories即可。
  2. 请求通知权限:
    必须获取用户的通知弹窗权限,否则后台无法展示自定义通知,在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完全终止后,无法主动扫描连接设备,但如果设备已配对,当外围设备主动发起重连时:

  1. 系统会弹出蓝牙连接的系统通知
  2. 系统会唤醒APP并触发willRestoreState回调,此时可在该方法中发送自定义通知

核心限制说明

iOS不允许BLE中心设备在后台/终止状态下主动扫描并连接设备,只能被动处理已配对/已连接设备的断开或重连事件。要实现后台连接通知,必须依赖外围设备主动发起重连,同时配置正确的权限和连接选项。

内容的提问来源于stack exchange,提问作者Tung Vu Duc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 10:29:54