升级到iOS Beta 13之后,我注意到了一件不愉快的事情:我的应用有时会因传入的VoIP推送而崩溃。
在崩溃报告中,我看到以下内容:
iOS 13 Killing app because it never posted an incoming call to the system after receiving a PushKit VoIP callback Fatal Exception: NSInternalInconsistencyException 0 CoreFoundation 0x1af21b9f0 __exceptionPreprocess 1 libobjc.A.dylib 0x1af7284fc objc_exception_throw 2 CoreFoundation 0x1af11efec + [_CFXNotificationTokenRegistration keyCallbacks] 3 Foundation 0x1aeda1330 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] 4 PushKit 0x19caa6b54 -[PKPushRegistry _terminateAppIfThereAreUnhandledVoIPPushes] 5 libdispatch.dylib 0x1afa441ec _dispatch_client_callout 6 libdispatch.dylib 0x1af9f6c6c _dispatch_lane_barrier_sync_invoke_and_complete 7 PushKit 0x19caa5b74 __73-[PKPushRegistry voipPayloadReceived:mustPostCall:withCompletionHandler:]_block_invoke 8 libdispatch.dylib 0x1afa43678 _dispatch_call_block_and_release 9 libdispatch.dylib 0x1afa441ec _dispatch_client_callout 10 libdispatch.dylib 0x1af9f61f8 _dispatch_main_queue_callback_4CF$VARIANT$mp 11 CoreFoundation 0x1af1992a0 CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE 12 CoreFoundation 0x1af1942a8 __CFRunLoopRun 13 CoreFoundation 0x1af1937ac CFRunLoopRunSpecific 14 GraphicsServices 0x1ae395180 GSEventRunModal 15 UIKitCore 0x1b6e60244 UIApplicationMain 16 VOIPProject 0x1009822d8 main + 25 (AppDelegate.swift:25) 17 libdyld.dylib 0x1af6e9e7c start
我不明白如何解决该问题。每当收到VoIP推送消息时,我是否必须发布CallKit来电屏幕?这听起来很疯狂,因为在显示带有来电的屏幕之前,我检查通知是否有效。谁能解释我该怎么办?
在此线程从苹果论坛上,来自苹果的工作人员解释说有人这样:
在iOS 13.0和更高版本上,必须使用CallKit框架在收到传入IP语音呼叫时,并且在didReceiceIncomingPush()方法执行完毕之前,报告传入的IP语音呼叫,否则系统将终止您的应用程序。
反复未能报告呼叫可能会阻止您的应用接收更多来电通知。
基本上,您不能再将VoIP推送用于非VoIP消息传递,而将需要使用常规的推送通知。
这是在WWDC会议“应用程序后台执行的进展”会议期间宣布的:https://developer.apple.com/videos/play/wwdc2019/707/
我一直在寻找有关如何适应此更改的应用程序的答案,我可以收集以下内容:
语音推送
当您的应用收到这种推送时,它将需要使用CallKit报告新的来电。因此,这种推送仅适用于使用CallKit的呼叫。
建议您将通知的apns-expiration
值设置为0或很小的值,这样您就不会收到推送通知,并且会被迫为已过期的呼叫显示呼叫屏幕。
推送通知
定期推送通知是另一种选择。如果您的服务器具有编写通知文本所需的所有信息,则可以发送甚至不会在后台运行应用程序的通知。如果需要在将通知内容呈现给用户之前修改通知的内容,则可以使用Notification Service应用程序扩展,并且如果需要唤醒应用程序并在后台执行某些操作,则可以发送静默推送通知。
通知服务应用程序扩展
要使用此功能,必须将通知的设置mutable-content
为1。这样,扩展程序将在收到通知之前将其显示给用户,允许您在30秒的时间内更改其内容。
缺点是您的应用程序将保留在后台,仅允许您的扩展程序运行。这可能意味着您将需要在应用程序和扩展之间共享信息和代码,方法是使用用户默认值,钥匙串或共享整个数据库(如果您的应用程序没有为此做好准备,这可能不是一个简单的任务) 。
静默推送通知
要发送静默推送通知,您必须将通知的设置content-available
为1并删除它的alert,badge和sound。该通知将在后台唤醒您的应用,并调用您的应用代表的didReceiveRemoteNotification
。
该选项的缺点很烦人:
您将只获得30秒的运行时间。
这些通知必须apns-priority
为5,这可能导致它们被分组并突发发送,甚至被限制或不发送。
如果用户强行关闭应用程序,它将完全忽略所有静默通知,直到用户再次打开应用程序为止。