Back to Blog

Group Video Calling Using the Agora Flutter SDK

Introduction

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.

https://giphy.com/gifs/election2020-dnc-2020-democratic-national-convention-KenZCPB6lReAsffAIE

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.

Prerequisites

If you’re new to Flutter, then install the Flutter SDK from here.

Project Setup

  1. 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:

pubspec.yaml

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:

Group Video Calling Using the Agora Flutter SDK - Screenshot #5
Project Structure

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 HomePage.dart.

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:

HomePage.dart

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 onJoin() function:

HomePage.dart — _handleCameraAndMic()

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

HomePage.dart — onJoin()

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.

importing the Agora SDK

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:

  • _users is a list that contains the uid of all the users that are in the channel.
  • _infoStrings contains all the logs for all the events that occur during the call.
  • muted is a Boolean state variable to mute and unmute a user.
  • _engine is 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.

Agora CallPageState

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() and _addAgoraEventHandlers() functions:

  • _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.

_initAgoraRtcEngine()

  • _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.

_addAgoraEventHandlers()

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:

joinChannel()

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 (_viewRows() and _toolbar()), which take care of displaying up to four users and adding buttons at the bottom for disconnecting, muting, and switching the camera.

build

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 _expandedVideoRow() widget.

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:

Group Video Calling Using the Agora Flutter SDK - Screenshot #3
_toolbar Widget

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.

Testing

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:

flutter run 

Conclusion

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.

Other Resources

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.

RTE Telehealth 2023
Join us for RTE Telehealth - a virtual webinar where we’ll explore how AI and AR/VR technologies are shaping the future of healthcare delivery.

Try Agora for Free

Sign up and start building! You don’t pay until you scale.
Try for Free
Get Started with Agora thumbnail