我们有一个BLE外设,每小时连接到手机并传递一些数据。以下是该过程的工作原理:
在
中使用键UIApplicationLaunchOptionsBluetoothCentralsKey
启动时
application(didFinishLaunchingWithOptions launchOptions)
app使用传递给它的ID重新初始化CBCentralManager。假设应用程序在手机重启后至少启动了一次,一切都运行良好几天(如果应用程序没有运行或被迫内存不足,iOS正常启动它,假设用户没有手动强行关闭)。
但是,当有来自BLE设备的传入请求时,iOS每隔几天就停止唤醒应用程序。如果用户重新启动应用程序一切正常工作几天,然后再次停止。鉴于我们产品的性质,让我们的应用程序/外围设备以最可靠的方式协同工作至关重要。
关于为什么会发生这种情况的理论:
(仔细研究后,所有人都被解雇了)
用户重新启动手机,忘记重新启动应用。
我们已经添加了正常运行时间的记录,并显示手机在应用启动之间没有重启。
内存警告会导致应用被启动。
再一次,添加了日志记录,他们发现没有applicationDidReceiveMemoryWarning
错误的连接会导致应用在上传结果时运行的时间超过10秒,并且iOS会终止并且会感到不安
我们人为地将服务器响应延迟了15秒来测试这一点,测试期间一切都能正常运行。
有关正在发生的事情以及为什么iOS停止通知应用程序有关传入BLE连接的任何想法?
其中一个问题是我们无法弄清楚如何可靠地重现问题所以任何建议都会受到高度赞赏!
谢谢!
更新1:
以下是我们初始化CBCentralManager
的方法:
self.centralManager = CBCentralManager(delegate: self, queue: nil, options: [
CBCentralManagerOptionRestoreIdentifierKey : MyCentralManagerID,
CBCentralManagerOptionShowPowerAlertKey : 0])
我看到一些建议,队列参数不应该是零。鉴于我无法可靠地重现问题,我在做出改变之前犹豫不决,直到我能够自信地观察它的影响。
答案 0 :(得分:4)
我想首先说我已经使用CoreBluetooth很长一段时间了,从我注意到CoreBluetooth状态保存和恢复根本不可靠。你可以让它正常工作,但是你永远不会让它可靠地重新连接,除非Apple有一天修复它。
有很多错误导致这种情况无法正常工作,但我会给你一个我认为会导致问题的错误:
如果事件源自您正在与之通信的外围附件,例如连接/断开连接事件和特征通知,状态恢复将仅重新启动您的应用程序,因为蓝牙相关活动。对于其他事件,最重要的是一般蓝牙状态更改事件,您的应用程序将不会重新启动并通知此情况。之所以如此糟糕,是因为所有蓝牙状态更改事件都将取消所有挂起或当前连接,这意味着挂起的连接将被删除,并且您的应用程序将不会收到通知。这实际上意味着您的应用程序仍然认为连接仍处于未决状态,而事实上它们并非如此。由于您的应用程序此时已终止,因此再次唤醒的唯一方法是让用户再次手动启动它(或者为此目的“破解”其他后台模式,这也不能非常可靠地工作)。 / p>
如果用户切换飞行模式,切换蓝牙,重启iOS设备或任何其他许多导致状态变化的未定义原因,就会发生这种情况......
但这只是一个错误。还存在许多其他因素,例如XPC连接在不同时间被中断而没有明显的原因。我还注意到挂起的连接可以进入“limbo”模式,其中外围状态设置为Connecting,但实际上它永远不会连接,除非你循环连接状态。
总之,我感到非常难过,说出来,但如果你正在开发必须依赖于周边在后台被重新连接的应用程序,然后我不建议这样做。你会感到沮丧。我可能会写一篇关于Apple不想修复的Core Bluetooth中所有错误的文章。更奇怪的是,你可以很容易地从一个应用程序破坏设备上的全局蓝牙连接,这样在设备重启之前没有应用程序可以使用蓝牙。这非常糟糕,因为它违反了Apple自己的沙盒原则。