DEV Community

Alexander Samuel
Alexander Samuel

Posted on

How to add Flutter In-app Chat to your app? (10 mins)

Image description
In this tutorial, you’ll learn how to add Fluttter in-app communication to your app in just 10 minutes. Let it be any size of app and deployed on any platform. You can easily add MirrorFly in-app chat, voice, and video SDKs by following the simple protocols in this tutorial.

Flutter is the most popular cross-platform framework currently being used by more than `46% of developers across the world. Make your Flutter app more engaging with in-app communication SDKs.

Let’s be clear about all the things covered in this blog

  1. Prerequisites
  2. Getting started with MirrorFly account
  3. Initializing and Installing the SDKs
  4. Integrating chat and call SDKs with your Flutter app
  5. Integrating additional features

Prerequisites

  • Android Lolipop 5.0 (API level 21) or above
  • Java 7 or higher
  • Gradle 4.1.0 or higher
  • iOS 12.1 or later
  • Xcode 14.1 or later
  • Swift 5.0 or later

Getting started

Integrate Chat SDKs

Initially, you need a MirrorFly account to start with the integration steps. Follow the below method
Step 1: Go to MirrorFly console page and create your account
Step 2: Complete the setup of your account
Step 3: Acquire MirrorFly license key from the overview page

Step 1: Create Android Dependency
In your Android folder, add the following to your root build.gradle
allprojects {
repositories {
google()
mavenCentral()
jcenter()
maven {
url "https://repo.mirrorfly.com/snapshot/"
}
}
}

Now add the following dependencies in the app/build.gradle file
android {
packagingOptions {
exclude 'META-INF/AL2.0'
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/license.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/notice.txt'
exclude 'META-INF/ASL2.0'
exclude 'META-INF/LGPL2.1'
exclude("META-INF/*.kotlin_module")
}
}

Step 2: Create iOS Dependency
Add the following code in the end of your ios/podfile
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(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"
end
end
end

Now, enable all the below mentioned capabilities in your project.
Goto Project -> Target -> Signing & Capabilities -> Click + at the top left corner -> Search for the capabilities below

Step 3: Create Flutter Dependency
In your pubspec.yaml, add the below dependencies
dependencies:
mirrorfly_plugin: ^0.0.12

Now, run flutter pub get command in your project library. You can also use all classes and methods with the following statement.
import 'package:mirrorfly_plugin/mirrorfly.dart';

Step 4: Initialize MirrorFly Plugin
In order to initalize the plugin, place the below code in your main.dart file - inside the main function - before runApp().
void main() {
WidgetsFlutterBinding.ensureInitialized();
Mirrorfly.init(
baseUrl: 'https://api-preprod-sandbox.mirrorfly.com/api/v1/',
licenseKey: 'Your_Mirrorfly_Licence_Key',
iOSContainerID: 'Your_iOS_app_Group_id');
runApp(const MyApp());
}

Step 5: Register a User

To register a user, follow the below method.
Mirrorfly.registerUser(userIdentifier).then((value) {
// you will get the user registration response
var userData = registerModelFromJson(value);
}).catchError((error) {
// Register user failed print throwable to find the exception details.
debugPrint(error.message);
});

Note: During registration, the above registerUser method will accept the FCM_TOKEN as an optional parameter and pass it across. The connection will be established automatically upon completion of registration and is not required for separate logins.

Step 6: Send a One-to-one Message

Call the below method to to start sending message to another user

Note: To generate unique user JID by username call the below method
var userJid = await Mirrorfly.getJid(username);
Mirrorfly.sendTextMessage(message, jid).then((value) {
// you will get the message sent success response
var chatMessage = sendMessageModelFromJson(value);
});

Step 7: Receive a One-to-one Message

Use the callbackListeners method to receive a message from another user. This function will be triggered every time a user receives a message.
Mirrorfly.onMessageReceived.listen(result){
// you will get the new messages
var chatMessage = sendMessageModelFromJson(result)
}

Integrate Call SDKs

To integrate call SDKs with your Flutter app, repeat the similar steps from Step 1 - Step 5 with a minor change in Step 2: Creating iOS Dependencies.

Creating iOS Dependency

Add the following code at the end of your ios/podfile
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(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"
end
end
end

Now disable the bitcode for your project
Goto Project -> Build Settings -> Filter the term Bitcode -> and select No from the dropdow

Now, you can enable all the below mentioned capabilities in your project.
Goto Project -> Target -> Signing & Capabilities -> Click + at the top left corner -> Search for the capabilities below

Conditions and Notes

Note: From Android 12, ensure that android.permission.BLUETOOTH_CONNECT and android.permission READ_PHONE_STATE runtime permissions are granted for your app for seamless audio routing and GSM call handling.

Caution 1: If the android.permission.BLUETOOTH_CONNECTpermission is not granted, call audio will not be routed to BT Headset even though it is connected.

Caution 2: 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 needs the below permission to show ongoing call notifications.
Manifest.permission.POST_NOTIFICATIONS

Caution: To make and receive a voice/video call, microphone and camera usage permissions were required. Make Sure those permissions are granted

After initiating the previous steps as mentioned in Step 1 - Step 5 follow the below mentioned steps to make use of call SDKs.

Step 1: Make a Voice Call

Run the below method to make a one-to-one voice call
`Mirrorfly.makeVoiceCall(USER_JID).then((response) {
if (response) {

}
}).catchError((e) {
  debugPrint("#Mirrorfly Call Exception $e");
Enter fullscreen mode Exit fullscreen mode

});
`

Step 2: Receive a Call

The 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 if you are connected to the server in foreground state.

Once the call is presented with the 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();
});

Image description

Adding Features
Now let’s add few more features into our chat and call SDKs

Push Notifications
Lets add push notifications to flutter app using firebase integrations

Step 1: Integrate Firebase to the Application

  1. Create project in the Firebase console using your app package name. Ex: com.testapp
  2. Download the automatically generated files google-service.json and GoogleService-Info.plist
  3. Now add google-service.json file to your android/app folder
  4. Then add GoogleService-Info.plist file to your iOS/Runner folder
  5. Now add the firebase dependencies in the pubspec.yaml file dependencies: firebase_core: ^latest_version firebase_messaging: ^latest_version 6.Finally, run flutter pub get to install the dependencies

Step 2: Initialize Firebase in your App

Initialize firebase in the main function of your main.dart file

void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}

Configure FCM in your app
`void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();

