iOS停止从外设传入的BLE连接唤醒应用程序

我们有一个BLE外围设备,每小时连接到手机并传递一些数据。 这是过程如何工作:

启动时使用密钥UIApplicationLaunchOptionsBluetoothCentralsKey

  1. application(didFinishLaunchingWithOptions launchOptions)应用程序使用传递给它的ID重新初始化CBCentralManager。
  2. 然后经过正常的恢复周期,从BLE外设读取数据。
  3. 对云中的服务执行REST请求。

假设应用程序已经启动至less一次手机重启后,一切运作良好几天(如果应用程序没有运行或被迫内存不足,iOS正常启动它,假设用户没有强制closures手动)。

然而,每隔几天,当有来自BLE设备的传入请求时,iOS停止唤醒应用程序。 如果用户重新启动应用程序,一切正常工作几天,然后再次停止。 鉴于我们产品的性质,以尽可能最可靠的方式使我们的应用程序/外设一起工作至关重要。

关于为什么可能发生的理论:
(经仔细检查,他们全部被解雇)

  • 用户重新启动手机,忘记重新启动应用程序。
    我们添加了正常运行时间的日志logging,并显示手机在启动应用程序之间没有重新启动。

  • 内存警告导致应用程序被启动。
    再次,添加日志logging,他们表明,没有applicationDidReceiveMemoryWarning

  • 上传结果导致应用程序运行时间超过10秒,iOS终止结果并不高兴
    我们人为地将服务器响应延迟了15秒,以testing这一点,并且在testing过程中,所有事情都能正常运行。

任何想法正在发生的事情,为什么iOS停止通知应用程序关于传入的BLE连接?

其中一个问题是,我们无法弄清楚如何可靠地重现问题,所以任何build议都会非常感谢!

谢谢!


更新1:这是我们如何初始化CBCentralManager

 self.centralManager = CBCentralManager(delegate: self, queue: nil, options: [ CBCentralManagerOptionRestoreIdentifierKey : MyCentralManagerID, CBCentralManagerOptionShowPowerAlertKey : 0]) 

我看到一些build议队列参数不应该是零。 鉴于我无法可靠地重现问题,我犹豫不决,直到我可以自信地观察它的影响。

我想先说我已经在CoreBluetooth工作了很长一段时间,从我注意到,CoreBluetooth State Preservation and Restoration不能可靠地工作。 你可以得到它的工作“好”,但你永远不会得到它可靠地重新连接,除非苹果有一天修复它。

有太多的错误,导致这个不能正常工作,但我会给你一个,我相信是造成你的问题:

如果事件来自您正在与之通信的外设附件(如连接/断开连接事件和特征通知),状态恢复将只会因蓝牙相关的活动而重新启动您的应用程序。 对于其他事件,最重要的是一般的蓝牙状态改变事件,你的应用程序不会重新启动并通知这个。 之所以这么糟糕,是因为所有的蓝牙状态改变事件都会取消所有挂起或当前的连接,这意味着挂起的连接将被丢弃,你的应用程序将不会被通知。 这实际上意味着你的应用程序仍然会认为这些连接还没有完成。 由于此时您的应用程序被终止,所以再次唤醒的唯一方法是让用户再次手动启动它(或者为此目的“破解”其他背景模式,这也不能非常可靠地工作)。

如果用户切换飞行模式,切换蓝牙,重启iOS设备,或任何其他未定义的原因,许多导致状态更改…

但这只是一个错误。 还有许多其他的存在,比如XPC连接在不同时间被中断而没有明显的原因。 我也注意到挂起的连接可以进入“边缘”模式,其中外围状态被设置为连接,但事实上,除非循环连接状态,否则它将不会连接。

无论如何,我很难说,但如果你正在开发一个应用程序,必须依赖外设在后台重新连接,那么我不会推荐这样做。 你会感到沮丧。 我大概可以写一篇关于苹果公司不想解决的核心蓝牙问题的文章。 更奇怪的是,你可以从一个单一的应用程序很容易地毁坏设备上的全球蓝牙连接,所以没有应用程序可以使用蓝牙,直到设备重新启动。 这是非常糟糕的,因为它违背了苹果自己的沙盒原则。