Direct Call iOS SDK

Learn how to integrate Direct Call iOS SDK in your app to avail the Direct Call feature.

Overview

CleverTap provides in-app calls via its Direct Call iOS SDK, which means you can make and receive calls in any iOS app if the device has an internet connection and Direct Call iOS SDK. This section shows you how to set up and integrate the Direct Call iOS SDK and manage calls. To know more about the Direct Call feature, refer to Direct Call.

iOS Prerequisites

The Direct Call framework is built using Swift-5 in Xcode v13.4.1. To support CallKit, the target iOS version for deployment must be greater than or equal to iOS 10. You can test Direct Call on both, devices and simulators.

Setup

This section explains how to set up the Direct Call iOS SDK. Following is the setup required before you start integrating the Direct Call iOS SDK:

Enable VoIP Push

The following is a list of required details to enable your infrastructure with VoIP push:

  • Team ID
  • Bundle ID
  • Authkey .p8 file
  • .p12 VoIP certificate
  • .pem VoIP certificate
  • Key ID

To know more, refer to VoIP APNs Setup.

Install Direct Call iOS SDK using CocoaPod

To install the Direct Call iOS SDK:

  1. Add the pod spec repo as a source and the CleverTap-DirectCall-SDK pod to your Podfile as shown below:
source 'https://github.com/CleverTap/podspecs.git'
source 'https://github.com/CocoaPods/Specs.git'

platform :ios, '10.0'

target 'SampleProject' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for SampleProject

  pod 'CleverTap-DirectCall-SDK'

end
  1. After you have updated your Podfile, run pod install in your terminal.

Set Up Xcode Project

To set up your Xcode project, add the following capabilities in your project:

Add Permissions

To add permissions in your app's Info.plist file:

  1. Navigate to the Info.plist file from your project navigator.
28782878
  1. Create a key called Privacy - Microphone Usage Description with a type string.
  2. Create a key called Privacy - Camera Usage Description with a type string.

Disable Bitcode

To disable bitcode from your build settings:

  1. Click the Build Setting tab.
  2. Search Enable Bitcode.
  3. Select No to disable it.
23362336

Signing & Capabilities

From the Signing & Capabilities tab, add the following capabilities:

  • Add Push Notifications capability.
  • Select the following modes under the Background Modes capability:
    • Audio, Airplay, and Picture in Picture
    • Voice over IP
19421942

Set an Outgoing Tone

Add the .mp3 file named outgoing_tone to your project to set an outgoing tone. This file plays a dialing sound when the user makes a call.

Configure Quick Launch Button on CallKit Screen

The CallKit function adds a quick launch button on the call screen for your application, which helps switch between the app and the native CallKit screen. The icon file (white mask) DCCallkitLogo.png is read from your app resources.

📘

Icon Image File Specifications

The icon image must be a square with a side length of 40 points. The image's alpha channel creates a white mask image used in the native CallKit screen UI for the button, which helps switch between the native CallKit screen and the app calling screen.

Integrate CleverTap iOS SDK

The Direct Call iOS SDK uses CleverTap SDK for analytics. For that, Direct Call iOS SDK requires an active CleverTap instance as a parameter during the SDK initialization. If the CleverTap instance is unavailable, the Direct Call iOS SDK does not initialize and returns an error ERR_CLEVERTAP_URL_NOT_AVAILABLED.

To integrate the CleverTap iOS SDK, refer to the CleverTap iOS Integration Guide.

📘

Minimum Supported Version

The Direct Call iOS SDK requires a CleverTap SDK version of v4.1.0 or higher.

Integrate the Direct Call iOS SDK

After the CleverTap iOS SDK is integrated, register and initialize your app with the DirectCallSDK framework:

  1. Open your AppDelegate file and import both, CleverTap and Direct Call SDKs:
import CleverTapSDK
import DirectCallSDK
  1. Enable DirectCall logging as follows:
DirectCall.isLoggingEnabled = true
  1. In your AppDelegate file, call the registerVoIP function to generate a VoIP token and set pushRegistryDelegate.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        CleverTap.setDebugLevel(CleverTapLogLevel.off.rawValue)
        CleverTap.autoIntegrate()
        DirectCall.isLoggingEnabled = true
        DirectCall.cleverTapInstance = CleverTap.sharedInstance()
        
        guard let rootView = self.window?.rootViewController else {
            return true
        }
        DirectCall.registerVoIP(withRootView: rootView, appName: "Sample app")
        
        return true
    }