//Configuring FCM to Handle Incoming Messages
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
runApp(MyApp());
}

@pragma('vm:entry-point')
Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
// Handle background messages

// If you're going to use other Firebase services in the background, such as Firestore,
// make sure you call initializeApp before using other Firebase services.
await Firebase.initializeApp();
// We are checking the Platform Condition here, because we are handling the push notification in iOS via Notification Extension
if (Platform.isAndroid) {
//Handle the push notification as given below
onMessage(message);
}
}

`

Step 3: Handle Notifications

When you get a Firebase push notification in your Firebase Messaging service, you can utilize this method to get the content of the message before creating and displaying it:

`static void onMessage(RemoteMessage message) {
WidgetsFlutterBinding.ensureInitialized();

await Mirrorfly.handleReceivedMessage(notificationData).then((value) async {
var data = chatMessageFromJson(value.toString());
if(data.messageId!=null) {
//Create and Display the Notification
}
});
}

`

Note: For push notifications in iOS, certain limitations exist when the app is in the terminated or background state. Therefore, we utilize the Notification Service Extension to handle these push notifications.

Step 4: Additional Configuration for iOS

To enable push notifications on iOS, a certain configuration is needed. To make sure that push notifications are received in the background and in the terminated state, this involves adding specific parameters and a notification extension.

Note: Please upload your APNS and VoIP certificates to our console. To learn more how to generate and upload APNS and VOIP certificates, Click Here

Step 5: Capabilities

To receive push notifications in the background or unused state, enable the below capabilities.

Note: Add the “Push Notifications” capability to your project. This can be done via the "Capability" option on the "Signing & Capabilities" tab:

Click on the “+ Capabilities” button
Search “Push Notifications.”

Note: The “Background modes” capability need to be enabled, along with both the “Background fetch” and “Remote notifications” sub-modes.

Click on the “+Capabilities” button
Search “Background Modes.”
Now ensure that both “Background fetch” and “Remote notifications” sub-modes are enabled:

Step 6: Add Group ID

It is necessary to activate the app group container ID in order to receive messages in the background or when the app is ended.

To access user settings and the database in the container, you must enable app grouping in order to access data between the app and the notification extension.

Step 7: Notification Extension

The SDK requires you to include the Notification Extension service in your project in order to receive push notifications in the background and in the Killed state.

1.Open the iOS folder in Xcode to create the NotificationExtension Target.
In Xcode -> File -> New -> Target -> ' NotificationServiceExtension' -> Next -> TargetName -> Activate Scheme

2.Include the Mirrorfly Plugin and Firebase Messaging in the newly formed NotificationExtension target in the podfile.
target 'NotificationExtension' do
use_frameworks!
pod 'Firebase/Messaging'
pod 'mirrorfly_plugin', :path => '.symlinks/plugins/mirrorfly_plugin/ios'
end

3.Do pod install from Terminal inside the iOS folder.
4.Open the Notification Extension File and import the Mirrorfly Plugin.
import mirrorfly_plugin

5.Add the following code to the notification extension file's didReceive method: This code will handle the incoming push notifications.
`override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

    MirrorFlyNotification().handleNotification(notificationRequest: request, contentHandler: contentHandler, containerID: APPGROUPS, licenseKey: LICENSEKEY)

}
Enter fullscreen mode Exit fullscreen mode

