App gets terminated when VoIP push is received when app in background

Our app gets terminated when an incoming call is received when app is in the background.

Error : Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: 'Killing app because it never posted an incoming call to the system after receiving a PushKit VoIP push callback.'

Xcode - 11.3
iPhone - SE (13.3.1)

Hello @Ajay_Nagwani

when received ringing event, you have to call ‘provider.reportNewIncomingCall()’ on the same thread.
https://developer.apple.com/documentation/pushkit/pkpushregistrydelegate/2875784-pushregistry

Important

On iOS 13.0 and later, if you fail to report a call to CallKit, the system will terminate your app. Repeatedly failing to report calls may cause the system to stop delivering any more VoIP push notifications to your app. If you want to initiate a VoIP call without using CallKit, register for push notifications using the UserNotifications framework instead of PushKit. For more information, see UserNotifications.

Thanks,

I’ve already reported a call. Can you please help me where am I wrong?

func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
// MARK: Handling incoming call
SendBirdCall.pushRegistry(registry, didReceiveIncomingPushWith: payload, for: type) { uuid in
guard uuid != nil else {
let update = CXCallUpdate()
let randomUUID = UUID()
update.remoteHandle = CXHandle(type: .generic, value: “invalid”)
CXCallManager.shared.reportIncomingCall(with: randomUUID, update: update) { error in
CXCallManager.shared.endCall(for: randomUUID, endedAt: Date(), reason: .acceptFailed)
}
completion()
return
}
completion()
}
}

If ‘SendBirdCall.pushRegistry()’ is handled normally, ‘SendBirdDelegate.didStartRinging’ is called from the same thread. You have to call the method there.

thanks

Please refer to quickstart example code.

We’ve referred this code. Our app gets crashed in following method:
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void)

with error: Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: 'Killing app because it never posted an incoming call to the system after receiving a PushKit VoIP push callback.'

I have the same issue, didStartRinging is not called cause App is killed before that method is called.

If I report the incoming call in the completion block of SendbirdCall.pushRegistry() the app is crashing, like in the Quickstart Code Sample.

But if I do it outside the completion block the app is not crashing, but I’m not sure how to proceed here.

// This is crashing

   func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
    SendBirdCall.pushRegistry(registry, didReceiveIncomingPushWith: payload, for: type) { uuid in
                SendBirdCall.pushRegistry(registry, didReceiveIncomingPushWith: payload, for: type) { uuid in
        guard uuid != nil else {
            let update = CXCallUpdate()
            update.remoteHandle = CXHandle(type: .generic, value: "invalid")
            let randomUUID = UUID()

            CXCallManager.shared.reportIncomingCall(with: randomUUID, update: update) { _ in
                CXCallManager.shared.endCall(for: randomUUID, endedAt: Date(), reason: .acceptFailed)
            }
            completion()
            return
        }

        completion()
    }
}

// This is working but then I have no UUID from Sendbird

func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
    let update = CXCallUpdate()
    update.remoteHandle = CXHandle(type: .generic, value: "Test")
    CXCallManager.shared.reportIncomingCall(with: UUID(), update: update)
    completion()

}

iOS13 SDK

Also researched here in the Apple forum
https://developer.apple.com/forums/thread/118607?page=2
Seems like CallSDK can’t work with Xcode 11 and iOS13 SDK, cause the behaviour change or requirements of PushKit

2020-08-31 18:23:53.798643+0200  [] nw_read_request_report [C1] Receive     failed with error "Software caused connection abort"
2020-08-31 18:23:53.799521+0200  Apps receving VoIP pushes must post an incoming call (via CallKit or IncomingCallNotifications) in the same run loop as   pushRegistry:didReceiveIncomingPushWithPayload:forType:[withCompletionHandler:] without delay.
2020-08-31 18:23:53.800579+0200  *** Assertion failure in -[PKPushRegistry _terminateAppIfThereAreUnhandledVoIPPushes], /Library/Caches/com.apple.xbs/Sources/PushKit/PushKit-37/PKPushRegistry.m:343
2020-08-31 18:23:53.801430+0200  [] nw_read_request_report [C10] Receive failed with error "Software caused connection abort"
2020-08-31 18:23:53.801962+0200  *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Killing app because it never posted an incoming call to the system after receiving a PushKit VoIP push callback.'
*** First throw call stack:
(0x1be429344 0x1be13ecc0 0x1be326878 0x1be778160 0x1d2baeb44 0x126d1f4d8 0x126d2ee14 0x1d2bad9e0 0x126d1e05c 0x126d1f4d8 0x126d2df64 0x1be3a48d4 0x1be39f58c 0x1be39ebc8 0x1c87805cc 0x1c2551744 0x102e6135c 0x1be21b384)
libc++abi.dylib: terminating with uncaught exception of type NSException