DirectCall.isLoggingEnabled = true

The resterVoIP function expects the following parameters:

Parameter

Description

Type

Notes

rootView

The view controller on which the call screen displays.

UIViewController

Required

appName

The name you want to display on the CallKit incoming screen.

String

Optional

  1. Initialize the Direct Call iOS SDK as follows:
DirectCall.initSDK(withInitOptions: initOptions) { result in
            switch result {
            case .success(let success):
                print("SDK Initialized! \(success)")
                //Handle success scenario
                
            case .failure(let error):
                print("SDK initialization failed \(error)")
                //Handle failure scenario
            }
        }

The syntax for the parameters of initOptions is as follows:

let initOptions: [String: Any] = [
                    "accountID": "Direct Call Account Id",
                    "apikey": "Direct Call Api Key",
                    "production": true/false,
                    "cuid" : "unique-cuid"
                ]

The initOptions in the function call expects a dictionary with the following parameters:

Parameter

Description

Type

Notes

accountID

Unique identity of the client's account.

String

  • Required
  • Available from the dashboard.

apikey

Unique identity of the client's account.

String

  • Required
  • Available from the dashboard.

cuid

Unique user ID of the person making a call.

String

  • Required
  • The cuid must range between 5 and 50 characters.
  • The cuid is case sensitive, and only '_' is allowed as a special character.
  • The cuid parameter cannot be of the number-number type, that is, a number followed by another number separated with a special character. For example, org_25 is allowed, but 91_8899555 is not allowed.
  • You must use a unique cuid for every device.

production

Used to setup production/ development environment for VoIP push support.

Boolean

  • Required
  • It must be true if you build an app for production and false if you build an app for development.

Make a Direct Call

Use the following code to make a Direct Call:

let customMetaData = DCCustomMetadata(initiatorImage: String, receiverImage: String)

let callOptions = DCCallOptionsModel(context: String, cuid: String, customMetaData: DCCustomMetadata)


DirectCall.call(callOptions: callOptions) { result in
            switch result {
            case .success(let success):
                //Handle call initiated
                
            case .failure(let error):
                //Handle call failure
            }
        }

The parameters to make a Direct Call are as follows:

Parameter

Description

Type

Notes

cuid

It is the receiver's cuid.

String

Required

context

It specifies the context of the call. For example, Delivery Partner is calling, Driver is calling, Agent is calling, and so on.

String

  • Required
  • It must include alphanumeric characters, and its length must not exceed 64 characters.

customMetaData

It is a DCCustomMedtadata object with the following properties:

  • receiver_image (string)
  • initiator_image (string)

DCCustomMedtadata

  • Optional
  • receiver_image is a URL that displays the receiver's image to the initiator of the call. (optional)
  • initiator_image is a URL that displays the initiator's image to the receiver of the call. (optional)

Call Events Handling

Add the following code inside the viewDidLoad() of your View Controller to monitor call events:

NotificationCenter.default.addObserver(self, selector: #selector(self.callStatus(notification:)), name: NSNotification.Name(rawValue: "MessageReceived"), object: nil)

Following is an example of creating a function to handle call events:

@objc func callStatus(notification: Notification) {
    let message = notification.object as? DirectCallStatus
    if let _ = notification.userInfo?["networkLatency"] as? Int {
        // gives the realtime latency of your network during a call
    }
    if message == DirectCallStatus.CALL_DECLINED {
        //when the call is declined from the receiver's end
        
    } else if message == DirectCallStatus.CALL_MISSED {
        //when the call is missed at the receiver's end
        
    } else if message == DirectCallStatus.CALL_OVER {
        //when the call has been disconnected
        
    }
    else if message == DirectCallStatus.CALL_ANSWERED {
        // when call is answered
        
    } else if message == DirectCallStatus.RECEIVER_BUSY_ON_ANOTHER_CALL {
        //when the receiver is busy on another call
        
    } else if message ==
                DirectCallStatus.ERR_MICROPHONE_PERMISSION_NOT_GRANTED {
        //this message is thrown if microphone permission is denied while receiving a call.
    }
}

Call Button Handling

Before initiating the call, always check whether the Direct Call services are enabled or not using the isEnabled property.

guard DirectCall.isEnabled else {
  //handle SDK not initialised
  return
}
//handle make call

Call Hangup Functionality

The hangup function ends a call for both parties programmatically. For example, if there is a metered call and the business wants to end the call after a specific duration, then they must maintain a timer in the app and call the hangup function at the appropriate time.

DirectCall.hangup()

Override the Dashboard's Call Screen Branding

CleverTap dashboard provides a branding tool to alter the look and feel of the call screens. If you have multiple apps to integrate with the Direct Call iOS SDK, then all apps will share the same branding that you have set from the CleverTap dashboard.
To override the dashboard branding, use overrideDefaultBranding during the Direct Call iOS SDK initialization.

DirectCall.overrideDefaultBranding = DCCallScreenBranding(bgColor: "bgColor", fontColor: "fontColor", logo: "logoUrl", buttonTheme: ButtonTheme)

The parameters to override the dashboard's call screen branding are as follows:

Parameter

Description

Type

Notes

bgColor

Hex color code for the background of the call screens. For example, #000000.

String

Required

fontColor

Hex color code for the text displayed on the call screens. For example, #ffffff.

String

Required

logo

The HTTPS URL of the image that renders in the call screens.

Sting

Required

buttonTheme

The theme for the control buttons of the call screen (Mute, Speaker, and Bluetooth).

ButtonTheme

  • Required
  • The .light theme represents the white color of the buttons, whereas the .dark is for black color.

Logout the Direct Call iOS SDK

Add the following code to clear the user session after a user logs out from the app. It ends all the connections, and to make a new call, you must repeat the Initialization and Authentication steps.

DirectCall.logout()

Exceptions

From iOS 13, Apple now mandates that all VoIP push notifications must be reported to the CallKit framework as a new call. If a VoIP push notification is not reported to CallKit within the required time window, iOS terminates the app. If VoIP push notifications are not reported to CallKit repeatedly, Apple ultimately stops delivering VoIP push notifications to the app. The end user needs to reinstall the app to get VoIP push notifications again.
Due to this, the DirectCallSDK demonstrates the following two expected behaviors in iOS:

  • If the receiver is busy in an ongoing VoIP call, then making another VoIP call to the same receiver reports an incoming dummy call to CallKit and ends it instantly but does not affect the previous, ongoing call.
  • If the user has logged out from the active session maintained by DirectCallSDK by calling the DirectCall.logout(), then making a call to the same cuid opens up the CallKit screen and ends it on the next tick as an invalid call.

To know more, refer to Apple pushRegistry

Errors

The following table lists the different errors and their probable causes:

Error

Description

ERR_NETWORK_NOT_AVAILABLE

No internet connection.

ERR_DIRECTCALL_SDK_NOT_INITIALIZED

Direct Call iOS SDK is not initialized.

ERR_MICROPHONE_PERMISSION_NOT_GRANTED

Microphone permission not granted.

ERR_CONTACT_NOT_REACHABLE

The receiver is not reachable.

ERR_SERVER_FAILURE

The server is not reachable.

ERR_INVALID_CUID

Invalid cuid.

ERR_CUID_ALREADY_CONNECTED_ELSEWHERE

The cuid is connected to another device.

ERR_SOMETHING_WENT_WRONG

Failure while calling.

ERR_VOIP_SERVICE_FAILED_TO_REGISTER

The VoIP service failed to register.

ERR_CUID_MISSING

The cuid is missing.

ERR_CONTACT_REGISTRATION_FAILED

Contact registration failed.

ERR_ACCOUNTID_REQUIRED

The Direct Call Account ID is required.

ERR_APIKEY_REQUIRED

The API key is required.

ERR_INVALID_LENGTH_CUID

The cuid length must be in the range of 5-50.

ERR_PRODUCTION_FIELD_REQUIRED

The Production key is missing.

ERR_CLEVERTAP_DETAILS_NOT_FOUND

CleverTap details are missing.

ERR_STOP_RETRY

Direct Call iOS SDK initialization failed.

ERR_FAILURE_IN_MAKE_CALL

Failure while making a call.

ERR_CALL_CONTEXT_INVALID

The characters are not alphanumeric, or the length is more than 64 characters.

ERR_CAN_NOT_CALL_SELF

The receiver's and initiator's cuid cannot be the same.

ERR_CLEVERTAP_URL_NOT_AVAILABLE

The CleverTap iOS SDK's base URL was not found.

ERR_NETWORK_LATENCY

Network latency.

FAQ

Q. Is Direct Call accountId and apikey the same as CleverTap's accountId and token?
A. No. Direct Call accountId and apikey are different from CleverTap's accountId and token. You can find these details under your dashboard's Direct Call Settings.