调用了CallKit reportNewIncomingCall完成功能,但仍然收到“杀死应用程序,因为它从未发布过来电...".碰撞 [英] CallKit reportNewIncomingCall completion called but still getting "Killing app because it never posted an incoming call ..." crash

查看:138
本文介绍了调用了CallKit reportNewIncomingCall完成功能,但仍然收到“杀死应用程序,因为它从未发布过来电...".碰撞的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

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

这是我实现的 reportNewIncomingCall 的代码:

 让callUpdate = CXCallUpdate()callUpdate.remoteHandle = CXHandle(类型:.phoneNumber,值:会话)callUpdate.localizedCallerName =用户名callUpdate.hasVideo = truecallUpdate.supportsDTMF =否让uuid = {{some uuid}}provider.reportNewIncomingCall(with:uuid,update:callUpdate,complete:{error in如果让错误=错误{打印("reportNewIncomingCall错误:\(error.localizedDescription)")}DispatchQueue.main.async {完成()}}) 

编辑

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

  func pushRegistry(_注册表:PKPushRegistry,didReceiveIncomingPushWith负载:PKPushPayload,类型:PKPushType,完成:@escaping()-> Void){如果类型== .voIP {守卫让payloadData = payload.dictionaryPayload为[String:任何],让数据= payloadData [数据"]为?[String:任何],让typeCall = data ["type"]为?字符串其他{complete(); return}如果typeCall =="OPEN_ACTIVITY_CALL";{警卫让userName = data ["userName"]为?字符串其他{complete(); return}self.appleCallKit?.showIncomingCall(用户名:userName)}完成()}} 

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

解决方案

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

只需尝试将其删除:

  provider.reportNewIncomingCall(with:uuid,update:callUpdate,complete:{error in如果让错误=错误{打印("reportNewIncomingCall错误:\(error.localizedDescription)")}完成()}) 

编辑

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

  1. 如果 guard 语句之一失败,则不会报告新的来电,因此应用程序崩溃.您应该执行以下操作:

  guard允许有效载荷数据=有效载荷.dictionaryPayload为?[String:任何],让数据= payloadData [数据"]为?[String:任何],让typeCall = data ["type"]为?其他字符串{reportFakeCall(completion)//< ---返回} 

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

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

 如果typeCall =="OPEN_ACTIVITY_CALL";{警卫让userName = data ["userName"]为?其他字符串{reportFakeCall(completion)//<-如第1点返回}self.appleCallKit?.showIncomingCall(username:userName,完成)//< ---} 

将完成处理程序传递给 showIncomingCall ,并在 reportNewIncomingCall 的完成内调用它.

  1. 如果 typeCall 不等于 OPEN_ACTIVITY_CALL ,您不会报告新的来电,并且应用程序崩溃.

 如果typeCall =="OPEN_ACTIVITY_CALL";{...} 别的 {reportFakeCall(完成)} 

您可以如下实现 reportFakeCall 方法:

  func reportFakeCall(完成:@escaping()->无效){让callUpdate = CXCallUpdate()让vCallId = UUID()provider.reportNewIncomingCall(使用:vCallId,更新:callUpdate,完成:{错误完成()self.endCall(with:vCallId)//CXEndCallAction交易})} 

This is my first time using PushKit and CallKit combination to build a VoIP feature. I noticed that starting from iOS 13 it is mandatory to report a PushKit VoIP push, otherwise the app will crash.

Due to this regulation I proceeded to implement the reportNewIncomingCall method inside didReceiveIncomingPushWith and made sure that its completion is successfully called, which it did, because the breakpoint I placed within the completion block was activated.

However, not long after that, the app crashed and showed "Killing app because it never posted an incoming call to the system after receiving a PushKit VoIP callback", which is weird because previously the completion block was called.

Does anybody know why this happens?

This is the code of reportNewIncomingCall I implemented:

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()
    }
})

EDIT

This is the pushRegistry(_, didReceiveIncomingPushWith...) code:

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) method executes reportNewIncomingCall in the previous code block

解决方案

I think that the problem could be the DispatchQueue.main.async. This will cause your completion handler to be executed later in a future run loop and probably for the system is too late.

Just try to remove it:

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

EDIT

In the new code you've provided, I can see at least three errors that can lead to the crash.

  1. If one of the guard statements fails, you will not report a new incoming call, hence the app crashes. You should do something like this:

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 
    }

Report a fake call and immediately terminate it.

  1. Given that the reportNewIncomingCall is an asynchronous method, you are not guaranteed that the completion() of the pushRegistry(didReceiveIncomingPushWith...) will be called after the completion of the reportNewIncomingCall. So, in some cases, the app will crash because you havn't reported a new incoming call before the completion. You should do something like this:

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) // <---
}

Pass the completion handler to the showIncomingCall and call it inside the completion of the reportNewIncomingCall.

  1. If typeCall is not equal to OPEN_ACTIVITY_CALL you don't report a new incoming call and the app crashes.

if typeCall == "OPEN_ACTIVITY_CALL" {
    ...
} else {
    reportFakeCall(completion)
}

You can implement the reportFakeCall method as follows:

func reportFakeCall(completion: @escaping () -> Void)
{
    let callUpdate = CXCallUpdate()
    let vCallId = UUID()
    provider.reportNewIncomingCall(
        with: vCallId,
        update: callUpdate,
        completion: { error in
            completion()
            self.endCall(with: vCallId) // CXEndCallAction transaction
    })
}

这篇关于调用了CallKit reportNewIncomingCall完成功能,但仍然收到“杀死应用程序,因为它从未发布过来电...".碰撞的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