Build a Livestream Video & Chat App for Android

As we seek to still connect with friends and family while we all #stayhome, Live Streaming and Video Conferencing have become insanely popular. These technologies have always been great tools for connecting with coworkers and loved ones who are not located nearby; however, we are now seeing incredible growth in their use for connecting with people near and far. Artists are live-streaming their performances; teachers are educating children via online classes; friends and family are meeting online using group video chat, etc.

With this being the case, the apps that support these connections have also been taking off, and we thought it might be fun to show you just how easy it would be to build a live streaming application powered by video and chat! In this tutorial, we'll walk through how to build a live-video-streaming application on Android. What’s more, the app we build here won’t just be an ugly, bare-bones application; thanks to Stream's Chat API, which will allow for seamless communication between users within the live video chat, we’ll have a friendly and appealing UI!

Note: If you'd like to jump right into the code, you can find the complete open-source codebase on GitHub.

At the end of the tutorial, you will have created the following application from scratch:

To incorporate chat into our application, this tutorial will leverage Stream’s Low-Level Android Client; if you’d like to read more about using it, check out Stream’s Android Chat Docs!

Getting Started

Let’s start by cloning the step-1 branch of the app repo from GitHub, which will serve as our initial codebase for this tutorial. Head over to your preferred working directory on your machine and clone the project using the following snippet:

The step-1 branch contains the necessary project code with a basic UI that consists of the following:

  • A simple YouTube-style video streaming view
  • A customized input box with a send button, for adding comments
  • All of the required Gradle dependencies, including Stream’s Low-Level Android client – one of the core dependencies of this tutorial

To start, you will need to generate a file called secret.properties within the root directory of your project. Populate your new file with the following code:

Replace the and defaults with the values from your own Stream Dashboard. The StreamApiKey is a public key which you can get by registering your chat app at https://getstream.io/dashboard/. The UserToken is the JWT token of your app user. To ease the process of generating a JWT on the fly, we’ve created a simple generator within our docs, which can be found here.

Once you have finished adding the necessary secrets, just run the ./gradlew build command. At this point, you should have the project building successfully!

After running the app, you should see the following screen with the video playing automatically and comment input controls present at the bottom:

Creating the UI

Let’s add the UI code responsible for displaying the chat messages over the video!

We will start by modifying the activity_main.xml to add a RecyclerView widget, which will display chat messages as a vertical list. The RecyclerView will be placed at the bottom of the screen, leaving the space at the top for the video, to give it more real estate and make it the focal point. Behind the list view, we are also going to add a gradient to improve the readability of the latest incoming messages, which happens to be useful when bright video frames are displayed on the device, as well.

Let’s start by adding the following views to the activity_main.xml file:

Next, we will need to implement the adapter class to be responsible for rendering the chat messages in the RecyclerView widget. To do this, we will add a “MessagesListAdapter.kt” file with the following code:

As you can see, we are using the ListAdapter class from the androidx.recyclerview package – this is a wrapper over the standard RecyclerView.Adapter class and is a great way to optimize the way items render when you update the list.

To read more about the ListAdapter class, head over to the Android docs.

We also declared the layout for the single chat message element as R.layout.item_message. Let’s define that layout now! Create a new layout file called “item_message.xml” in in the app/res/layout directory and add the following code:

At the end of this step, we are going to instantiate the adapter and set it to the RecyclerView in the LiveStreamActivity.onCreate() hook method. We are also going to add the updateMessagesList(messages: List) function, which will be responsible for updating the message items in the list:

The Message type in the updateMessagesList() function belongs to the io.getstream.chat.android.client.models package from the Stream Low-Level client library.

In the next part of this tutorial, we are going to implement simple message sending logic and handle incoming message events!

Adding Chat with Stream

Now that you have completed the previous steps, your code should be the same as the step-2 branch of the app repo.

You can check out the step-2 branch if you’d like to start from this part and skip the previous portion of the tutorial.

Let’s start by initiating the ChatClient instance. Let’s add the following line inside the onCreate() function of our App class:

Next, let’s jump into the LiveStreamViewModel.kt file. This is the place where the actual connection with the chat backend will be managed. Let’s start by defining the User and Channel metadata in the companion object at the bottom of the class:

Then, obtain the ChatClient instance and assign it into a class property called chatClient. Now, let’s use the ChatClient instance to initiate the Channel. We will do so by calling the setUser() function within theinit {} block:

If the chatClient.setUser() operation is successful, we are going to receive the ConnectionData object in the onSuccess() callback.

At this point, we set the channel by calling the chatClient.channel() function. This function takes two parameters: the CHANNEL_TYPE and CHANNEL_ID. For the purposes of our sample application, we are setting CHANNEL_TYPE to “livestream” and CHANNEL_ID to a hardcoded value.

In your production application, you will want to pass a unique ID specific to the video stream you wish to present.

This function returns the ChannelController instance, which we assign to the private lateinit var channelController: ChannelController class property.

We will also use this instance later, to perform requests to the chat backend.

When we receive the onSuccess callback, we are calling two functions: requestChannel() and subscribeToNewMessageEvent():

Inside requestChannel(), we are creating an instance of QueryChannelRequest() and calling channelController.query(request) followed by an enqueue() call, which executes our function. The request contains channel data that specifies the name of the channel, the number of latest messages we want to obtain, and the watch flag. The withWatch() method informs our app that we want to receive channel events (e.g. new message events).

subscribeToNewMessageEvent() calls chatClient.events().subscribe(), in order to subscribe to the stream of chat events. It uses only the events of the NewMessageEvent type and updates the LiveData channel with newly received Message objects. In addition, once the QueryChannelRequest is successful, we obtain the list of messages and pass it to the LiveData.

Now, our Activity will subscribe to this channel and update the screen to show the received messages on the screen! Inside the LiveStreamActivity onCreate() hook, we obtain an instance of LiveStreamViewModel and subscribe to the LiveStreamViewModel.viewState’s LiveData. In doing so, the Activity will receive State updates informing it about new messages and errors:

We call the updateMessageList() function whenever we receive State.Messages or State.NewMessage updates. Note that, in the case of receiving a State.NewMessage, we are adding the new message to the existing list that we get from the messagesList adapter.

At this point, when running the application, we should be able to post new messages to the chat, and new messages should be displayed in the chat view. In the next step, we are going to add a little animation to make the chat list updates more smooth!

Cleaning up the UI

At this point, your code should correspond to the step-3 branch of the app repo; you can checkout this branch if you’d like to start from this section of the tutorial.

Let’s declare an instance of LinearSmoothScroller as a class property in the LiveStreamActivity class:

We are now going to modify the updateMessagesList() so that we can use it to animate the list to scroll to the latest message after notifying the adapter about new data:

That’s it! We have just implemented the chat feature! Your app should now look like this:

Hint: Click the play button to view on YouTube!

Wrapping Up

I hope getting through this tutorial gave you a sense of how fast it can be to add a live chat feature into a video streaming app on Android. Thanks to Stream and the Low-Level Android Chat Client, we were able to avoid dealing with any complex chat backend or with WebSockets, entirely!

Note: For the production live streaming application, you’ll need to tune up this demo app a bit. Ideally, you will want to create a separate chat channel for each group, and allow multiple users to join the conversation.

Here are a few more links to resources which will help you get up and running quickly:

Please feel free to reach out in the comments below should you have any questions.

Thanks for reading, and happy coding!

TutorialsChat