`

Step 8: Requesting Permission

A straightforward API for seeking authorization through the requestPermission method is offered by the firebase_messaging package.

`FirebaseMessaging messaging = FirebaseMessaging.instance;

NotificationSettings settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: true,
sound: true,
);

print('User granted permission: ${settings.authorizationStatus}');
`

Image description

Note: On Android, authorization status will return authorized if the user has not disabled notifications for the app via the operating system settings.

Step 9: Add Runtime Permissions for Push Notifications

Starting with Android 13 We require the following permissions in order to get notifications:

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

Get Last Seen Time of a User

You can use the technique below to find out the chat user's last seen time.
Mirrorfly.getUserLastSeenTime(jid).then((String? value) {
});

Hide Last Seen Time of a User

Use the following way to see if friends can view your last seen status.
`Mirrorfly.isHideLastSeenEnabled().then((bool? value) {

});
`

Get User/Group profile Details

You can use the technique below to obtain the chat user's profile information.
Mirrorfly.getProfileDetails(jid, fetchFromServer).then((value) {
var data = Profile.fromJson(json.decode(value.toString()));
});

Get Recent Chats

To retrieve a user's or group's most recent chat.
var value = await Mirrorfly.getRecentChatOf(jid);
var data = RecentChatData.fromJson(json.decode(value));

Get Recent chat List

Use the following procedure to obtain the most recent conversation list:
Mirrorfly.getRecentChatList().then((value) {
var data = recentChatFromJson(value);
}).catchError((error) {
// Error handling
});

Conclusion

Thank you for investing your time in implementing this tutorial. I hope this tutorial helped you add Flutter in-app communication with MirrorFly SDKs to your app.

If you still have any queries, you can get in touch with our tech support team for immediate solutions, or in order to add more chat and call features, you can have a look at our documentation page.

You can also find Flutter UIKit to plug and-play chat features in your app on any platform. Good luck with your search. See you soon. Bye.

Top comments (0)