当从外围设备传入BLE连接时,iOS停止唤醒应用程序

当从外围设备传入BLE连接时,iOS停止唤醒应用程序,ios,iphone,bluetooth-lowenergy,cbcentralmanager,Ios,Iphone,Bluetooth Lowenergy,Cbcentralmanager,我们有一个可移动的外设,每小时连接一次电话,并传送一些数据。以下是该过程的工作原理: 使用中的键启动应用程序启动时 应用程序(didFinishLaunchingWithOptions launchOptions)应用程序使用传递给它的ID重新初始化CBCentralManager 然后,它经过常规的恢复周期,从BLE外围设备读取数据 对云中的服务执行REST请求 假设该应用程序在手机重启后至少启动过一次,那么几天内一切正常(如果应用程序未运行或内存不足,iOS会正确地重新启动,假设用户没有手动

我们有一个可移动的外设,每小时连接一次电话,并传送一些数据。以下是该过程的工作原理:

使用中的键启动应用程序启动时

  • 应用程序(didFinishLaunchingWithOptions launchOptions)
    应用程序使用传递给它的ID重新初始化CBCentralManager
  • 然后,它经过常规的恢复周期,从BLE外围设备读取数据
  • 对云中的服务执行REST请求
  • 假设该应用程序在手机重启后至少启动过一次,那么几天内一切正常(如果应用程序未运行或内存不足,iOS会正确地重新启动,假设用户没有手动强制关闭)

    但是,每隔几天,当有来自设备的传入请求时,iOS就会停止唤醒应用程序。若用户重新启动应用程序,一切正常运行几天,然后再次停止。鉴于我们产品的性质,让我们的应用程序/外围设备以最可靠的方式协同工作至关重要

    关于为什么会发生这种情况的理论:
    (经过仔细检查,他们全部被解雇)

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

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

    • 连接不良会导致应用程序在上传结果时运行时间超过10秒,iOS会终止应用程序并使其心烦意乱
      为了测试这一点,我们人为地将服务器响应延迟了15秒,并且在测试过程中一切都继续正常工作

    关于发生了什么以及为什么iOS停止向应用程序通知传入的BLE连接,有什么想法吗

    其中一个问题是,我们无法找出如何可靠地重现该问题,因此任何建议都将受到高度赞赏

    谢谢大家!


    更新1: 下面是初始化CBCentralManager的方法:

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

    我看到一些建议,队列参数不应为零。考虑到我无法可靠地再现问题,在我能够自信地观察到其影响之前,我很犹豫是否要进行更改。

    我想首先说,我已经使用CoreBlutooth很长时间了,从我所注意到的情况来看,CoreBlutooth状态保存和恢复根本无法可靠地工作。你可以让它正常工作,但除非有一天苹果能修复它,否则你永远无法让它可靠地重新连接

    有太多的bug导致此功能无法正常工作,但我将给您一个我认为会导致您出现问题的bug:

    如果事件源于您正在与之通信的外围设备附件(如连接/断开连接事件和特征通知),则状态恢复仅会因蓝牙相关活动而重新启动您的应用程序。对于其他事件,最重要的是一般蓝牙状态更改事件,您的应用程序将不会重新启动并通知此事件。之所以如此糟糕,是因为所有蓝牙状态更改事件都将取消所有挂起或当前连接,这意味着挂起的连接将被删除,而应用程序将不会收到通知。这实际上意味着您的应用程序仍将认为连接仍处于挂起状态,而实际上它们并非如此。由于您的应用程序此时被终止,因此再次唤醒它的唯一方法是让用户再次手动启动它(或者为此目的“黑客”其他后台模式,这也不太可靠)

    如果用户切换飞行模式、切换蓝牙、重启iOS设备或任何其他导致状态改变的未定义原因,就会发生这种情况

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


    无论如何,我很难过地说,但如果你开发的应用程序必须依赖于在后台重新连接外围设备,那么我不建议你这么做。你会感到沮丧。我可能会写一篇关于核心蓝牙中苹果不想修复的所有缺陷的文章。更奇怪的是,你可以很容易地从一个应用程序破坏设备上的蓝牙连接,这样在设备重新启动之前,任何应用程序都不能使用蓝牙。这是非常糟糕的,因为它违背了苹果自己的沙箱原则。

    Anton,谢谢你在这个问题上发表了如此透彻和深思熟虑的帖子。试图弄明白这一点非常令人沮丧,你的回答证实了我们一直担心的问题——问题出在iOS本身,而不是我们的应用程序在做什么,因此基本上超出了我们的控制范围。我能够在这些问题上获得“一些”可靠性,请查看我在这里的帖子