外围设备需要特殊 ACK 时的 CoreBluetooth 和状态保存和恢复

CoreBluetooth and State Preservation & Restoration when peripheral needs special ACK

我正在使用一个蓝牙外围设备,在连接到它之后,在它真正可以向我发送我需要的数据之前来回有一个 ACK​​。

流程是这样的:

  1. 发现外设
  2. 连接外设
  3. 发现服务和特征
  4. 监听特定特征的更新
  5. 外设向该特性发送特殊消息
  6. 然后应用向外设发送ACK
  7. 外设将app需要的数据发给我

我已经在状态保存和恢复的协议方法中实现了所需的逻辑centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any])

问题一:

当应用程序在后台并且 iOS 决定接管蓝牙通信(出于资源原因)时,iOS 将如何完成第 5、6 和 7 步?

因为如果不能,则外围设备将无法发送应用程序在步骤 7 中需要的数据。

问题二:

在我读到的文档中,iOS 可能会启动您的应用程序几秒钟。在那种情况下会执行我的根 ViewController 的 viewDidLoad 方法吗?这就是我实例化 CBCentralManager

的地方

我发现的一些在线资源:

Core Bluetooth Background Processing for iOS Apps

Zero to BLE on iOS – Part Three

Paulw11 的这两条评论帮助我理解了发生了什么:

No, that doesn’t happen. If you have a pending discovery, a pending “connect” or you have an active notify on a characteristic then iOS will relaunch your app so that it can handle the discovery, the connection or the notification. iOS can’t do this on your behalf; it doesn’t know what you want to do. – Paulw11


Having your Bluetooth object attached to a view controller is a bad idea if you want to perform operations in the background. I suggest a singleton or an object owned by your app delegate – Paulw11


首先,我错误地认为 iOS 会在我的应用程序处于后台时尝试代表我的应用程序处理所有蓝牙通信并且 iOS 不得不终止它。实际情况是 iOS 在有限的时间内以后台模式启动应用程序,以便您可以 运行 您的恢复代码。

最后,我的 ViewController 的 viewDidLoad 中的逻辑是错误的。我创建了一个 BluetoothManager class 并在 AppDelegate

application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool 方法中实例化了它