Skip to content

VOIP notifications

Marco Brescianini edited this page Nov 7, 2024 · 34 revisions

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 while using the Kaleyra Video SDK 4.0 version. If you need the guide for the previous versions of the Kaleyra Video SDK please refer to the this guide instead.

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 Kaleyra Video 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 Kaleyra Video 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:

  • Listen on "on_call_incoming" webhook coming from Kaleyra Video. (Discover how your backend can be notified with upcoming call events registering event hook on_call_incoming here)
  • Forward the data you have received via the webhook to APNS

The client side

The following chapters will guide you through the steps you should do in order to enable VoIP notifications in your app using the Kaleyra Video SDK.

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

VoIP management strategies

Starting from 2.9.0 version the Kaleyra Video SDK provides two strategies for handling VoIP notifications received by your app: automatic and manual. The former, automatically handle the reception of VoIP notifications on behalf of your app. The latter, allows you to take control of the VoIP notifications received by your app at the cost of writing the code required to handle VoIP notifications properly.

Automatic strategy

When the Kaleyra Video SDK uses the automatic strategy, your code is required to perform only two tasks. First, configure the Kaleyra Video SDK 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.

Automatic configuration

You tell the Kaleyra Video SDK to use an automatic VoIP handling strategy setting the "automatic" value to the voip property of the configuration object. The following snippets of code will show you how the Kaleyra Video SDK should be configured:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    var config = Config(appID: "APP ID", region: .europe, environment: .sandbox)
    config.voip = .automatic(listenForNotificationsInForeground: false)

    do {
        try KaleyraVideo.instance.configure(config)
    } catch {}

    return true
}
Getting the device push token

The Conference voipCredentialsPublisher will notify its subscribers whenever the VoIP 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:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    var config = Config(appID: "APP ID", region: .europe, environment: .sandbox)
    config.voip = .automatic(listenForNotificationsInForeground: false)

    do {
        try KaleyraVideo.instance.configure(config)
        KaleyraVideo.instance.conference?.voipCredentialsPublisher.sink { credentials in
            print("Token: \(credentials?.tokenAsString)")
        }.store(in: &subscriptions)
    } catch {}

    return true
}

Note

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 (got from your app delegate's application(_:didRegisterForRemoteNotificationsWithDeviceToken:) method) and one for the VoIP push notifications (got from the Kaleyra Video SDK).

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), 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 is configured, 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 your app is ready

Receiving VoIP notifications in foreground

While configuring the VoIP notifications handling strategy to automatic, you can provide a boolean flag indicating whether the Kaleyra Video SDK should listen for VoIP notifications when your app is in background and when it is in foreground. By default, the Kaleyra Video SDK won't listen for VoIP notifications while your app is in foreground. However, if you want to enable this feature you can tell the SDK to do so while configuring it.

The following snippets of code will how you'd do it:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    var config = Config(appID: "APP ID", region: .europe, environment: .sandbox)
    config.voip = .automatic(listenForNotificationsInForeground: true)

    do {
        try KaleyraVideo.instance.configure(config)
    } catch {}

    return true
}

Manual strategy

Below you'll find the required steps you should take if you choose to opt-in for handling VoIP notifications yourself.

Manual configuration

Before the Kaleyra Video SDK can be initialized you must tell you want to opt-in for the manual VoIP management strategy:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    var config = Config(appID: "APP ID", region: .europe, environment: .sandbox)
    config.voip = .manual

    do {
        try KaleyraVideo.instance.configure(config)
    } catch {}

    return true
}
VoIP notification hand over

Once your app has received a VoIP notification you must hand it over to the Kaleyra Video SDK.

class MyNotificationHandler: PKPushRegistryDelegate {

    func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
        KaleyraVideo.instance.conference?.handleNotification(payload)
        completion()
    }
}

Important

Beware, you must configure the SDK before the push payload can be handed over to it.

Show the call UI

The last thing you must do is present the call user interface when the [Conference] callPublisher emits a new value

Requirements

When choosing to opt-in for the manual VoIP management there are a few requirements to be met by your app in order for the Kaleyra Video SDK to play nice with CallKit.

I) Initialize the PKPushRegistry object providing it a background serial queue. Do not use the main queue nor provide nil as the PKPushRegistry initializer argument

func foo() {
    // DO THIS
    let queue = DispatchQueue(label: "foobar")
    let registry = PKPushRegistry(queue: queue)

    // DO NOT DO THIS
    let registry = PKPushRegistry(queue: .main)
   
    // NOR THIS
    let registry = PKPushRegistry(queue: nil)
}

II) VoIP notifications should be handled only when your app is in background. When the app is in foreground the Kaleyra Video SDK will receive incoming calls through a direct connection with our back-end. However, if you'd like to receive VoIP notifications when the app is in foreground and you'd like the SDK to not receive incoming calls from the direct connection you must tell the Kaleyra Video SDK you want so:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    var config = Config(appID: "APP ID", region: .europe, environment: .sandbox)
    config.voip = .manual
    config.shouldListenForDirectIncomingCalls = false

    do {
        try KaleyraVideo.instance.configure(config)
    } catch {}

    return true
}

Notification payload

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
  },
  "event": "on_call_incoming",
  "room_id": "room_58fee601fcef",
  "data": {
    "initiator": "usr_123456789",
    "roomAlias": "room_58fee601fcef",
    "options": {
      "callType": "audio_video",
      "creationDate": "2020-06-26T10:59:04.315Z",
      "duration": 0,
      "recordingType":"automatic",
      "recording":"automatic",
      "live": true,
      "record": false
    },
    "users": [
      {
        "status": "invited",
        "user": {
          "userAlias": "usr_987654321"
        }
      },
      {
        "status": "invited",
        "user": {
          "userAlias": "usr_123456789"
        }
      }
    ]
  }
}

When a VoIP notification is received, the Kaleyra Video SDK will search for the actual payload it needs to create an incoming call. The Kaleyra Video SDK cares about information in the following format:

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

Sample apps

Take a look at our sample app for an example of how to integrate the Kaleyra Video with support for VoIP push notifications in your app.

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.

Clone this wiki locally