VOIP notifications - Bandyer/Bandyer-iOS-SDK Wiki

Enabling VoIP push notifications is the only way your users can receive incoming calls while your application is not active in foreground. In this document we will guide you through the steps needed to enable and support VoIP notifications in your app.

This guide shows you how to enable VoIP push notifications with the BandyerSDK version >= 1.2.0 If you need the guide for the previous versions of the BandyerSDK please refer to the old revisions of this guide.

Table of Contents:

Requirements

VoIP push notifications requires CallKit framework. If you haven't enabled CallKit in your app yet, head over to our CallKit integration guide before reading any further.

The server side

The Bandyer platform does not handle the delivery of notifications on behalf of your application. It is up to you how to deliver notifications to your app. The Bandyer platform provides a set of web hooks you can subscribe to with your servers, in order to be notified about call events, such as calls being created, ended and so on. Here below you'll find the bare minimum steps your server side code must perform in order to deliver voip push notifications to your app:

The client side

On the client side your code must perform only two task. First, configure the BandyerSDK providing the information it needs to handle the notification payload for you. Second, send the device push token received from the operating system to your server.

Project setup

First of all, you must setup your project adding to your app target the push notification capability. You must enable push notification capability even if your app does not support regular push notifications, otherwise you won't receive VoIP push notifications either. If you have already set up your app to support regular push notifications, you can skip this chapter altogether.

To enable push notifications in your app, open Xcode and select your app project file in the "project navigator" panel on the left side of your screen. Then, select your app target in Xcode main panel and select the "Signing & Capabilities" tab.

push-notifications-step-1

Then click on the "+ Capability" button in the upper left corner of the "Signing & Capabilities" tab, it should appear a dialog with a list of capabilities you can add to your app (if "Push Notifications" is not listed in the capabilities dialog, then you have already added the Push Notifications capability to your app). Finally double click on the "Push Notifications" entry and you are good to go.

push-notifications-step-2

Eventually an entitlement file should have been added to your project and a "Push Notifications" capability entry should have been added in Xcode's "Signing & Capabilities" tab, like in the following screenshot.

push-notifications-step-3

SDK configuration

The BDKConfig object contains two properties that you must populate in order to support VoIP push notifications in your app. The first property is pushRegistryDelegate, it expects an object conforming to PKPushRegistryDelegate protocol; the provided object will be used by the BandyerSDK when setting up VoIP push notifications and it is responsible for handling the device push token received by the operating system. The second property is notificationPayloadKeyPath, it contains the key path where the BandyerSDK will look for the incoming call information contained within the voip push notification payload.

The following snippets of code will show you how the BandyerSDK should be configured in order to handle VoIP notifications properly:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // [...] 

    //The following statement is going to tell the BandyerSDK which object it must forward device push tokens to when one is received.
    config.pushRegistryDelegate = self

    //Now we are ready to initialize the SDK providing the app id token identifying your app in Bandyer platform.
    BandyerSDK.instance().initialize(withApplicationId: "PUT YOUR APP ID HERE", config: config)

    return true
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //[...]

    //The following statement is going to tell the BandyerSDK which object it must forward device push tokens to when one is received.
    config.pushRegistryDelegate = self;

    //Now we are ready to initialize the SDK providing the app id token identifying your app in Bandyer platform.
    [BandyerSDK.instance initializeWithApplicationId:@"PUT YOUR APP ID HERE" config:config];

    return YES;
}

Getting the device push token

Beware, VoIP device push tokens are not regular push tokens, they look the same but they are not. If your app uses regular push tokens and you are integrating VoIP push also, you are going to get two push device tokens, one for the regular push notifications and one for the VoIP push notifications.

The object conforming to PKPushRegistryDelegate you provided during BandyerSDK configuration will be called whenever the device push token is updated by the system. It is up to you to deliver the token received to your back-end system. Here a simple snippet of code showing you how the PKPushRegistryDelegate looks like:

func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) {
    let token = pushCredentials.tokenAsString
    //Send the device token to your notification delivery system
}

- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)pushCredentials forType:(PKPushType)type
{
    NSString *token = pushCredentials.bdk_tokenAsString;
    //Send the device token to your notification delivery system
}

Beware, the PKPushRegistryDelegate methods won't be called unless the call client has been started. You MUST start the call client in order to receive the device push token, initialising the BandyerSDK is not sufficient to get the token.

Receiving VoIP notifications

You should not do anything to receive VoIP notifications, the Kaleyra Video SDK will handle that for you. Once a VoIP notification is received, the iOS operating system will wake-up or launch your app in background (it depends whether your app is in suspended state or not) like the user would launch it from the springboard, so your app delegate application(_:didFinishLaunchingWithOptions:) method will be called (only if the app was suspended actually), the root view controller will be loaded and installed in your app main window, your app will execute the same flow it would execute if it was launched by the user from the springboard. Once the Kaleyra Video SDK call client is started, the VoIP notification will be handed to your app and processed by the Kaleyra Video SDK. The only thing you must do is present the call user interface when the BCXCallClientObserver callClient:didReceiveIncomingCall: method is called

extension MyViewController: CallClientObserver {

    public func callClient(_ client: CallClient, didReceiveIncomingCall call: Call) {
        let intent = HandleIncomingCallIntent(call: call)
	
	//Present the call UI interface
	//[...]
    }
}

@implementation MyViewController

- (void)callClient:(id <BDKCallClient>)client didReceiveIncomingCall:(id <BDKCall>)call
{
    BDKHandleIncomingCallIntent *intent = [[BDKHandleIncomingCallIntent alloc] initWithCall:call];

    //Present the call UI interface
    //[...]	
}

@end

Notification payload key path

The voip push notification payload received by your app is just a simple dictionary containing the information your server sent to APNS. It looks like this:

{
  "aps": {
    "alert": {
      "title": ""
    },
    "content-available": 1
  },
  "data": {
    "initiator": "usr_123456789",
    "options": {
      "callType": "audio_video",
      "creationDate": "2020-06-26T10:59:04.315Z",
      "duration": 0,
      "live": 1,
      "record": 0
    },
    "roomAlias": "room_58fee601fcef",
    "users": [
      {
        "status": "invited",
        "user": {
          "userAlias": "usr_987654321"
        }
      },
      {
        "status": "invited",
        "user": {
          "userAlias": "usr_123456789"
        }
      }
    ]
  },
  "event": "on_call_incoming",
  "room_id": "room_58fee601fcef"
}

When a VoIP notification is received, the Kaleyra Video SDK will search for the actual payload it needs to create an incoming call. It'll do that automatically, but you can help it out giving it the path it must look for the actual incoming call payload, through the notificationPayloadKeyPath property found on the BDKConfig object.
You are not required to set any value on the notificationPayloadKeyPath property, but if you do it, the Kaleyra Video SDK will use the keypath found in that property when searching for the actual notification payload.

The Kaleyra Video SDK cares about information in the following format:

{
  "initiator": "usr_123456789",
  "options": {
    "callType": "audio_video",
    "creationDate": "2020-06-26T10:59:04.315Z",
    "duration": 0,
    "live": 1,
    "record": 0
  },
  "roomAlias": "room_58fee601fcef",
  "users": [
    {
      "status": "invited",
      "user": {
        "userAlias": "usr_987654321"
      }
    },
    {
      "status": "invited",
      "user": {
        "userAlias": "usr_123456789"
      }
    }
  ]
}   

Sample apps

We created two apps, one in objective-c and one in swift to show you how to integrate the Kaleyra Video with support for VoIP push notifications in your app. The two apps show you how to enable CallKit and VoIP push notifications because they go hand to hand. Starting from iOS 13, VoIP push notifications require CallKit to work.

Where to go from here

You should now have a better understanding of how to integrate VoIP push notifications in your app. If you haven't already you should take a look at our Receiving an incoming call guide that will show you how to handle an incoming call in your app.