Dynamic Channels for Video Chat Using Agora RTM on React Native
Tags: reactnative, javascript, tutorial, mobile
Published: 2021-12-10 16:25:39

The Agora RTC (Real-time Communication) SDK makes it easy to build video chat apps on React Native. We can have multiple users communicate with each other by using the same channel name for our video chat room.

If you’re building a social video chat app, you might want to let your users generate rooms that other users can browse, join, and communicate in. You can do this with a back-end server to handle these requests and update other users with information about created rooms, but that would involve writing back-end code and hosting your own server.

In this tutorial, we’re going to see an alternative way of achieving the same goal by using the Agora RTM (Real-time Messaging) SDK. We’ll use messages sent by users to communicate the creation and updating of dynamic video chat rooms, all with front-end code.

This can be handy because when you don’t want to build a back-end server, you can use messages to update other users on the status of the rooms. This approach can be easily extended to having fully managed rooms as well as features like admin admit/deny a user, mute another user, and remove a user from the room.

We’ll be using the [Agora RTC SDK](https://www.npmjs.com/package/react-native-agora/) and [Agora RTM SDK](https://www.npmjs.com/package/agora-react-native-rtm) for React Native in this example. I’m using v3.2.2 of the RTC SDK and v1.2.2-alpha.3 of the RTM SDK at the time of writing.

Project Overview
================

*   We have an RTM room called ‘lobby’. We’ll use it to signal users when someone creates a new room or when the members in a room change.
*   The way we’ll do this is by having the most senior member in the video chat room send messages to others. The oldest member in the room is considered the senior member, more on this later.
*   We’ll send messages in the form of ‘roomName:memberCount’ which can be processed by other users to store the room name and member count as a dictionary in their application state. We’ll use it to render a list of rooms with the number of members in it.
*   Once we have the list, we can join the room by using the RTC SDK. We’ll also need to listen for users joining and leaving to update the member count for everyone else. This is done only by the senior member to avoid overhead.
*   We also need to consider two cases to update room information for other users. First, when a new user joins the lobby, the senior-most member in each channel sends the user a peer message. Second, when a channel’s member count is updated we send a channel message to all users connected to the lobby to update their room list.

Creating an Agora account
=========================

[Sign up](https://sso.agora.io/en/signup?utm_source=medium&utm_medium=blog&utm_campaign=dynamic-channels-for-video-chat-using-agora-rtm-on-react-native) for an account and log in to the dashboard.

<img alt="" class="t u v kt aj" src="https://miro.medium.com/max/1000/1\*YFtAcuBfRmPXr8DGEA79SA.png" width="500" height="581" srcSet="https://miro.medium.com/max/552/1\*YFtAcuBfRmPXr8DGEA79SA.png 276w, https://miro.medium.com/max/1000/1\*YFtAcuBfRmPXr8DGEA79SA.png 500w" sizes="500px" role="presentation"/>

Navigate to the Project List tab under the Project Management tab, and create a project by clicking the blue Create button. (When prompted to use App ID + Certificate, select only App ID.) The App ID will be used to authorize your requests while you’re developing the application, without generating tokens. Copy the App ID someplace safe, we’ll need it in a bit.

_Note:_ This guide does not implement token authentication, which is recommended for all RTE apps running in production environments. For more information about token-based authentication in the Agora platform, see [https://docs.agora.io/en/Video/token?platform=All%20Platforms](https://docs.agora.io/en/Video/token?platform=All%20Platforms).

Download the Source
===================

You can jump to the code if you like. The code is open source and available on [GitHub](https://github.com/EkaanshArora/Agora-Dynamic-VideoChat-Rooms). To try it out for yourself, see the readme for steps on how to run the app.


![Screenshots from the app running on an Android Emulator](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1i59dx7t50uygmyxcvnm.jpeg)

Structure of our example
========================

This is the structure of the application that we are building:

```
**.**  
├── android  
├── components  
│ └── **Permission.ts**  
│ └── **Style.ts**  
├── ios  
├── **App.tsx  
.**
```

App.tsx
-------

App.tsx will be the entry point into the app. We’ll have all our code in this file.

{% gist https://gist.github.com/EkaanshArora/9dbcd75818c23a29e0785b65e5123852 %}

We start by writing the import statements. Next, we define an interface for our application state containing the following:

*   `**appId**`: our Agora App ID
*   `**token**`: token generated to join the channel
*   `**inCall**`**:** boolean to store if we’re in an active video chat room
*   `**inLobby**`**:** boolean to store if we’re in the lobby
*   `**input**`**:** string to store input when creating a new room
*   `**peerIdsRTC**`: array to store the RTC UIDs of other users in the video chat room
*   `**seniors**`**:** array storing RTM members who have joined the video chat room before us
*   `**myUsername**`: local user’s name to log in to RTM
*   `**rooms**`**:** dictionary to store room names and their member count

{% gist https://gist.github.com/EkaanshArora/5500042ba4cfb1275eeb5df30d2f698c %}

We define a class-based component: the `_rtcEngine` variable will store the instance of the RtcEngine class, and the `_rtmEngine` variable will store the instance of the RtmEngine class, which we can use to access the SDK functions.

In the constructor, we set our state variables and request permission for recording audio on Android. (We use a helper function from `permission.ts` as described below.) When the component is mounted, we call the `initRTC`  and `initRTM` functions, which initialize the RTC and RTM engines using the App ID. When the component unmounts, we destroy our engine instances.

RTC Initialization
------------------

{% gist https://gist.github.com/EkaanshArora/9b4dcf25763836653dc8fad4c73f7009 %}

We use the App ID to create our engine instance. We use the `enableVideo` method to set the SDK in video mode.

The RTC triggers a `userJoined` event for each user present when we join the channel and for each new user who joins later. The `userOffline` event is triggered when a user leaves the channel. We use event listeners to keep our peerIds array updated with UIDs. We will use this array later to render the video feeds from other users.

Once we’ve joined a channel, the SDK triggers the `JoinChannelSuccess` event. We set our state variable `inCall` as true to render the video chat UI.

When a new user joins our video chat room, if we’re the senior member as discussed before, we send a channel message with the updated user count to all members across channels using the `lobby` RTM channel.

RTM Initialization
------------------

{% gist https://gist.github.com/EkaanshArora/3ca5fe83cd8b26579311b88b5399f338 %}

We’re using RTM to send our room name and member count. We maintain an array of seniors, that is, members who have joined the call before us. If the seniors array size is <2, it means we’re the senior-most member, responsible for the signaling. (The local user is also part of the array.)

First, we attach the `channelMemberJoined` and `channelMemberLeft` listeners, which are triggered when a user joins or leaves the RTM channel. When a user joins the lobby channel, if we’re the senior-most member we send them a peer message. If a user leaves the current video chat channel, we update the seniors array (removing them from it if they had arrived before us). We also send a channel message to the lobby if we are the senior member updating the count.

Next, we attach the `channelMessageReceived` and `messageReceived` event listeners, which are triggered when we receive a channel message and a peer message, respectively. We split the `channelName:memberCount` string (for example, `‘helloWorld:5’`) and use the two pieces of data to update our dictionary. (for example, `rooms: { ‘helloWorld’: 5, ‘roomTwo’: 3 }`).

Join a Call
-----------

{% gist https://gist.github.com/EkaanshArora/edde05050e1f705ce6c8457eddb978b5 %}

We define a function to join the call that takes in the channel name as an argument. We update the state with the channel name and join the channel on both RTM and RTC, using the `joinChannel` methods.

We use the `getChannelMembersBychannelId` method on RTM to get the UIDs of the users on the channel. If we’re the only member, we send a channel message to the lobby channel on RTM to update everyone about the created room.

Leaving the Call
----------------

{% gist https://gist.github.com/EkaanshArora/97b21e4a3245ae643234f7ec1fbedb1d %}

We leave the RTM and RTC video chat room channels but stay connected to the lobby channel on RTM to keep receiving updates. We update our state by clearing the `peerIds` array, the `seniors` array, and the `channelName`. We also set `inCall` as false and `inLobby` as true to render the lobby UI.

Rendering Our UI
----------------

{% gist https://gist.github.com/EkaanshArora/6abe3c47bb7fdefb8b00501604b66714 %}

We define the render function for displaying buttons to display the status if we’re in a call or the lobby.

{% gist https://gist.github.com/EkaanshArora/41b1531eaaef603a2e0d1b87d8aac2e2 %}

We use the `_renderRooms` function to render a scroll view, which iterates over the rooms dictionary to show a list of created rooms with their member count. The user can tap any room to join it, which calls the `joinCall` function. We also render a text input to let the user create a room that calls the same `joinCall` function with that input.

{% gist https://gist.github.com/EkaanshArora/6606c551946ef7aad035b686fba8aa74 %}

We use the `_renderCall` function to render the videos once we’re connected to a video chat room. We use the `RtcLocalView` component from the SDK to render our own (local user’s) video. We use `RtcRemoteView` inside a scroll view to render the videos of connected users using the UIDs stored in the `peerIds` array. We also display a button to leave the room.

Permission.ts
-------------
{% gist https://gist.github.com/EkaanshArora/bf4ad0db0fcff4d7c8b8a33517698c97 %}

We’re exporting a helper function to request microphone permissions from the Android OS.

Style.ts
--------

{% gist https://gist.github.com/EkaanshArora/7aae26a1fae65e3b7daf4db34ce19d45 %}

The Style.ts file contains the styling for the components.

What’s next?
============

The same technique can be used to communicate other information, such as names of users connected, room description, and room title. We can even use the same mechanism to kick users off the call by sending an RTM message that, when evaluated, calls the leave channel method on the remote user’s device.

Conclusion
==========

You’ve seen how we can leverage the Agora RTM SDK to share information and dynamically create video chat rooms. You can refer to the [Agora React Native API Reference](https://docs.agora.io/en/Video/API%20Reference/react_native/index.html) for methods that can help you quickly add more features to your next real-time engagement application.