Introduction
Whether it's sharing important information, asking questions, or simply chatting, participants can engage with each other effortlessly during the video call sessions, integrating a real time chat feature into your Flutter video call app improves participant collaboration and communication. You can implement real-time messaging capabilities, using the PubSub (Publish-Subscribe) mechanism, ensuring efficient and scalable message distribution across meetings.
In this guide, we'll navigate the process of seamlessly integrating real time chat capabilities into your existing flutter video chat app. From establishing the chat environment to managing real time chat interactions within your video call interfaces, we'll cover all the essential steps to augment your app's functionality and user experience.
Benefits of Implement Chat Feature in Flutter Video Call App
- Enhanced Collaboration: Chat enables participants to communicate ideas, share files, and ask questions, fostering collaboration and teamwork.
- Real-time Feedback: During video calls, users can provide immediate feedback, ask questions, or clarify doubts improving communication efficiency.
- Documentation: Chat transcripts record discussions and decisions made during meetings, facilitating post-meeting review and follow-up.
- Increased Engagement: Chat encourages active participation from all participants, even those who might be hesitant to speak up during video calls.
Getting Started with VideoSDK
We must use the capabilities that VideoSDK offers. Before diving into the implementation steps and building the Flutter chat app, let's ensure you complete the necessary prerequisites to integrate the real time chat feature.
Create a VideoSDK Account
Go to your VideoSDK dashboard and sign up if you don't have an account. This account gives you access to the required Video SDK token, which acts as an authentication key that allows your application to interact with VideoSDK functionality.
Generate your Auth Token
Visit your VideoSDK dashboard and navigate to the "API Key" section to generate your auth token. This token is crucial in authorizing your application to use VideoSDK features. For a more visual understanding of the account creation and token generation process, consider referring to the provided tutorial.
Prerequisites
Before proceeding, ensure that your development environment meets the following requirements:
- VideoSDK Developer Account (if you do not have one, follow VideoSDK Dashboard)
- The basic understanding of Flutter and Having installed it on your device.
- Flutter VideoSDK
Install VideoSDK
Install the VideoSDK using the below-mentioned flutter command. Make sure you are in your Flutter chat app directory before you run this command.
$ flutter pub add videosdk
//run this command to add http library to perform network call to generate roomId
$ flutter pub add http
VideoSDK Compatibility
Android and iOS app | Web | Desktop app | Safari browser |
---|---|---|---|
Structure of the project
Your project structure should look like this.
root
├── android
├── ios
├── lib
├── api_call.dart
├── join_screen.dart
├── main.dart
├── meeting_controls.dart
├── meeting_screen.dart
├── participant_tile.dart
We are going to create flutter widgets (JoinScreen, MeetingScreen, MeetingControls, and ParticipantTile).
App Structure
The app widget will contain JoinScreen
and MeetingScreen
widget. MeetingScreen
will have MeetingControls
and ParticipantTile
widget.
Configure Project
For Android
For Android
- Update
/android/app/src/main/AndroidManifest.xml
for the permissions we will be using to implement the audio and video features.
- Also, you will need to set your build settings to Java 8 because the official WebRTC jar now uses static methods in
EglBase
an interface. Just add this to your app-level/android/app/build.gradle
.
android {
//...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
- If necessary, in the same
build.gradle
you will need to increaseminSdkVersion
ofdefaultConfig
up to23
(currently, the default Flutter generator sets it to16
). - If necessary, in the same
build.gradle
you will need to increasecompileSdkVersion
andtargetSdkVersion
up to33
(currently, the default Flutter generator sets it to30
).
For iOS
- Add the following entries which allow your app to access the camera and microphone of your
/ios/Runner/Info.plist
file :
<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) Camera Usage!</string>
<key>NSMicrophoneUsageDescription</key>
<string>$(PRODUCT_NAME) Microphone Usage!</string>
- Uncomment the following line to define a global platform for your project in
/ios/Podfile
:
# platform :ios, '12.0'
For MacOS
- Add the following entries to your
/macos/Runner/Info.plist
file that allows your app to access the camera and microphone:
<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) Camera Usage!</string>
<key>NSMicrophoneUsageDescription</key>
<string>$(PRODUCT_NAME) Microphone Usage!</string>
- Add the following entries to your
/macos/Runner/DebugProfile.entitlements
file that allows your app to access the camera, microphone, and open outgoing network connections:
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.device.camera</key>
<true/>
<key>com.apple.security.device.microphone</key>
<true/>
- Add the following entries to your
/macos/Runner/Release.entitlements
file that allows your app to access the camera, microphone, and open outgoing network connections:
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.device.camera</key>
<true/>
<key>com.apple.security.device.microphone</key>
<true/>
Essential Steps to Implement Video Calling Functionality
After successfully integrating VideoSDK into your Flutter chat app, you have laid the foundation for real-time audio and video communication. Now, let's take it a step further by integrating the real time chat feature. This will allow users to send messages during a call, providing a convenient way to share quick messages, links, or information.
Step 1: Get started with api_call.dart
api_call.dart
Before jumping to anything else, you will write a function to generate a unique meetingId. You will require an authentication token, you can generate it either by using videosdk-rtc-api-server-examples or by generating it from the VideoSDK Dashboard for development.
Step 2: Creating the JoinScreen
Let's create join_screen.dart
file in lib
directory and create JoinScreen StatelessWidget
.
The JoinScreen will consist of:
- Create Meeting Button: This button will create a new meeting for you.
- Meeting ID TextField: This text field will contain the meeting ID, you want to join.
- Join Meeting Button: This button will join the meeting, which you have provided.
- Update the home screen of the app in the
main.dart
Step 3: Creating the MeetingControls
Let's create meeting_controls.dart
file and create MeetingControls StatelessWidget
.
The MeetingControls will consist of:
- Leave Button: This button will leave the meeting.
- Toggle Mic Button: This button will unmute or mute the mic.
- Toggle Camera Button: This button will enable or disable the camera.
MeetingControls will accept 3 functions in the constructor.
onLeaveButtonPressed
: invoked when the Leave button is pressed.onToggleMicButtonPressed
: invoked when the toggle mic button is pressed.onToggleCameraButtonPressed
: invoked when the toggle Camera button is pressed.
Step 4: Creating ParticipantTile
Let's create participant_tile.dart
file and create ParticipantTile StatefulWidget
.
The ParticipantTile will consist of:
- RTCVideoView: This will show the participant's video stream.
ParticipantTile will accept Participant
in constructor
- participant: participant of the meeting.
Step 5: Creating the MeetingScreen
Let's create meeting_screen.dart
file and create MeetingScreen StatefulWidget
.
MeetingScreen will accept meetingId and token in the constructor.
- meetingID: meetingId, you want to join
- token: VideoSDK Auth token.
CAUTION
If you getwebrtc/webrtc.h
file not found error at a runtime in iOS, then check the solution here.
TIP:
You can checkout the complete quick start example here.
Integrate Chat Feature
For communication or any kind of messaging between the participants, VideoSDK provides pubSub
mechanism and can be used to develop a wide variety of functionalities. For example, participants could use it to send messages to each other, share files or other media, or even trigger actions like muting or unmuting audio or video.
Now we will see, how we can use PubSub to implement real time chat functionality. If you are not familiar with the PubSub mechanism, you can follow this guide.
Group Chat
The first step in creating a group chat is choosing the topic that all the participants will publish and subscribe to send and receive the messages. We will be using CHAT
this as the topic for this one. So let us create a message input and send button to publish the messages using the pubSub
from the Room
object.
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
class ChatView extends StatefulWidget {
final Room room;
...
}
class _ChatViewState extends State<ChatView> {
final msgTextController = TextEditingController();
void initState() {
...
// Subscribing 'CHAT' Topic
widget.room.pubSub
.subscribe("CHAT", messageHandler)
.then((value) => setState((() => messages = value)));
}
//Handler which will be called when new mesasge is received
void messageHandler(PubSubMessage message) {
setState(() => messages!.messages.add(message));
}
Widget build(BuildContext context) {
return Column(
children:[
Row(
children: [
Expanded(
child: TextField(
style: TextStyle(
fontSize:16,
fontWeight: FontWeight.w500,
),
controller: msgTextController,
onChanged: (value) => setState(() {
msgTextController.text;
}),
decoration: const InputDecoration(
hintText: "Write your message",
border: InputBorder.none,
),
),
),
ElevatedButton(
onPressed:(){
if(!msgTextController.text.trim().isEmpty){
widget.room.pubSub
.publish(
"CHAT",
msgTextController.text,
const PubSubPublishOptions(
persist: true),
)
.then(
(value) => msgTextController.clear())
}
},
child: const Text("Send Message"),
),
],
),
]
);
}
}
The final step in the group chat would be to display the messages others send. For this will use the messages
and display all the messages by subscribing to the topic CHAT
.
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
class ChatView extends StatefulWidget {
final Room room;
...
}
class _ChatViewState extends State<ChatView> {
// PubSubMessages
PubSubMessages? messages;
void initState() {
...
// Subscribing 'CHAT' Topic
widget.room.pubSub
.subscribe("CHAT", messageHandler)
.then((value) => setState((() => messages = value)));
}
//Handler which will be called when new mesasge is received
void messageHandler(PubSubMessage message) {
setState(() => messages!.messages.add(message));
}
Widget build(BuildContext context) {
return Column(
children:[
Expanded(
child: messages == null
? const Center(child: CircularProgressIndicator())
: SingleChildScrollView(
reverse: true,
child: Column(
children: messages!.messages
.map(
(message) => Text(
message.message
),
)
.toList(),
),
),
),
...
//Send Message code Here
]
);
}
void dispose() {
// Unsubscribe
widget.room.pubSub.unsubscribe("CHAT", messageHandler);
super.dispose();
}
}
Now let us open this ChatView
widget on a button click from our meeting screen.
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
import './participant_tile.dart';
import './ChatView.dart';
class MeetingScreen extends StatefulWidget {
final String meetingId;
final String token;
const MeetingScreen(
{super.key, required this.meetingId, required this.token});
State<MeetingScreen> createState() => _MeetingScreenState();
}
class _MeetingScreenState extends State<MeetingScreen> {
// Other code here...
// This widget is the root of your application.
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () => _onWillPop(),
child: Scaffold(
appBar: AppBar(
title: const Text('VideoSDK QuickStart'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
// Other meeting widgets ...
ElevatedButton(
onPressed: (){
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) => ChatView(
key: const Key("ChatScreen"),
meeting: widget.room),
));
},
child: const Text('Open')),
],
),
),
),
home: JoinScreen(),
);
}
}
Private Chat
In the above example, if you want to convert into a private chat between two participants, then all you have to do is pass sendOnly
parameter in PubSubPublishOptions
.
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
class ChatView extends StatefulWidget {
final Room room;
...
}
class _ChatViewState extends State<ChatView> {
//...
Widget build(BuildContext context) {
return Column(
children:[
Row(
children: [
Expanded(
child: TextField(
style: TextStyle(
fontSize:16,
fontWeight: FontWeight.w500,
),
controller: msgTextController,
onChanged: (value) => setState(() {
msgTextController.text;
}),
decoration: const InputDecoration(
hintText: "Write your message",
border: InputBorder.none,
),
),
),
ElevatedButton(
onPressed:(){
if(!msgTextController.text.trim().isEmpty){
// Pass the participantId of the participant to whom you want to send the message.
widget.room.pubSub
.publish(
"CHAT",
msgTextController.text,
const PubSubPublishOptions(
persist: true, sendOnly: ["xyz"]),
)
.then(
(value) => msgTextController.clear())
}
},
child: const Text("Send Message"),
),
],
),
]
);
}
}
Displaying the Latest Message Notification
You may want to show the notification to the user when a new message arrives. So let's continue our example and add an alert for the new images.
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
class ChatView extends StatefulWidget {
final Room room;
...
}
class _ChatViewState extends State<ChatView> {
void initState() {
...
}
//Handler which will be called when new mesasge is received
void messageHandler(PubSubMessage message) {
//Show snackbar on new message
if(context.mounted){
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(
message.message,
overflow: TextOverflow.fade,
),
));
}
setState(() => messages!.messages.add(message));
}
Widget build(BuildContext context) {
return Column(
children:[
...
]
);
}
void dispose() {
...
}
}
Downloading Chat Messages
All the messages from the PubSub were published persist : true
and can be downloaded as a .csv
file. This file will be available in the VideoSDK dashboard as well as through the Sessions API.
In Flutter's real-time chat feature, combine real-time voice and video with asynchronous text messaging, accommodating various communication preferences and scenarios with the functionality provided by VideoSDK. With the guidance offered in this tutorial, you can develop a user-friendly video-calling platform that enables users to connect in innovative ways.
Now if you have just started to build or integrate new features with VideoSDK, you can unlock the full potential of VideoSDK today and build personalized video experiences! Just Sign up now and receive 10,000 free minutes and take your video app to new heights.