If you are implementing incoming call as another function and calling it as below. It won't work
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
yourIncomingCallFunction()
}
Instead Try Following :
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
print("didReceiveIncomingPushWith payload")
if let callerID = payload.dictionaryPayload["callerID"] as? String,
let hasVideo = payload.dictionaryPayload["hasVideo"] as? Bool{
let update = CXCallUpdate()
update.remoteHandle = CXHandle(type: .generic, value: callerID)
update.hasVideo = hasVideo
let bgTaskID = UIApplication.shared.beginBackgroundTask(expirationHandler: nil)
self.provider?.reportNewIncomingCall(with: UUID(), update: update, completion: { (_) in
completion()
})
UIApplication.shared.endBackgroundTask(bgTaskID)
}
completion()
}
This has Implemented the call provider posting call request inside the pushRegistry:didReceiveIncomingPushWith payload with completion handler function. This worked for me.
Try the VOIP request with terminal command:
curl -v -d '{"callerID": "test@test.com", "uuid":"YourUDIDorEmptyField", "hasVideo": false}' --http2 --cert yourvoipcertificatepemfile_Here.pem:pemfilePassword_Here https://api.development.push.apple.com/3/device/yourDeviceTokenID_generated_with_update_push_credentials_with_token_Here
Replace:
test@test.com with related details on CXHandle.HandleType
If it is your Callers Name (.generic) or email (.emailAddress) or phone number (.phoneNumber)
YourUDIDorEmptyField with your UUID or you can keep it empty as when reportNewIncomingCall(with: UUID(), update: callUpdate) has initialize UUID() in the code itself.
"hasVideo" : false here false is a Boolean (true/false) obviously that handles the Audio / Video call status on the incoming calling screen and you can use it to identify the call as exactly what type it is by implementing it.
yourvoipcertificatepemfile_Here is the name of your .pem file that you have exported from the voip certificate (voipcertificate.cer not directly but after generating from developer account and installing to your machine. Then in your keychain -> mycertificates export it as .pem file with a Password (pemfilePassword_Here).)
pemfilePassword_Here is your password that you have given when you are exporting .pem file from your installed voip certificate. (refer to 4th point.)
yourDeviceTokenID_generated_with_update_push_credentials_with_token_Here should be replace with the token generated by following Delegate method of PKPushRegistryDelegate. See below.
func pushRegistry(_ registry: PKPushRegistry,didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) {
let parts = pushCredentials.token.map { String(format: "%02.2hhx", $0) }
let token = parts.joined()
print("did update push credentials with token: \(token)") }
If you have any concern please let me know. I have tried and tested this on App in foreground, background, lockScreen, and even after app removed from recent apps.
(iOS 13.4.1 and Xcode Version 11.4 (11E146))