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

iOS中心端APP配置BLE状态恢复后重启无法自动启动问题

iOS BLE中心端设备重启后自动启动失败排查思路

我尝试实现iOS中心端APP在设备重启后,检测到外设重新广播时自动启动。遵循Apple Core Bluetooth状态恢复指南配置后,APP无法自动重启。

预期行为:

  • 外设持续广播时,设备重启后APP自动启动
  • 因BLE事件启动APP时,launchOptions?[.bluetoothPeripherals]包含恢复的外设

观察到的行为:

  • 设备重启后APP未自动启动
  • 手动打开APP后,willRestoreState方法会被调用,但launchOptions?[.bluetoothPeripherals]为nil

用户代码:

override init() {
    super.init()
    centralManager = CBCentralManager(delegate: self, queue: nil,options: [CBCentralManagerOptionShowPowerAlertKey: true, CBCentralManagerOptionRestoreIdentifierKey: "MyCentralManager"])
}

func centralManager(_ central: CBCentralManager, willRestoreState state: [String : Any]) {
    if let peripherals = state[CBCentralManagerRestoredStatePeripheralsKey] as? [CBPeripheral] {
        print("Restored peripherals: \(peripherals)")
        let options: [String: Any] =
            
            [CBConnectPeripheralOptionNotifyOnConnectionKey: true, CBConnectPeripheralOptionNotifyOnDisconnectionKey: true, CBConnectPeripheralOptionNotifyOnNotificationKey: true]
            
        for peripheral in peripherals {
            // Optionally, reconnect to any restored peripherals
            centralManager.connect(peripheral, options: options)
        }
    }
}

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) {
    print("🔍 Discovered Peripheral: \(peripheral.name ?? "Unknown")")

    // Check if the discovered peripheral matches the target device
    if let peripheralName = advertisementData[CBAdvertisementDataLocalNameKey] as? String, peripheralName == "test-peripheral" {
        print("✅ Target Peripheral Found: \(peripheralName). Stopping scan...")
        centralManager.stopScan()

        // Save reference to discovered peripheral
        self.discoveredPeripheral = peripheral

        // Delay connection to allow time for testing reconnection scenarios
        DispatchQueue.main.asyncAfter(deadline: .now() + 7) { [self] in
            let options: [String: Any] = [
                CBConnectPeripheralOptionNotifyOnConnectionKey: true,
                CBConnectPeripheralOptionNotifyOnDisconnectionKey: true,
                CBConnectPeripheralOptionNotifyOnNotificationKey: true
            ]

            print("⚡ Connecting to \(peripheralName)...")
            centralManager.connect(peripheral, options: options)
        }
    } else {
        print("❌ No matching peripheral found.")
    }
}


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    print("🚀 AppDelegate: didFinishLaunchingWithOptions called")

    if let bluetoothPeripherals = launchOptions?[.bluetoothPeripherals] as? [String] {
        print("⚡ App relaunched by iOS due to BLE event! Restored peripherals: \(bluetoothPeripherals)")
        showAlert(title: "Peripheral Restoration", message: "Restored peripherals: \(bluetoothPeripherals.joined(separator: ", "))")
    } else {
        print("❌ No peripherals found in launch options.")
    }

    return true
}

排查思路

1. 确认状态恢复的核心前提

BLE状态恢复仅针对已成功建立连接的外设,单纯扫描外设不会触发系统重启后自动启动APP:

  • 必须确保重启设备前,APP已经与外设完成连接(确认centralManager(_:didConnect:)代理方法触发)
  • 重启前APP需处于后台挂起状态,手动划掉APP会清除系统保存的BLE恢复状态

2. 检查CBCentralManager初始化配置

  • CBCentralManagerOptionRestoreIdentifierKey必须全局唯一,整个APP只能有一个CBCentralManager实例使用该ID
  • 初始化需在APP启动早期完成(比如AppDelegate的didFinishLaunchingWithOptions中),确保实例不会被提前销毁(用户当前在init中初始化,需确认该实例是全局单例)

3. 验证连接选项的有效性

连接外设时必须设置以下选项为true,这是系统触发恢复的关键:

[
    CBConnectPeripheralOptionNotifyOnConnectionKey: true,
    CBConnectPeripheralOptionNotifyOnDisconnectionKey: true,
    CBConnectPeripheralOptionNotifyOnNotificationKey: true
]

用户代码中虽已设置,但需确保这些选项在连接成功时生效——当前代码的7秒延迟连接可能导致重启前还未建立连接,系统未保存恢复状态。

4. 修正launchOptions的认知

  • 只有系统自动启动APP时,launchOptions?[.bluetoothPeripherals]才会有值;手动打开APP时该字段为nil是正常行为
  • willRestoreState方法被调用,说明系统确实保存了BLE状态,但需结合系统启动日志确认是否触发了自动启动

5. 检查项目配置权限

  • 必须开启Background Modes中的Uses Bluetooth LE accessories(Xcode项目→Signing & Capabilities→Background Modes)
  • Info.plist中需配置蓝牙权限描述:NSBluetoothAlwaysUsageDescription(iOS 13+)或NSBluetoothPeripheralUsageDescription,且用户已授权蓝牙权限

6. 调整测试流程

正确的测试步骤应为:

  1. 打开APP,等待成功连接到外设(确认didConnect日志输出)
  2. 将APP退至后台(不要手动关闭)
  3. 重启iPhone,保持外设处于广播/可连接状态
  4. 解锁设备后等待30秒以上,系统可能有延迟触发APP启动

7. 日志调试

  • 通过Xcode的「Devices and Simulators」查看设备日志,搜索APP的Bundle ID或关键词bluetooth,确认系统是否尝试启动APP
  • 在willRestoreState中添加外设UUID的日志输出,确认恢复的外设信息:
    print("Restored peripheral UUIDs: \(peripherals.map { $0.uuid.uuidString })")
    

内容的提问来源于stack exchange,提问作者ajc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 19:55:58