调用CallKit reportNewIncomingCall完成,但仍然收到“正在杀死应用程序,因为它从未发布过来电...”崩溃

问题描述

这是我第一次使用PushKitCallKit组合来构建VoIP功能。我注意到,从iOS 13开始,必须报告 PushKit VoIP推送,否则该应用将崩溃。

由于这项规定,我继续在reportNewIncomingCall内实现didReceiveIncomingPushWith方法,并确保成功完成了它的完成,因为我放置在完成块中的断点已被激活。

但是,此后不久,该应用程序崩溃并显示“杀死应用程序,因为它在收到PushKit VoIP回调后从未向系统发布来话呼叫”,这很奇怪,因为之前已调用完成模块。

有人知道为什么会这样吗?

这是我实现的reportNewIncomingCall的代码:

let callUpdate = CXCallUpdate()
callUpdate.remoteHandle = CXHandle(type: .phoneNumber,value: session)
callUpdate.localizedCallerName = username
callUpdate.hasVideo = true
callUpdate.supportsDTMF = false
        
let uuid = {{some uuid}}
        
provider.reportNewIncomingCall(with: uuid,update: callUpdate,completion: { error in
    if let error = error {
         print("reportNewIncomingCall error: \(error.localizedDescription)")
    }
    DispatchQueue.main.async {
        completion()
    }
})

编辑

这是pushRegistry(_,didReceiveIncomingPushWith...)代码:

func pushRegistry(_ registry: PKPushRegistry,didReceiveIncomingPushWith payload: PKPushPayload,for type: PKPushType,completion: @escaping () -> Void) {
    if type == .voIP {
         guard let payloadData = payload.dictionaryPayload as? [String: Any],let data = payloadData["data"] as? [String: Any],let typeCall = data["type"] as? String else { completion();return }

         if typeCall == "OPEN_ACTIVITY_CALL" {
              guard let userName = data["userName"] as? String else { completion();return }
              self.appleCallKit?.showIncomingCall(username: userName)
         }
         completion()
    }
}

self.appleCallKit?.showIncomingCall(username: userName)方法在上一个代码块中执行reportNewIncomingCall

解决方法

我认为问题可能出在DispatchQueue.main.async上。这将使您的completion处理程序在以后的运行循环中稍后执行,可能对系统而言为时已晚。

只需尝试将其删除:

provider.reportNewIncomingCall(with: uuid,update: callUpdate,completion: { error in
    if let error = error {
        print("reportNewIncomingCall error: \(error.localizedDescription)")
    }
    completion()
})

编辑

在您提供的新代码中,我至少看到了三个可能导致崩溃的错误。

  1. 如果guard语句之一失败,则不会报告新的来电,因此应用程序崩溃。您应该执行以下操作:
guard let payloadData = payload.dictionaryPayload as? [String: Any],let data = payloadData["data"] as? [String: Any],let typeCall = data["type"] as? String else { 
        reportFakeCall(completion) // <---
        return 
    }

举报虚假电话并立即终止。

  1. 鉴于reportNewIncomingCall是异步方法,因此不能保证completion()完成后将调用pushRegistry(didReceiveIncomingPushWith...)的{​​{1}}。因此,在某些情况下,该应用程序将崩溃,因为您在完成之前没有报告新的来电。您应该执行以下操作:
reportNewIncomingCall

将完成处理程序传递给if typeCall == "OPEN_ACTIVITY_CALL" { guard let userName = data["userName"] as? String else { reportFakeCall(completion) // <-- As in point 1 return } self.appleCallKit?.showIncomingCall(username: userName,completion) // <--- } ,并在showIncomingCall的完成内调用它。

  1. 如果reportNewIncomingCall不等于typeCall,则不会报告新的来电,并且应用会崩溃。
OPEN_ACTIVITY_CALL

您可以如下实现if typeCall == "OPEN_ACTIVITY_CALL" { ... } else { reportFakeCall(completion) } 方法:

reportFakeCall

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...