No one expected that working from home would be the new normal. This pandemic has been tough for everyone but it has proved that even when the complete country is in lockdown, people can work with ease in their homes. Where people are connected online with their colleagues, friends, and family .
Connecting via video call is the need of the hour, and people are using various applications to do that. But such applications aren’t usually customizable to your needs, because they are built with a common UI that solves general use cases. Also, these applications might compromise on the privacy of your data.
The solution is pretty simple: a webRTC service that helps you customize your application according to your use case. In this post, we will look at a sample of how we can implement our own video calling application using the Agora Flutter SDK.
If you’re new to Flutter, then install the Flutter SDK from here.
- Agora Flutter SDK v3.2.1
- VS Code or another IDE of your choice
- Agora developer account (see How to Get Started with Agora)
- We begin by creating a Flutter project. Open your terminal, navigate to your dev folder, and enter the following:
flutter create agora_group_calling
2. Navigate to your
pubspec.yaml file. In that file, add the following dependencies:
Be careful with the indentation when adding the packages because you might get an error if the indentation is off.
3. In your project folder, run the following command to install all the dependencies:
flutter pub get
4. Once we have all the dependencies, we can create the file structure. Navigate to the lib folder and create a file structure like this:
Building the Group Video Calling Interface
To begin with, we navigate to
main.dart. Replace the template code with the following code:
This code just initializes your Flutter application and calls
MyHomePage(), which we defined in
Building Our Home Page
Continuing with our home page, we will be asking our users to enter a channel name. A channel name is a unique string that will put people with the same channel name in a single group call:
This will create a UI similar to the image on the left, which has an input field for the channel name and a join button. The join button calls a function
onJoin, which first gets the user’s permission to access their camera and microphone during the call. Once the user grants these permissions, we move to the next page, CallPage.dart
To ask the user for access to the camera and microphone, we use a package named permission_handler. Here I declare a function named
_handleCameraAndMic(), which I will be referring to in the
Now, in our
onJoin() function we create reference for the above function and then pass the channel name that the user submitted to the next page, CallPage.dart
Building our Call Page
Before we begin with our CallPage.dart, let’s use the App ID that we got from the Agora developer account. (Follow the instructions here to learn how to generate an App ID.) Navigate to AppID.dart in your utils folder and create a variable named appID.
var appID = '<--- Enter your app id here --->'
After this we move to our CallPage.dart and we begin by importing all the files.
Here I create a stateful widget called CallPage such that it’s constructor can read the channel name that the user submitted.
Then we declare some variables in our CallPageState, which we will use while making this page:
_usersis a list that contains the
uidof all the users that are in the channel.
_infoStringscontains all the logs for all the events that occur during the call.
mutedis a Boolean state variable to mute and unmute a user.
_engineis an object for our RtcEngine class
- In our dispose method, we clear the _users list and destroy the RtcEngine.
- In our initState() method, we call the initialize() function, which we will be declaring in the coming steps.
We will create the initialize() function, such that it is a common call for all major functions. The main use of initialize() function is to initialize the Agora SDK. In the initialize function, I am creating the reference of the
_initAgoraRtcEngine()is used as an instance of the Agora SDK. Initialize it using the App ID that you got from the Agora dashboard. We also use the
enableVideo()function to enable the video module. This function can be called before joining the channel or during a call. If you call it before joining the channel, then the call is by default launched in video mode. Otherwise, it launches the app in the audio mode, which can be switched to the video later if required.
_addAgoraEventHandlers()is a function that takes care of all the major callback functions. So we begin with
setEventHandler(), which listens for engine events and receives the statistics of the corresponding RtcEngine.
Some important callbacks include:
joinChannelSuccess()is triggered whenever a local user joins the specified channel. It returns the channel name, the uid of the user, and the time elapsed (in ms) for the local user to join the channel.
leaveChannel()is the opposite of that because it is triggered when the user leaves the channel. It returns the stats of the call whenever the user leaves the channel. These stats include latency, CPU usage, duration, etc.
userJoined()is a method that is triggered when a remote user joins a particular channel. A successful callback returns the uid and the time elapsed of the remote user.
userOffline()is the opposite of that because it occurs when a user leaves the channel. A successful callback returns the uid and the reason for going offline, which includes dropping, quitting, etc.
firstRemoteVideoFrame()is a method that is called when the first video frame of a remote video is rendered. This helps you in returning the uid, the width, the height, and the time elapsed.
To end our initialize() function, we will be adding the
joinChannel() function. A channel acts as a common room for people to be in the same video call. This joinChannel() method can be called with something like:
It takes four parameters to run successfully:
- Token: It is an optional field that can be null for testing, but it should be generated by a token server when moving to production.
- Channel Name: It takes a string input to put users into a common video call.
- Optional Info: This is an optional field through which you can pass additional information about the channel.
- uid: It is the unique ID for every user that joins the channel. If you pass 0 or null value in that, then Agora automatically assigns the uid for every user.
This sums up all the functions and methods required to make this video calling application. Now we can make our widgets, which will take care of the complete UI for our application.
Here I am declaring two widgets (
_toolbar()), which take care of displaying up to four users and adding buttons at the bottom for disconnecting, muting, and switching the camera.
Let’s start with
_viewRows(). For this we need to know the user and their uid for displaying their video. We need a common list of local and remote users with their uid. To implement this, we create a widget named
_getRendererViews(), in which we use RtcLocalView and RtcRemoteView.
Then we simply use expanded views using our widget called
_videoView() and put them in a row using the
Once we have our views structured properly, we will hard code the design using a switch case, which creates columns where views are stacked.
With this, you will have a complete video calling app implemented. Now, to add features like disconnecting the call, muting yourself, and switching the camera, we will create a basic widget called _toolbar() with three buttons:
Here we have declared three functions:
_onToggleMute()lets you mute and unmute your stream. Here, we use the
muteLocalAudioStream()method, which takes a Boolean input to mute or unmute the stream.
_onCallEnd()disconnects the call and takes the user back to the home page.
_onSwitchCamera()lets you toggle between the front and the rear cameras. Here, we use the switchCamera() method, which helps you achieve the desired functionality.
Once we are done building the group video calling application, we can test it on our device. To do that, navigate to your project directory in your terminal and run this command:
Congratulations! You have implemented your own group calling application, which you built using the Agora Flutter SDK, with some basic functionality like muting the local stream, switching the camera, and disconnecting the call.
You can get the complete code for this application here.
To learn more about the Agora Flutter SDK and other use cases, you can refer to the developer guide here.
You can also have a look at the complete documentation for the functions discussed above and many more here.
I also invite you to join Agora Developer Slack Community.