Adding PubNub Chat to an Agora Video Android App

Nowadays, as people pay increasing attention to virtual communication, many teams want to create their own social software. Agora and PubNub offer tools that make building communication software with video and text communication features quick and easy.

In this tutorial, I’ll show you how to integrate the PubNub Web SDK to add text-based chat to an Android app that uses the Agora Video SDK for voice and video communication.

Prerequisites

Note: You can download the finished project as a reference.

Project Setup

There will be five steps to build our communication application in this tutorial:

  • Add the PubNub keys.
  • Add the chat UI.
  • Integrate a PubNub client.
  • Connect the PubNub client to a channel.
  • Use the client to send and receive messages in the channel.

Build The Project

There will be five steps to build our communication application in this tutorial: Add the PubNub keys, add the chat UI, integrate a PubNub client, connect the PubNub client to a channel, and use the client to send and receive messages in the channel.

Add PubNub Keys

In order to use PubNub SDK to send messages, you open the String.xml file under the res/values folder and add PubNub publish and subscribe keys.
<resources>
    ...

    <string name="pubNub_sub_key">PubNub Subscribe Key</string>
    <string name="pubNub_pub_key">PubNub Publish Key</string>
    ...
</resources>

Add the Chat UI

Next, you add the chat UI in the video call layout so that users can send text messages during video calls. Go to the activity_video_chat_view.xml file. Add a EditText view, a button to edit and send messages, and a RecyclerView to display the chat history.
<LinearLayout
android:id="@+id/chat_layout"
android:layout_width="170dp"
android:layout_height="250dp"
android:orientation="vertical"
android:layout_alignParentBottom="true"
android:layout_marginBottom="155dp"
>

<TextView
android:id="@+id/text_channel_member_count"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=" CHAT"
/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/message_list_audience"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="20dp"
/>

</LinearLayout>

<LinearLayout
android:id="@+id/message_send_layout"
android:layout_width="170dp"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="120dp"
>

<EditText
android:id="@+id/message_edittiext"
android:layout_width="120dp"
android:layout_height="37dp"
android:hint="Single line input"
android:background="@color/white"
android:lines="1"
android:padding="5dp"
android:layout_marginTop="3dp"
android:textColor="@color/black"
/>

<TextView
android:id="@+id/send_chat_btn"
android:layout_width="45dp"
android:layout_height="40dp"
android:clickable="true"
android:onClick="onSendClicked"
android:textColor="@color/white"
android:background="@color/blue"
android:padding="6dp"
android:text="Send"
/>
</LinearLayout>

Integrate the PubNub Client

First, in the app-level build.gradle file, declare the dependency for the PubNub SDK.

dependencies {
    ...
    // add PubNub Android-Java SDK here at that bottom      implementation group: 'com.pubnub', name: 'pubnub-gson', version: '4.+'
    ...
}

In the base project, when a user wants to start the video call, the app calls initEngineAndJoinChannel method to initialize the Agora client and joins a channel. You want to add similar functionality to the PubNub integration. To do this, add another method called initPubNubClicent after initEngineAndJoinChannel. In that method, pass the PubNub key values to a PNConfiguration instance and initialize a new PubNub instance.

private void initPubNubClient() {
    PNConfiguration pnConfiguration = new PNConfiguration();
    pnConfiguration.setSubscribeKey(getString(R.string.pubNub_sub_key));
    pnConfiguration.setPublishKey(getString(R.string.pubNub_pub_key));

    PubNub pubnub = new PubNub(pnConfiguration);
}

You can register a listener to handle PubNub client events.

private void initPubNubClient() {
    ...
    pubnub.addListener(new SubscribeCallback() {
        @Override
        public void status(PubNub pubnub, PNStatus status) {   
           
        }
        @Override
        public void message(PubNub pubnub, final PNMessageResult message) {
            // Handle new message stored in message.message
            ...
        }

        ...
    });
   
}
The message event is triggered when users (including both local and remote users) send messages in the channel. In this case, you check if the message is sent by the local user or the remote user. If the message is sent by the local user, you display the message on the right side of the RecyclerView. Otherwise, you display the message on the left side of the RecyclerView. (I discuss this later in the article.)

Connect the PubNub Client to a Channel

To receive and send messages, you first need to connect to a channel. It is better to use the same channel name that you used to join the video call. Add this code after the initialization of the PubNub instance:

pubnub.subscribe().channels(Arrays.asList(channelName)).execute();

In the demo code, I hard-coded the channelName as “test.” However, you can create an interface to let users enter their channel name and join that channel.

Use PubNub Client to Send and Receive Messages

When a user enters the text message and clicks the send button, you need to send this message to the channel using the PubNub client. So create the onClick method for the send message button. In that method, you first get the text that the user entered in the EditText. Then you send the message to the target channel. If the message was successfully sent to the channel, you can remove the text in the EditText.

public void onSendClicked(View view) {

   ...

    // create message payload using Gson
    final JsonObject messageJsonObject = new JsonObject();
    messageJsonObject.addProperty("msg", editText.getText().toString());

    pubnub.publish().channel(channelName).message(messageJsonObject).async(new PNCallback() {
        @Override
        public void onResponse(PNPublishResult result, PNStatus status) {
            // Check whether request successfully completed or not.
            if (!status.isError()) {
                editText.setText("");
                // Message successfully published to specified channel.
            }
            // Request processing failed.
            else {

                // Handle message publish error. Check 'category' property to find out possible issue
                // because of which request did fail.
                //
                // Request can be resent using: [status retry];
            }
        }
    });
}
To receive a message from the channel (as discussed above), you need to use the message event callback. You can get the message information and sender’s ID in the message parameter. With this information, you can properly display the chat messages in the RecyclerView.
@Override
public void message(PubNub pubnub, final PNMessageResult message) {
    // Handle new message stored in message.message
    final String msg = message.getMessage().getAsJsonObject().get("msg").getAsString();
    if (!message.getPublisher().equals(pnConfiguration.getUuid())) {       
        //Message from remote users
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                //Display on the screen
                String account = message.getPublisher();
                Log.i(TAG, "onMessageReceived account = " + account + " msg = " + msg);
                MessageBean messageBean = new MessageBean(account, msg, false);
                messageBean.setBackground(R.drawable.shape_circle_blue);
                mMessageBeanList.add(messageBean);
                mMessageAdapter.notifyItemRangeChanged(mMessageBeanList.size(), 1);
                mRecyclerView.scrollToPosition(mMessageBeanList.size() - 1);
            }
        });
    }
}
Note: Some coding is required to display the chat message on the screen. The coding is not explained here. You can use this demo code for reference.

Build And Test on Devices

Now let’s run the application!

In Android Studio, make sure that your Android devices are plugged in or that you can use two emulators, and click Run.

Done!

Congratulations! You have learned how to implement the live chat functionality in your applications. Thanks for following along. I hope you’ll enjoy exploring more features in the Agora Video SDK and the PubNub Messaging SDK.”

Want to build Real-Time Engagement apps?

Get started with 10,000 free minutes today!

If you have questions, please call us at 408-879-5885. We’d be happy to help you add voice or video chat, streaming and messaging into your apps.


Stay inspired by accessing all RTE2020 session recordings. Gain access to innovative Real-Time-Engagement content and start innovating today.