调用了CallKit reportNewIncomingCall完成功能,但仍然收到“杀死应用程序,因为它从未发布过来电...".碰撞 [英] CallKit reportNewIncomingCall completion called but still getting "Killing app because it never posted an incoming call ..." crash
问题描述
这是我第一次使用 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)")}完成()})
编辑
在您提供的新代码中,我至少看到了三个可能导致崩溃的错误.
- 如果
guard
语句之一失败,则不会报告新的来电,因此应用程序崩溃.您应该执行以下操作:
guard允许有效载荷数据=有效载荷.dictionaryPayload为?[String:任何],让数据= payloadData [数据"]为?[String:任何],让typeCall = data ["type"]为?其他字符串{reportFakeCall(completion)//< ---返回}
举报虚假电话并立即终止.
- 鉴于
reportNewIncomingCall
是异步方法,因此不能保证pushRegistry(didReceiveIncomingPushWith ...)
的completion()
>将在reportNewIncomingCall
完成后被调用.因此,在某些情况下,该应用程序将崩溃,因为您没有在完成之前报告新的来电.您应该执行以下操作:
如果typeCall =="OPEN_ACTIVITY_CALL";{警卫让userName = data ["userName"]为?其他字符串{reportFakeCall(completion)//<-如第1点返回}self.appleCallKit?.showIncomingCall(username:userName,完成)//< ---}
将完成处理程序传递给 showIncomingCall
,并在 reportNewIncomingCall
的完成内调用它.
- 如果
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.
- 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.
- Given that the
reportNewIncomingCall
is an asynchronous method, you are not guaranteed that thecompletion()
of thepushRegistry(didReceiveIncomingPushWith...)
will be called after the completion of thereportNewIncomingCall
. 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
.
- If
typeCall
is not equal toOPEN_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屋!