This is what I get as Error Message when I do exactly the same thing as in the QuickStart Example

from further testing I found out that when fresh install the app. First incoming Voip push works app is not crashing, but when I then try to put the app back to background and then start second incoming call app get’s killed as described as above.

Hello @Carmen, thanks for letting us know about the issue and sorry for the late response.

The incoming call report code within the completion block of SendBirdCall.pushRegistry() is for handling invalid push tokens, temporarily creating and destroying an empty call to prevent the app from failing.

If the didStartRinging is not called, can you check if you have implemented SendBirdCallDelegate in your AppDelegate and registered it to SendBirdCall by invoking SendBirdCall.addDelegate(APP_DELEGATE, identifier: IDENTIFIER)? By design, didStartRinging should run immediately if the SendBirdCall.pushRegistry is called with valid push payload, and you must report a CallKit call within the delegate method.

Thanks

1 Like

Hi, thanks for your reply.
Yes everything is hooked up with the SendbirdCallDelegate, it is also working for the first incoming call. But If I put the app back in background and start a second incoming call it is crashing.

I compiled the QuickStart Sample app with the latest SendbirdCall SDK and there I have the same issue.

I switch to SendbirdCall SDK 1.2.2 and there the issue doesn’t appear all the calls not only the first one are triggering the delegate and the didStartRinging method

Hi @Carmen, thanks for the reply.

So is the issue not appearing on SDK 1.2.2, but appearing on other versions? Could you provide us some code snippet of didStartRinging method if it’s possible? It would allow us to debug further because that is not supposed to happen.

This may occur if you are reporting an incoming call to CallKit in a separate queue inside didStartRinging. Also, could you also try it after re-installing the app, or from a different device?

We are currently debugging the issue as well :slight_smile:

Thanks

Exactly when I use the latest SDK version 1.2.5 second incoming call is crashing the app because the didStartRinging method is not called.
When I use the SDK version 1.2.2 everything is working for second incoming call.

This may occur if you are reporting an incoming call to CallKit in a separate queue inside didStartRinging . Also, could you also try it after re-installing the app, or from a different device?

I tried it a lot of times also on a different phone.
As I said a have also tried it with your QuickStart Sample app. there it is exactly the same issue as I have in my app.
The problem is the didStartRinging is not even called for the second incoming call. So call is not reported to CallKit.

i    func didStartRinging(_ call: DirectCall) {
    os_log("SendBirdCallDelegate Did start ringing", log: .sendBirdCall, type: .info)

    guard let uuid = call.callUUID else {
        fatalError()
    }
    
    guard CXCallManager.shared.shouldProcessCall(for: uuid) else {
        fatalError()
    }


    let name = call.caller?.nickname ?? "Unknown"
    let update = CXCallUpdate()
    update.remoteHandle = CXHandle(type: .generic, value: name)
    update.hasVideo = call.isVideoCall
    update.localizedCallerName = name

    CXCallManager.shared.reportIncomingCall(with: uuid, update: update)
}
func voipRegistration() {
    self.voipRegistry = PKPushRegistry(queue: DispatchQueue.main)
    self.voipRegistry?.delegate = self
    self.voipRegistry?.desiredPushTypes = [.voIP]
    os_log("PKPushRegistry configured", log: .sendBirdCall, type: .info)
}

I do not use other queues

Thanks for the additional information.
We have identified the issue and are preparing for a fix. I’ll let you know when we release the fix.

Thanks.

1 Like

Nice :+1:
Do you have a ruff estimation how long it would take to release the fix?
We want to deliver this cool feature as soon as possible :slight_smile:

Hi @Carmen,
We’ve just released SendbirdCalls SDK 1.2.6 with the fix for VoIP Push Notifications handling.
Can you check with this new version?

Thanks and sorry for the inconvenience.

1 Like

Thanks the issue seems to be fixed in this version. But therefore we recognized another issue:

  • Incoming Call, the callee doesn’t pick and the caller ends the call. The incoming call is still shown on caller side, it got not ended/canceled on callee side.

Are you saying that the call is not being cancelled on the callee side even after the caller ends(cancels) the call? Have you implemented the DirectCallDelegate and didEnd delegate method and report the endCall action to CallKit?

yes you’re right we forgot to set in AppDelegate also the DircectCallDelegate, we only set in the UI component when call was already accepted.

Thanks that fixed the issue :+1:t2: