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
- Basic knowledge of Java and the Android SDK
- Agora.io account
- PubNub developer account
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<PNPublishResult>() {
@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.”