Let's integrate our SDK in few minutes

Quick Start#

Audio/Video Call SDKs for iOS#

With CONTUS MirrorFly Call SDK for iOS, you can easily add real-time call features to your client app within 30 minutes.

Through our client SDK, you can initialize and configure chat into your app with minimal efforts.

Note : If you're looking for the fastest way to build your app’s UI with MirrorFly Chat SDKs, you can use our sample apps. To get our sample apps, click here

Integrate Call SDK#

Requirements#

The below are the requirements for call SDK for iOS,

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

Things To Be Noted Before You Get Started#

SDK License Key#

caution

Skip this step if you are already having your license key.

To integrate MirrorFly Call SDK into your app, you will need a SDK License Key. The MirrorFly server will use this license key to authenticate the SDK in your application.

To get the License Key,#

Step 1: Register here to get a MirrorFly User account. Registration is subject to verification and would take up to 24 hours.

Step 2: Login to your Account

Step 3: Get the License key from the application Info’ section

Step 4: Download the iOS SDK

license-key

Getting Started#

Step 1: Add the following ChatSDK pod to your Podfile. If pod hasn't been initialised yet means, create a Podfile by executing pod init command.

pod 'MirrorFlySDK', '5.13.3'

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

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['EXCLUDED_ARCHS[sdk=iphonesimulators*]'] = 'arm64'
config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
end
end
end

Step 3 : Now, disable the bitcode for your project

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

Bitcode

Step 4: 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
Capabilities
Background Modes

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

Background Modes
Voice over IP

Capabilities-voip

Step 5: 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 LICENSE_KEY = "xxxxxxxxxxxxxxxxxxxxxx"
let CONTAINER_ID = "xxxxxxxxxxxxxxxxxxxxxx"

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 initializeSDK function to validate the license key and to fetch critical data from server for SDK initialization. Furthermore, in your project you must use the AppDelegate class within the didFinishLaunchingWithOptions method call the initialization method by passing the license key. Let's have a look at the example given below.

    ChatManager.initializeSDK(licenseKey: LICENSE_KEY) { isSuccess, flyError, flyData in }

    AppDelegate

    ArgumentTypeDescription
    LICENSE_KEYStringUsed to proceed with Registration
    CALLBACKFlyCompletionHandlerFlyCompletionHandler is implemented and expressed as lambda expression

    Registration#

    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.

    info

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

    Note: While registration, the below registerApiService method will accept the additional params required for notification processing on server and IS_FORCE_REGISTER as an optional param for maintaining sessions, USER_TYPE as an optional param to provide type of user and META_DATA as an optional param to provide MetaData of user.

      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{
      return
      }
      // This is your Username
      guard let username = data["username"] as? String else{
      return
      }
      // This is your JID
      guard let username = data["userJid"] as? String else{
      return
      }
      }else{
      let error = data.getMessage()
      print("#chatSDK \(error)")
      }
      }
      ArgumentTypeDescription
      USER_IDENTIFIERStringUnique Id to Register the User. User identifiers can only contain lowercase alphanumeric characters, hyphens (-), and underscores (_).
      APNS_DEVICE_TOKENStringToken to register APNS device (optional)
      VOIP_DEVICE_TOKENStringToken to register VoIP device (optional)
      IS_EXPORTBooltrue for production(apns certificate) builds and false for sandbox(apns certificate)builds
      IS_FORCE_REGISTERBooldefault value true provide true to force the logout of the old session If the registered user has reached the maximum no of multi-sessions or provide false to allow registration till the maximum no of multi-sessions
      USER_TYPEStringType of the user (optional)
      META_DATA[MetaData]list of key - value pair of metadata object. Maximum size is 3 (optional)
      CALLBACKFlyCompletionHanlderFlyCompletionHanlder is implemented and expressed as lambda expression for easy reading

      To know more about FlyCompletionHanlder click here

      caution

      If IS_FORCE_REGISTER is false, and it reached the maximum no of multi-sessions then registration will not succeed it will throw a 405 exception, Either IS_FORCE_REGISTER should be true or one of the existing session need to be logged out to continue registration.

      Initialize Call SDK#

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

        try! CallManager.initCallSDK()
        info

        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.Once Registration was successful, ChatSDK automatically attempts to connect to the Chat Server and ChatSDK also observe the changes in application state, and accordingly it will try to connect and disconnect the Chat Server.

        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.

            func onConnected() {
            // Navigate to Conversation screen
            }

            To know more about ConnectionEventDelegate visit ConnectionEvent Delegate

            Terminology#

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

            KeywordDescription
            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`
            info

            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)
              ArgumentType
              CALLMANAGER_DELEGATECallManagerDelegate

              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.

                CallManager.setCallViewController(CALL_VIEW_CONTROLLER)
                ArgumentTypeDescription
                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.

                  CallManager.setViewToPresentController("VIEW_TO_PRESENT")
                  ArgumentDescription
                  VIEW_TO_PRESENTViewController in which Call UI has to be presented.
                  info

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

                  Preparing user jid#

                  Almost all the sdk methods expect jid as a input parameter, so sdk provides below utility method to prepare the jid. The method prepares the user's jid from the username which we get in the Register response.

                  Note: The below characters is not allowed in uniqueId: U+0022 (") U+0026 (&) U+0027 (') U+002F (/) U+003A (:) U+003C (<) U+003E (>) U+0040 (@).

                  ArgumentTypeDescription
                  USER_NAMEStringunique username for preparing JID
                    try? FlyUtils.getJid(USER_NAME)

                    Make a Voice Call#

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

                      CallManager.makeVoiceCall(USER_JID) { [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()`
                      }
                      }
                      ArgumentTypeDescription
                      USER_JIDStringJid of another registered user
                      caution

                      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.

                      caution

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

                      Transfer Initial Call Payload#

                      Since we are making use of Chat Server to transfer initial call payload from caller to callee. Once the above make call function was processed successfully. The following delegate method of CallManagerDelegate will be triggered. There we can make use of the ChatSDK method to send the initial calling payload to the callee.

                        func sendCallMessage( groupCallDetails : GroupCallDetails , users: [String], invitedUsers: [String]) {
                        try? FlyMessenger.sendCallMessage(for: groupCallDetails, users : users , inviteUsers: invitedUsers) { isSuccess, flyError, flyData in
                        var data = flyData
                        if isSuccess {
                        print(data.getMessage() as? String ?? "")
                        } else{
                        print(data.getMessage() as! String)
                        }
                        }
                        }

                        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) {
                          ArgumentTypeDescription
                          CALLSTATUSCALLSTATUS enumAn enum class defines the current status of the call
                          USER_IDStringFor this CALLSTATUS our own userId will be returned from SDK
                          info

                          To know more about the CallManagerDelegate protocol and its delegate methods visit here.
                          To receive calls in the background and in killed state, kindly register for voip notification to know more kindly refer here