23

升级到 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 来电屏幕?这听起来很疯狂,因为我在显示来电屏幕之前检查通知是否有效。谁能解释我该怎么办?

4

1 回答 1

46

在苹果论坛的这个帖子上,苹果员工的某个人解释了这一点:

在 iOS 13.0 和更高版本上,必须在收到 IP 语音呼叫时以及在 didReceiceIncomingPush() 方法完成执行之前使用 CallKit 框架报告传入的 IP 语音呼叫,否则系统将终止您的应用程序。

多次不报告来电可能会阻止您的应用接收更多来电通知。

基本上,您不能再将 VoIP 推送用于非 VoIP 消息,并且需要使用常规推送通知。

这是在 WWDC 会议“应用程序后台执行的进步”期间宣布的https://developer.apple.com/videos/play/wwdc2019/707/


我一直在寻找有关如何使应用程序适应这种变化的答案,我可以收集到以下内容:

VoIP 推送

当您的应用收到这种推送时,它需要使用 CallKit 报告新的来电。因此,这种推送将专用于使用 CallKit 的调用。

建议您将通知设置apns-expiration为 0,这样您就不会收到推送并被迫显示已过期呼叫的呼叫屏幕。

推送通知

定期推送通知是另一种选择。如果您的服务器拥有编写通知文本所需的所有信息,您可以发送通知,这些通知甚至不会在后台运行您的应用程序。如果您需要在呈现给用户之前修改通知的内容,您可以使用 Notification Service 应用扩展,如果您需要唤醒您的应用并在后台执行某些操作,您可以发送静默推送通知。

通知服务应用程序扩展

要使用它,您必须将通知设置mutable-content为 1。这样,您的扩展程序将在通知呈现给用户之前收到通知,允许您更改其内容,时间限制为 30 秒。

缺点是您的应用程序将保留在后台,仅允许您的扩展程序运行。这可能意味着您需要在应用程序和扩展程序之间共享信息和代码,方法是使用用户默认值、钥匙串或共享整个数据库(如果您的应用程序没有为此做好准备,这可能不是一项简单的任务) .

静默推送通知

要发送静默推送通知,您必须将通知设置content-available为 1 并删除它的警报徽章声音。此通知将在后台唤醒您的应用,并调用您的应用委托的didReceiveRemoteNotification.

这个选项的缺点很烦人:

  • 您将只有 30 秒的时间运行。
  • 这些通知的 a 必须apns-priority为 5,这可能会导致它们被分组并以突发方式传递,甚至被限制或不传递。
  • 如果用户强制关闭应用程序,它将完全忽略所有静默通知,直到用户再次打开应用程序。
于 2019-08-21T16:16:54.353 回答