Signed Call iOS SDK

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

Overview

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

iOS Prerequisites

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

Setup

This section explains how to set up the Signed Call iOS SDK. Following is the setup required before you start integrating the Signed 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 Signed Call iOS SDK using Pods

To install the Signed Call iOS SDK:

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

target 'SignedCallDemo' do
  use_frameworks!
  pod 'CleverTap-SignedCall-SDK'

end

post_install do |installer|
    installer.pods_project.targets.each do |target|
        target.build_configurations.each do |config|
            config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
        end
   end
end
  1. Update your Podfile, and run pod install --repo-update in your terminal.
    For more details, refer to Pod setup.

Set Up Xcode Project

To set up your Xcode project, add the following capabilities to 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.
27822782
  1. Create the Privacy - Microphone Usage Description key of string type.
  2. Create the Privacy - Camera Usage Description key of string type.
    To know more, refer to Requesting Access to Protected Resources

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

Set Up Signing & Capabilities

Add the following capabilities from the Signing & Capabilities tab:

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

Set Up an Outgoing Tone

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

Configure Quick Launch Button on the 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) SCCallkitLogo.png is read from your app resources.

📘

Icon Image File Specifications

The icon image must be a square image with a side length of 40 points. The alpha channel of the image 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 Signed Call iOS SDK uses CleverTap SDK for analytics. Signed Call iOS SDK requires an active CleverTap instance as a parameter during the SDK initialization. If the CleverTap instance is unavailable, the Signed Call iOS SDK does not initialize and returns an error ERR_CLEVERTAP_URL_NOT_AVAILABLE.

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

📘

Minimum Supported Version

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

Integrate the Signed Call iOS SDK

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

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

The registerVoIP function expects the following parameters:

Parameter

Description

Type

Notes

rootView

The view controller on which the call screen displays.

UIViewController

Required

appName

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

String

Optional

  1. Initialize the Signed Call iOS SDK as follows:
SignedCall.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": "Signed Call Account Id",
    "apiKey": "Signed Call Api Key",
    "cuid" : "unique-cuid",
    "production": true/false
]

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. Available from the dashboard.

String

Required

apikey

Unique identity of the client's account. Available from the dashboard.

String

Required

cuid

Unique user ID of the person making a call.
Validation rules:

  • 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.

String

Required

production

Used to setup production/ development environment for VoIP push support.
Note: It must be true if you build an app for production and false if you build an app for development.

Boolean

Required

Make a Signed Call

Use the following code to make a Signed Call:

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

let callOptions = SCCallOptionsModel(context: String, receiverCuid: String, customMetaData: SCCustomMetadata)


SignedCall.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 Signed 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.
Note: It must include alphanumeric characters, and its length must not exceed 64 characters.

String

Required

customMetaData

It is a SCCustomMetadata object with the following properties:

  • receiverImage (string): URL that displays the receiver's image to the initiator of the call (optional).
  • initiatorImage (string): URL that displays the initiator's image to the receiver of the call. (optional)

SCCustomMetadata

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? SCCallStatus

    if message == SCCallStatus.CALL_DECLINED {
        //when the call is declined from the receiver's end
        
    } else if message == SCCallStatus.CALL_MISSED {
        //when the call is missed at the receiver's end
        
    } else if message == SCCallStatus.CALL_OVER {
        //when the call has been disconnected
        
    }
    else if message == SCCallStatus.CALL_ANSWERED {
        // when call is answered
        
    } else if message == SCCallStatus.RECEIVER_BUSY_ON_ANOTHER_CALL {
        //when the receiver is busy on another call
        
    } else if message ==
                SCCallStatus.ERR_MICROPHONE_PERMISSION_NOT_GRANTED {
        //this message is thrown if microphone permission is denied while receiving a 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.

SignedCall.hangup()

Override the Dashboard Branding for Call Screen

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 Signed Call iOS SDK, then all apps will share the branding you have set from the CleverTap dashboard.

To override the dashboard branding, use overrideDefaultBranding during the Signed Call iOS SDK initialization.

SignedCall.overrideDefaultBranding = SCCallScreenBranding(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).
Note: The .light theme represents the white color of the buttons, whereas the .dark is for black color.

ButtonTheme

Required

Logout the Signed Call iOS SDK

Add the following code to clear the 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.

SignedCall.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 SignedCallSDK 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 SignedCallSDK by calling the SignedCall.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_SIGNEDCALLSDK_NOT_INITIALIZED

Signed 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_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 Signed 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_INSTANCE_REQUIRED

CleverTap instance not available.

ERR_STOP_RETRY

Signed 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.

FAQs

Q. Is Signed Call accountId and apikey the same as CleverTap's accountId and token?

A. No. Signed Call accountId and apikey differ from CleverTap's accountId and token. You can find these details under your dashboard's Signed Call Settings.

Q. Why SignedCallSDK dependencies are not downloaded even after running the pod install?

A. As SignedCallSDK uses submodules performing pod repo update would help download and install required dependencies.

Q. What channels are used for call routing by Signed Call Android SDK?

A. Signed Call Android SDK uses an active socket connection as soon as the SDK is initialized. The socket connection is a primary routing channel to receive the calls, whereas FCM is a fallback channel in case the receiver is not connected to the socket channel. This socket connection processes the call requests raised to make a call. To know more, refer to the Best practices for initializing Signed Call SDKs.