问题
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
回答1:
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
guardstatements 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
reportNewIncomingCallis 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
typeCallis not equal toOPEN_ACTIVITY_CALLyou 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
})
}
来源:https://stackoverflow.com/questions/63481795/callkit-reportnewincomingcall-completion-called-but-still-getting-killing-app-b