Let's integrate our SDK in few minutes

Quick Start#
Download SDK Files

Call SDKs for iOS#

Make an easy and efficient way with CONTUS MirrorFly Call SDK for iOS - simply integrate the call features and functionalities into a client's app.

With client-side implementation, our call SDK lets you initialize and configure them easily. With the server-side, Our solution ensures the most reliable infra-management services for the calls within the app. Furthermore, we will let you know how to install the call SDK in your app for a better in-app call experience.

Note : To obtain a fastest way in action using CONTUS MirrorFly Call SDKs, you must try our trial app to enhance your Call app. So, just download our sample app and start with your app development. Click here to download the sample app.


The below are the requirements for call SDK for iOS,

  • Xcode 13 or later
  • iOS 12.1 or later
  • Swift 5.0 or later

Points to be Noted Before Making a Move#

SDK License Key#

Before proceeding with CONTUS MirrorFly Call SDK integration, there must be an SDK license key that needs to be obtained for your MirrorFly application.

This SDK must be authenticated by the MirrorFly server by making use of the license key for further processing.

To obtain your license key you need to follow the below steps:

Step 1: Signup into MirrorFly Console page (https://console.mirrorfly.com/register) to create a free MirrorFly account.

Step 2: You can provide your basic details like your name, organization details, work email, and contact number while creating an account

Step 3: Once you get into the account! You get access to navigate all the content on your MirrorFly account. Now, click on the ‘Overview page’ and get access to the license key and downloadable iOS SDK file to proceed further with integration process

Step 4: Copy license key under "Application info" in "Overview" page


Step 5: To download the frameworks, click on the ‘Download’ button, this will take you to the top of this guided documentation page. Here, click on the given ‘Download button’ and extract the frameworks from the ZIP folder

Step 6: After downloading the files, You have to create a new project to start with integration process to build your chat app for iOS

Integrate Call SDK#

Since the SDKs were compiled into multiple XCFramework binary packages you need to start with SDK integration. Thus, you have to follow the below given steps,

Step 1: First extract the xcframework files from the downloaded zip file that is provided at the top of this guided documentation. Once extracted you get the following xcframeworks.

  • FlyCall.xcframework
  • FlyCore.xcframework
  • FlyCommon.xcframework
  • FlyNetwork.xcframework
  • FlyDatabase.xcframework
  • FlyXmpp.xcframework
  • FlyTranslate.xcframework


Step 2: Add all the extracted xcframeworks to your project.

Goto Project -> Target -> General -> Frameworks,libraries and Embedded Content -> Select Embed & Sign for all the Chat SDK's xcframeworks


Step 3 : Now, disable the bitcodes for your project

Goto Project -> Build Settings -> Filter the term `Bitcode` -> and select No from the dropdown


Step 4: If you have not initiated any pods project before, then initiate the one. Now, add the required pods that are necessary for the SDK to execute the process perfectly.

pod 'libPhoneNumber-iOS'
pod 'Alamofire'
pod 'RealmSwift', '10.20.1'
pod 'XMPPFramework/Swift'
pod 'SocketRocket'
pod 'Socket.IO-Client-Swift'
pod 'GoogleWebRTC'

Step 5: Add the below given pod hook code block at the end of the pod file and thus, finally install the pods.

post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.1'
config.build_settings['ENABLE_BITCODE'] = 'NO'
config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = 'No'
config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'


Step 6: Now, enable all the below mentioned capabilities into your project.

Goto Project -> Target -> Signing & Capabilities -> Click + at the top left corner -> Search for the capabilities below
App Groups
Background Modes

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

Background Modes
Audio,Airplay, and Picture in Picture
Voice over IP
Background fetch
Remote notifications


Step 7: Enable Audio and Video record permisions.

Provide Microphone and Camera usage description in the plist file of your project.

Configure the SDK server & Data#

Now, configure the server details in SDK and access the data globally using the AppDelegate class.

let BASE_URL = "https://api-preprod-sandbox.mirrorfly.com/api/v1/"
let LICENSE_KEY = "xxxxxxxxxxxxxxxxxxxxxx"
let CONTAINER_ID = "group.com.mirrorfly.qa"

Initialize Data for Calls#

To start using the sdk, there are a few basic pieces of data that must be made available for the SDKs to function perfectly.

Thus, we utilize the usage of the ChatSDK builder class making the data available for SDKs. Furthermore, in your project you must use the AppDelegate class within the didFinishLaunchingWithOptions method and also provide required data to build the ChatSDK Builder. Let's have a look at the example given below.

try? ChatSDK.Builder.setAppGroupContainerID(containerID: CONTAINER_ID)
.setLicenseKey(key: LICENSE_KEY)
.isTrialLicense(isTrial: true)
.setDomainBaseUrl(baseUrl: BASE_URL)


Chat Builder Function Description#

FunctionParameter TypeDescription
setAppGroupContainerIDStringPass group container id of the project that stores UserDefaults and Database
setLicenseKeyStringUsed to proceed with Registration
isTrialLicenseBoolIf the obtained license key is a trial license key - display the message as true else false
setDomainBaseUrlStringUrl required to make API calls
buildAndInitializen/aInitialize the chat configuration

The base url must have Http/Https protocol which should be closed with a slash (/), or else will display an exception bug message.


The below method should be called to register a new user. This method will take care of both Sandbox mode registration as well as Live mode registration based on isTrialLicense provided in the ChatSDK.Builder class.


Unless you logged out of a session, make sure that you have called the Registration method only once in an application

Note: If the below registerApiService methods are available at the time of registration then can be passed across for further processing wherein, can be accepted as an optional param.

try! ChatManager.registerApiService(for: USER_IDENTIFIER ) { isSuccess, flyError, flyData in
var data = flyData
if isSuccess {
// This is your Password
guard let password = data["password"] as? String else{
// This is your Username
guard let username = data["username"] as? String else{
let error = data.getMessage()
print("#chatSDK \(error)")
USER_IDENTIFIERStringUnique Id to Register the User
APNS_DEVICE_TOKENStringToken to register APNS device (optional)
VOIP_DEVICE_TOKENStringToken to register VoIP device (optional)
IS_EXPORTBoolWhen API is export, the text will be displayed as true else false
CALLBACKFlyCompletionHanlderFlyCompletionHanlder is implemented and expressed as lambda expression for easy reading

To know more about FlyCompletionHanlder click here

Initialize Call SDK#

After successful registration, call the below method to initialize the Call SDK.

try! CallManager.initCallSDK()

Also call the above method in the AppDelegate's didFinishLaunchingWithOptions with a condition of isLoggedin or isUserId available logic based on your app.

Connect to the Chat Server#

In order to transfer the initial call data payload, we can make use of Chat server for that you have to establish a connection to the chat server using the below given method.


Disconnect Chat Server#

Use the below given method to disconnect from the chat server call.


Observe Connection Events#

The connection status can be observed and tracked by confirming the ConnectionEventDelegate. To do that you need to set ‘delegate’ in your ViewController's viewDidAppear method like below.

ChatManager.shared.connectionDelegate = self

Once the ConnectionEventDelegate has been set, you will be able to receive the connection status in the delegate method as mentioned below. Learn more about this method @ ConnectionEventDelegate.

func onConnected() {
// Navigate to Conversation screen


The below given are some of the common keyword/terminologies used in the Chat SDK with description

userID/userBareIDUnique ID assigned for each user Ex: 12345678 (any alphanumeric). The below characters is not allowed in userId: U+0022 (") U+0026 (&) U+0027 (') U+002F (/) U+003A (:) U+003C (<) U+003E (>) U+0040 (@) userID should follow below specification: https://xmpp.org/extensions/xep-0106.html
userJid (or) JIDuserID+@+domain of the chat server Ex. 12345678@xmpp.chatsystem.dev.contus.us
groupID/groupBareIDUnique ID assigned for each group Ex: group123456 (any alphanumeric). GroupJID = groupID +@mix.+domain of the chat server Ex: group123456@mix.xmpp.mirrorfly.dev.contus.us`

SDK here provides the built-in functions to prepare the JID and Group JID.

Observe Call Events#

To observe Call events create and set a Singleton Class that conforms to the CallManagerDelegate of FlyCall framework, and pass that object to the below method.

CallManager.setCallEventsDelegate(delegate: CALLMANAGER_DELEGATE)

Setup Call UI#

To set the Call UI that has to be presented during an outgoing call, call the below method. An instantiated view controller object has to be passed in the method.

CALL_VIEW_CONTROLLERUIViewControllerA class that conforms to UIViewController

Presenting the call UI#

Call SDK handles the UI presentation for an outgoing call. Call the below method after declaring the Call SDK and or before making a call.The below method sets the view on top of which the call ui will be presented.

VIEW_TO_PRESENTViewController in which Call UI has to be presented.

Setting the CallManager.setViewToPresentController is optional else the Call SDK will present the UI for an outgoing call in the project's root viewcontroller.

Make a Voice Call#

To make a one to one voice call, call the below method.

CallManager.makeVoiceCall(USER_ID) { [weak self] (isSuccess , message) in
if isSuccess {
// SDK will take care of presenting the Call UI. It will present the ViewController that is passed using the method `CallManager.setCallViewController()`
USER_IDStringUnique Id/userId/Jid of another registered user

To make and receive a voice/video call, Microphone and Camera usage permissions were required. Call SDK also provides method to check those permissions like CallManager.isAudioCallPermissionsGranted() and CallManager.isVideoCallPermissionsGranted(). We can also make use of these methods too.


If one to one call feature unavailable for your plan then it will throw 403 exception.

Receive a call#

Call SDK will take care of receiving and processing the received call payload and triggering the CallKit if you are connected to the server in foreground state. Once the CallKit is being presented with Accept/Reject Call buttons, we can either choose to attend or reject the call. If we attend the call the below method of the CallManagerDelegate will be triggered, and the status wil be of the case ATTENDED. Inside that method we can present the incoming call UI.

func onCallStatusUpdated(callStatus: CALLSTATUS, userId: USER_ID) {
CALLSTATUSCALLSTATUS enumAn enum class defines the current status of the call
USER_IDStringFor this CALLSTATUS our own userId will be returned from SDK

To know more about the CallManagerDelegate protocol and its delegate methods visit here

Push and Voip Notifications#

To receive calls in the background and in killed state, kindly register for remote as well for voip notification by conforming to the following delegates in the AppDelegate UNUserNotificationCenterDelegate PKPushRegistryDelegate. Call the below methods when an APNS token or VOIP token gets updated.

// APNS Token Update
VOIPManager.sharedInstance.saveAPNSToken(token: token)
//VOIP Token Update
VOIPManager.sharedInstance.saveVOIPToken(token: deviceTokenString)
TOKENApns or Voip Token

In class that extends the UNNotificationServiceExtension after validating whether the received payload is for call or not, call the below method to process the call further.

NotificationExtensionSupport.shared.didReceiveNotificationRequest("NOTIFICATION_CONTENT", "COMPLETION_BLOCK")
NOTIFICATION_CONTENTUNMutableNotificationContentNotification request content
COMPLETION_BLOCK(UNMutableNotificationContent?) -> VoidCompletion Block

Send the payload received through VOIP from the method didReceiveIncomingPushWith to the method below to process the call further.

PAYLOADPayload Dictionary