Search code examples
cordovaapple-push-notificationscordova-pluginsvoipios13

IOS 13 VOIP Push Notifications not received when app is KILLED


We have a Cordova App which is using WebRTC for Video Chat.
We are using this plugin to achieve VOIP Push Notifications https://github.com/mattkhaw/cordova-plugin-callkit.
Along with that, we are using AWS SNS to handle the VOIP pushes for us.
How does the flow work?

IOS Device Calee (User A)
1. When device opens the app, it registers on Apple servers and 
receives a VOIP Device Token
2. We call Amazon SNS to save the token and get the endpointARN for that token
3. We save the token in the database along with the user ID and endpointARN 
from AWS

Caller Side (User B)
1. User B wants to call User A
2. User B clicks the call button
3. A request it send to the server, which checks if a token exists for User A 
in the database.
4. If it exists, we call AWS SNS endpointARN so it will 
send a VOIP push to User A

All this is working fine when the app is open or when the app is in background.
The problem arises when the app is killed (terminated).
When the app is killed, the app crashes, and here is the log that we receive for that https://gist.github.com/AleksandarTokarev/74068feadd728a4bd1c672a024482af4.
I did some research on the log details, and it seems that the cause for that is written in
https://developer.apple.com/forums/thread/124517.

The exception code "0xbaadca11" indicates that your app was killled for failing to report a CallKit 
call in response to a PushKit notificaiton.  That should have been clear in the crash log,
but this particular requirement is implemented through multiple code paths and it looks like this 
one isn't as clear as the others.  For more details on the new requirement, take a look at:
https://developer.apple.com/videos/play/wwdc2019/707/

Any idea why this is happening? The plugin works correctly when app is running or in background.
I am using the following payload to call AWS SNS

let voip_protocol_value = `{"aps" : { "alert": "New Incoming Call" },
 "data" : { "Caller": { "Username" : "${caller}", "ConnectionId": "${Random.id()}"}}}`
                let payload = {}
                payload[`APNS_VOIP`] = voip_protocol_value
                let params = {
                    'Message': JSON.stringify(payload),
                    'MessageAttributes': {
                        'AWS.SNS.MOBILE.APNS.PRIORITY': {
                            'DataType': 'String',
                            'StringValue': '10'
                        },
                        'AWS.SNS.MOBILE.APNS.PUSH_TYPE': {
                            'DataType': 'String',
                            'StringValue': 'voip'
                        },
                    },
                    'MessageStructure': 'json',
                    'TargetArn': user.endpointArn
                }

Solution

  • I managed to fix this by modifying the plugin in the following way:
    https://github.com/luisbouca/cordova-plugin-callkit/compare/master...AleksandarTokarev:master.

    It seems that init() function was not being called when app was KILLED (TERMINATED), so a friend of mine helped me do small refactor and put the init() function code in the plugin initialize.

    This meant that Pushkit was not initialized (because it was in the init() method).

    The init() method is still there, but it is called when that is initialized in Javascript.

    This is probably related to our Meteor Cordova app and how things are initialized in the app itself.

    Now all works fine.