Push Notification

Push Notification is a feature that Notify the about the call.

Call PushNotification#

For enabling push notification for calls in IOS, you need to generate a VOIP Services Certificates in .p12 format with password. Once you have generated the VOIP certificate, share the .p12 along with its password to the server team for configuration in notificationservice.

The following screenshot shows the Audio Single Call PushNotification in Foreground and Background.

PushNotification

The following screenshot shows the Video Group Call PushNotification in Foreground and Background.

PushNotification

Add Notification Service Extension#

Notification Service extension is use to modify the contents of notifications before they are display and download the content

To obtain your Notification Service Extension you need to follow the below steps:

Step 1 : Create a new target for Notification Service with File > New > Target > Search Notification Service Extension, then Next.

PushNotification

Step 2 : When a dialog appears to activate the target extension, Give a name. For example: NotificationService, then click Finish.

PushNotification

Step 3 : The notification extension will come with a NotificationService.swift. Open it and replace the content with the code below:

import UserNotifications
import FlyCall
import FlyXmpp
import FlyCore
import FlyCommon
import AVFoundation
import FlyDatabase
import AudioToolbox
import FlyUIKit
class NotificationService: UNNotificationServiceExtension {
let BASE_URL = "https://api-uikit-qa.contus.us/api/v1/"
let CONTAINER_ID = "group.com.mirrorfly.qa"
let LICENSE_KEY = "**********************"
let IS_LIVE = false
let APP_NAME = "UiKitQa"
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
try? ChatSDK.Builder.setAppGroupContainerID(containerID: CONTAINER_ID)
.isTrialLicense(isTrial: !IS_LIVE)
.setLicenseKey(key: LICENSE_KEY)
.setDomainBaseUrl(baseUrl: BASE_URL)
.buildAndInitialize()
if let bestAttemptContent = bestAttemptContent {
let payloadType = bestAttemptContent.userInfo["type"] as? String
if payloadType == "media_call" {
// Modify the notification content here...
bestAttemptContent.title = "\(bestAttemptContent.title) [modified]"
if let notificationContent = request.content.mutableCopy() as? UNMutableNotificationContent {
FlyUIKitSDK.shared.intializePushNotification(notificationContent, isVoipType: true) { attemptContent in
contentHandler(attemptContent)
}
}
}
}
}
override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}

Step 4 : Add App Groups to the target application and notification extension on the Signing & Capabilities tab.

Adding a Push Notification Capability#

To use push notifications, you are required to add the push notification capability to your Xcode project. Select your target and then choose Signing & Capabilities.

Enable all the below mentioned capabilities into your project.

Capabilities
App Groups
Background Modes
Push Notification

Now, go to the background mode and enable the below given modes

Background Modes
Voice over IP
Background Fetch
Remote Notification

Initialize Data for Call Push Notification#

In your project you must use the AppDelegate class within the didFinishLaunchingWithOptions method and also provide required data to build the Call Push Notification Builder. Let's have a look at the example given below.

import PushKit
clearPushNotifications()
registerForPushNotifications()
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: { val, error in
}
)
application.registerForRemoteNotifications()
ChatManager.setMediaEncryption(isEnable: false)
ChatManager.hideNotificationContent(hide: false)
FlyUtils.setAppName(appName: "APP_NAME")
VOIPManager.sharedInstance.updateDeviceToken()
let licenceKeyForEncryption = String(licenseKey.prefix(16))
FlyDefaults.profileIV = licenceKeyForEncryption

Add the method UNUserNotificationCenterDelegate and PKPushRegistryDelegate like below:

// MARK:- Push Notifications
@available(iOS 13.0, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
/// Register for APNS Notifications
func registerForPushNotifications() {
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { granted, error in
if granted {
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
self.registerForVOIPNotifications()
}
}
}
}
/// This method is used to clear notifications and badge count
func clearPushNotifications() {
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = deviceToken.map { String(format: "%.2hhx", $0) }.joined()
if token.count == 0 {
print("Push Status Credentials APNS:")
return;
}
print("#token appDelegate \(token)")
print("#token application DT => \(token)")
VOIPManager.sharedInstance.saveAPNSToken(token: token)
Utility.saveInPreference(key: "googleToken", value: token)
VOIPManager.sharedInstance.updateDeviceToken()
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Push didFailToRegisterForRemoteNotificationsWithError)")
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([])
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
print("Push userInfo \(userInfo)")
completionHandler(.noData)
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
guard let rootViewController = (UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.window?.rootViewController else {
completionHandler()
return
}
if let rootVC = rootViewController as? UINavigationController{
let callLogsVC = MFUICallLogViewController()
rootVC.pushViewController(callLogsVC, animated: false)
}
}
}
// MARK:- VOIP Notifications
@available(iOS 13.0, *)
extension AppDelegate : PKPushRegistryDelegate {
func registerForVOIPNotifications() {
let pushRegistry = PKPushRegistry(queue: .main)
pushRegistry.delegate = self
pushRegistry.desiredPushTypes = [.voIP]
}
func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) {
//print out the VoIP token. We will use this to test the nofications.
NSLog("VoIP Token: \(pushCredentials)")
let deviceTokenString = pushCredentials.token.reduce("") { $0 + String(format: "%02X", $1) }
print("#token pushRegistry VT => \(deviceTokenString)")
print(deviceTokenString)
VOIPManager.sharedInstance.saveVOIPToken(token: deviceTokenString)
Utility.saveInPreference(key: "voipToken", value: deviceTokenString)
VOIPManager.sharedInstance.updateDeviceToken()
}
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
NSLog("Push VOIP Received with Payload - %@",payload.dictionaryPayload)
print("#callopt \(FlyUtils.printTime()) pushRegistry voip received")
VOIPManager.sharedInstance.processPayload(payload.dictionaryPayload)
}
}