Let's integrate Flutter Video & Call SDK

Quick Start#

Audio/Video Call SDKs for Flutter#

With CONTUS MirrorFly Call SDK for Flutter, 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 Plugin, you can use our sample apps. To get our sample apps, click here

Integrate Call SDK#


The requirements for Android

  • Android Lollipop 5.0 (API Level 21) or above
  • Java 7 or higher
  • Gradle 4.1.0 or higher
  • targetSdkVersion,compileSdk 34 or above.

The minimum requirements for iOS

  • iOS 12.1 or later

Things To Be Noted Before You Get Started#

SDK License Key#


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: Sign up for a MirrorFly Account

Step 2: Log into your Account

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


Getting Started#

Create Android dependency#

Step 4: Add the following to your root build.gradle file in your Android folder.

allprojects {
repositories {
maven {
url "https://repo.mirrorfly.com/release"

make sure below attributes are included in the app/build.gradle file in your Android folder.

android {
compileSdk 34 // or higher
defaultConfig {
minSdkVersion 21
targetSdkVersion 34 // or higher

Create iOS dependency#

Step 5: Check and Add the following code at end of your ios/Podfile

post_install do |installer|
installer.aggregate_targets.each do |target|
target.xcconfigs.each do |variant, xcconfig|
xcconfig_path = target.client_root + target.xcconfig_relative_path(variant)
IO.write(xcconfig_path, IO.read(xcconfig_path).gsub("DT_TOOLCHAIN_DIR", "TOOLCHAIN_DIR"))
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'
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = 'arm64'
shell_script_path = "Pods/Target Support Files/#{target.name}/#{target.name}-frameworks.sh"
if File::exist?(shell_script_path)
shell_script_input_lines = File.readlines(shell_script_path)
shell_script_output_lines = shell_script_input_lines.map { |line| line.sub("source=\"$(readlink \"${source}\")\"", "source=\"$(readlink -f \"${source}\")\"") }
File.open(shell_script_path, 'w') do |f|
shell_script_output_lines.each do |line|
f.write line

Step 6 : Now, disable the bitcode for your project

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


Step 7: 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 |


Create Flutter dependency#

Step 8: Add the below dependencies in pubspec.yaml.

mirrorfly_plugin: ^1.0.0

STEP 9: Run flutter pub get command in your project directory. You can use all classes and methods just with the following import statement

import 'package:mirrorfly_plugin/mirrorfly.dart';

Initialize MirrorFly Plugin#

To initialize the plugin, place the below code in your main.dart file inside main function before runApp().

void main() {
licenseKey: LICENSE_KEY,
flyCallback: (FlyResponse response) {
runApp(const MyApp());

Chat init Function Description#

FunctionParameter TypeDescription
licenseKeyStringLicense key is required to proceed with registration
iOSContainerIDStringCreate App groups and assign the obtained group container id. Plugin uses this string to create the path for the local storage.

The base URL must have the Http/Https protocol which must be closed with a ‘slash (/)’, if not an exception - a bug message will pop up.


Use the below method to login a user in sandbox Live mode.

Unless you log out the session, make a note that should never call the login method more than once in an application

Note: While registration, the below login method will accept the FCM_TOKEN as an optional param and pass it across. The connection will be established automatically upon completion of registration and not required for seperate login.

Mirrorfly.login(userIdentifier: userIdentifier,
fcmToken: token,
isForceRegister: isForceRegister,
flyCallback: (FlyResponse response) {
if(response.isSuccess && response.hasData){
// you will get the user registration response
var userData = registerModelFromJson(value);
userIdentifierStringA unique Id to Register the User. We accept only the AlphaNumeric String
tokenStringA registration token that is generated by FCM Plugin for the user's app instance to send message for free
isForceRegisterBooleandefault value true, provide true to force the logout of the old session if the login user has reached the maximum no of multi-sessions or provide false to allow registration till the maximum no of multi-sessions
flyCallbackFlyResponsecallback to observe the action status

Note : After login, make sure to update the profile of the login user Update Profile.

Note : You need to re-login when the onLoggedOut event is triggered.

Note : It is recommended to disallow users to backup an app if it contains sensitive data. Having access to backup files (i.e. when android:allowBackup="true"), it is possible to modify/read the content of an app even on a non-rooted device.


If 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 FORCE_REGISTER should be true or one of the existing session need to be logged out to continue registration.


Some of the most common terminologies used in MirrorFly Plugin with description

userID/userBareIDUnique Id to Register the User. User identifiers can only contain lowercase alphanumeric characters, (-) hyphens, and (_) underscores.
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`
Plugin will have built-in functions to prepare the JID, Group JID, and more.

To make and receive a voice/video call, Microphone and Camera usage permissions were required. Make Sure those permissions are granted


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

From Android 12, ensure that android.permission.BLUETOOTH_CONNECT and android.permission.READ_PHONE_STATE runtime permissions are granted for your app for seameless audio routing and gsm call handling. If the android.permission.BLUETOOTH_CONNECTpermission is not granted, call audio will not be routed to BT Headset even though it is connected. If the android.permission.READ_PHONE_STATE permission is not granted, gsm call related functionalities will not work in sdk.

Note: From Android 13, CallSDK need below permission to show ongoing call notification.


Make a Voice Call#

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

Mirrorfly.makeVoiceCall(toUserJid: USER_JID, flyCallBack: (FlyResponse response) {
if (response.isSuccess) {
USER_JIDStringJid of another registered user
flyCallbackFlyResponsecallback to observe the action status

Receive a call#

Call SDK will take care of receiving and processing the received call payload and triggering the CallKit for iOS and Incoming Call Intent for Android is presented, if you are connected to the server in foreground state. Once the Call 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 event listener onCallStatusUpdated will be triggered, and the status will be of the case Attended.

Mirrorfly.onCallStatusUpdated.listen((event) {
var statusUpdateReceived = jsonDecode(event);
var callMode = statusUpdateReceived["callMode"].toString();
var userJid = statusUpdateReceived["userJid"].toString();
var callType = statusUpdateReceived["callType"].toString();
var callStatus = statusUpdateReceived["callStatus"].toString();
callModeStringFor this callMode OneToOne or groupCall will be returned from SDK
userJidStringFor this userJID will be returned from SDK
callTypeStringFor this callType Video or Audio will be returned from SDK
callStatusCallStatusAn enum class defines the current status of the call