核心蓝牙 - 在后台执行长期行动

时间:2016-11-23 10:23:56

标签: ios objective-c iphone bluetooth core-bluetooth

这来自官方文档中的iOS应用核心蓝牙背景处理部分:

在后台执行长期操作

  

某些应用可能需要使用Core Bluetooth框架才能执行   在后台进行长期行动。举个例子,想象一下   为通信的iOS设备开发家庭安全应用程序   带门锁(配备蓝牙低能耗技术)。该   应用程序和锁相互作用,以便在用户自动锁定门   当用户返回时,离开家并解锁门   应用程序在后台。当用户离开家时,iOS设备   可能最终变得超出锁定范围,导致连接   锁定丢失。此时,应用程序可以简单地调用   connectPeripheral:options:CBCentralManager类的方法,和   因为连接请求没有超时,iOS设备会   用户返回家园时重新连接。

好的,我们有一个应用程序可以根据需要锁定/解锁门......正如所指出的,这适用于app在后台(很可能处于挂起模式)。现在,让我们继续(使用引用文档):

  

现在假设用户离开家几天。如果应用程序   当用户离开时系统终止,应用程序不会   当用户返回家时,能够重新连接到锁   用户可能无法解锁门。对于像这样的应用程序,它是   能够继续使用Core Bluetooth执行至关重要   长期行动,例如监控活动和待定连接。

因此,如果用户离开家几天,并且应用程序已被iOS终止,我们将不得不实施状态保存和恢复,以便iOS在检测到连接请求时重新启动应用程序,并让解锁门的应用程序。相关报价:

  

在上述家庭安全应用程序的情况下,系统   将监视连接请求,并重新启动应用程序   处理centralManager:didConnectPeripheral:委托回调时   用户返回主页并完成连接请求。

这一切都有道理,但请再次关注这一部分:

  

现在假设用户离开家几天。如果应用程序   当用户离开时,由系统终止,当用户返回家时,应用程序将无法重新连接到锁定,并且   用户可能无法解锁门。对于像这样的应用程序,它   能够继续使用Core Bluetooth执行至关重要   长期行动......

这是否意味着,如果用户在离家时的某个时刻被用户强行杀死,那么这也会有效吗?意味着当用户回家时,无论如何门都会解锁,或者他必须手动重新启动应用以解锁门?

我问这个问题,因为终止应用程序的重新启动是如何工作的。当用户杀死应用程序时,以及当iOS杀死支持后台执行的应用 时,它就不一样了:

  

支持后台执行的应用程序可能会被系统重新启动   处理传入的事件。如果应用因任何原因被终止   除了用户强制退出之外,系统启动应用程序   当发生以下事件之一时......

Source

再一次,如果用户离开了几天并且他通过双击Home按钮并向上拖动来关闭应用程序,他是否可以在不手动重新启动应用程序的情况下进入他的家?

1 个答案:

答案 0 :(得分:2)

没有。如果应用程序被用户强行杀死,那么它将不再被唤醒。它将被唤醒的唯一场景是,如果应用程序被iOS本身终止,这种情况迟早会发生,当应用程序暂时不是它的前景时。如果重启设备,它也不会重新启动。

话虽如此,根据我对Core Bluetooth的经验,我得出的结论是State Preservation太不可靠了。我相信你试图实现的用例不会运行得很好,这很具有讽刺意味,因为它正是Apple正在推广它的文档的用例。

例如,您将遇到以下问题:

如果事件源自您正在与之通信的外围附件,例如连接/断开连接事件和特征通知,状态恢复将仅重新启动您的应用程序,因为蓝牙相关活动。对于其他事件,最重要的是一般的蓝牙状态更改事件,您的应用将不会重新启动并通知此情况。之所以如此糟糕,是因为任何蓝牙状态更改事件都会导致所有待处理的连接被抛出,这意味着您的门锁连接将丢失。但是,由于您的应用程序未重新启动以通知此情况,因此它实际上意味着您的应用程序仍然认为连接仍处于待处理状态,而事实上它们并非如此。由于您的应用程序此时已终止,因此再次唤醒的唯一方法是让用户再次手动启动它(或者为此目的“破解”其他后台模式,这也不会非常可靠地工作)。 / p>

如果用户切换飞行模式,切换蓝牙,重启iOS设备或许多导致状态更改的任何其他未定义原因,则会出现这种情况......如果&不太可能发生蓝牙状态变化#34; ...用户离开家几天。"。

这个"问题"我和其他人多次报道过,但Apple出于某种原因似乎并不想修复它。

除此之外,还存在许多其他问题,例如XPC连接在不同时间被中断,没有明显的原因。我还注意到挂起的连接可以进入“limbo”模式,其中外围状态设置为Connecting,但实际上它永远不会连接,除非你循环连接状态。等等......

/ A