1-to-1 Video Chat App on Android using Agora.io

This blog post will walk you through the basic integration of the Agora Android SDK that will allow for two users to video chat. To get started there are a few prerequisites/basic knowledge that will not be covered.

Prerequisites

Step 1: Agora.io Account

Once you finish the sign-up process, you will be redirected to the Dashboard. Open the Projects tab on the left-hand nav to see your default project’s App ID.

the default project is disabled by default, make sure to enable it.

Step 2: Download the Agora Video SDK for Android

Download the Agora Video SDK for Android from Agora.io Developer Center
(https://docs.agora.io/en/Agora%20Platform/downloads)

Step 3: Integrate the Agora SDK

Within Android Studio, create a new Single Activity app.

give your application a name
use the default settings for target devices

Once you have created an empty project, it’s time to start integrating the Agora.io SDK. Start by dropping the SDK libs folder into your Android Project (from within your file-explorer)

I used the empty libs folder generated by Android Studio

Make sure to take note of the location of the libs folder in relation to the build.gradle. Next, it’s time to set the storage directory of the libs folder within app/src/main/build.gradle dependancies list, do this by adding the above storage directory to the fileTree code line.

make sure the PATH to libs matches the location of the libs folder relative to the build.gradle (app)
NOTE: Ensure that the path name contains no Chinese characters. If the path contains Chinese characters, compiling the code fails and displays an error message that contains random ASCII characters.

Next, make sure to add the sourceSets within the build.gradle, again make sure the PATH to the libs folder is relative to the build.gradle file.

note: the PATH will be the same as the one declared within the dependancies block

Next, its time to add your Agora.io App ID (see Step-1) to the Android project’s Strings.xml (app/src/main/res/values/Strings.xml).

<resources>
<string name="app_name">Agora-Android-Video-Tutorial</string>
<string name="agora_app_id"><#YOUR APP ID#></string>
</resources>

The next step is to add the appropriate permissions within Manifest.xml

The final step is to prevent obfuscation of the Agora classes, while this might sound complex it’s really simple. In the proguard-rules.pro file, add a -keep class configuration for the Agora SDK.

-keep class io.agora.**{*;}
This prevents obfuscation of the Agora SDK public class names.
NOTE: Ensure that the Android NDK plugin is installed and setup for this project

Step 4: Setup views

Now that we have the Agora.io SDK integrated, let’s set up our UI. I will breeze through this portion as we will be using standard UI elements.

I chose to use ImageViews instead of Buttons but you could use either.

In the example, I chose to use ImageView instead of Button for the various UI elements. Either works, the important part is to note that there are functions that we link to using the onClick property.

Step 5: Checking Permissions

I know what you must be thinking… “didn’t we already set up the Permissions?” Earlier we let the applications Manifest know which permissions our app plans to use, but we still have to explicitly request the user grant these permissions. Don’t worry this is the final step in getting the boilerplate project running and it’s painless.

First, let's declare which permissions we want to request.

// Permissions
private static final int PERMISSION_REQ_ID = 22;
private static final String[] REQUESTED_PERMISSIONS = {Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA};

Next, we set up a couple of functions to help us.

First, we have a method that will request permissions for a given permission string and code.

Next, we have a callback method that will get called after the user has responded to the permissions request prompt.

Last, within our class’s onCreate we check if our permissions have been granted and if not the above methods will handle the requests

Step 6: Initializing the Agora.io SDK

Now that we have our view, we are ready to initialize the Agora.io SDK, set up the user profile and set the video quality settings.

In the previous step, you may have noticed there are a couple places that I call initAgoraEngine(). Before we can dive into the initialization we need to make sure that our Activity has access to an instance of the Agora.io RtcEngine.

Within our MainActivity class, we need to declare a class property to store our instance of RtcEngine.

private RtcEngine mRtcEngine;

Now its time to initialize! After all the boilerplate setup we are finally at the step where we can start playing with the Agora.io engine!

Go ahead and declare your initAgoraEngine() method within your class. Within this function, we will create a new instance of the RtcEngine using the baseContext, the Agora app id (declared above), and an instance of the RtcEngineEventHandler (we’ll get into this a little later).

Once we have our new instance it’s time to set up our user’s session. Here we can set the Channel Profile to Communication, as this is a video chat and not a broadcast (TODO: a post on building a broadcast app). This is also where we configure our video encoder settings.

Please note: at this phase of the build, we can no longer use the emulator to test our work, we must use a mobile device

Step 7: Connecting the Video Streams

Before we can join a view call we need to be able to present the local video stream to the user via the UI elements we setup earlier (Step 4). For reference, below is the UI element’s id that our local video will render into.

android:id="@+id/floating_video_container"

In the first line, we get a reference for the UI element will act as our parent view for our video stream. The second step is to use the RtcEngine to create a SurfaceView that will render the stream from the front camera, we also set the new videoSurface to render on top of its parent view. The next step is to add the videoSurface as a subview of the UI element. Lastly, we pass the videoSurface to the engine as part of a VideoCanvas object. We leave the uid parameter blank so the SDK can handle creating a dynamic id for each user.

Now, that we have our local video feed setup we need to use a similar function to connect our remote video stream.

The main difference with the remote video from the local, is the user id parameter that gets passed to the engine as part of the VideoCanvas object that gets passed to the engine. The last line sets the fall back option in case the video degrades the engine will revert to audio only.

Step 8: Setup the SDK Event Handler

Earlier, I made a reference to the RtcEngineEventHandler, and now it’s time to declare it as a property of our MainActivity class. The engine will call these methods from the RtcEngineEventHandler.

Each event triggers some fairly straight forward functions, including one we wrote in the previous step. In the interest of keeping this brief, I will provide the code below but I won’t give an in-depth breakdown.

feel free to leave a comment if anything is unclear

Step 9: Joining and Leaving Channels

I know what you’re thinking, STEP 9 ?!! Don’t sweat it the next two steps are really simple. Let’s start by joining a call…

Note: if you do not specify the uid when joining the channel, the engine will assign one

As you can see from the first line, Agora SDK makes it simple, the engine calls joinChannel, passing in the channel name followed by the call to set up our local video stream. (Step 7)

note: the remove video method is the same used in step 8

Leaving the channel is even simpler, the engine calls leaveChannel. Above you’ll notice there are a few lines to remove the video stream subviews from each UI element.

Step 10: Adding Other Functionality

The last remaining parts are related to connecting the UI elements for toggling the microphone and video stream on the local device. Let’s start with the audio toggle:

First, we get the reference to our button, and then check if it has been toggled on/off using isSelected(). Once we have updated the UI element state, we pass the button’s updated state to the engine.

Moving on to the video toggle:

As with the audio toggle, we check/update the button’s state using isSelected() and then pass that to the engine. To give a better visual representation of the video being muted, we hide/show the videoSurface.

I hope you enjoyed reading along and working together on creating a 1-to-1 Video Chat Android app using the Agora.io SDK.

Full source code: https://github.com/digitallysavvy/agora-android-demo

If you have any questions or comments, please leave them below!