Adding a message counter for the Chat SDK to your Android app
With the release of the Chat SDK v2 in April of 2020, many of you may be asking where the floating message counter went. In Chat SDK v1, the counter showed users how many new messages they'd received while not on the Chat screen. We decided to move away from this pattern in Chat SDK v2 for a number of reasons. The primary reason is that providing a floating button directly in apps caused a lot of design issues that quickly became hard for integrators to resolve.
But there's good news. Chat SDK v2 has the ability to retrieve the data that you need to create your own message counter button using the following steps for Android.
Getting started
This tutorial assumes you already have some knowledge of how the Chat SDK is embedded and implemented. If you haven't embedded the SDK before, the quick start guide and the documentation would be good resources to use before progressing through the tutorial.
This guide gives a brief walkthrough of the following code in the chat_v2_message_counter_sample app on GitHub: Sample code.
Observing the chat state
Consider the following code block:
public UnreadMessageCounter(UnreadMessageCounterListener unreadMessageCounterListener) {
this.unreadMessageCounterListener = unreadMessageCounterListener;
Chat.INSTANCE.providers().chatProvider().observeChatState(new ObservationScope(), new Observer<ChatState>() {
@Override
public void update(ChatState chatState) {
if (chatState != null && !chatState.getChatLogs().isEmpty()) {
if (shouldCount && lastReadChatLogId != null) {
updateCounter(chatState.getChatLogs(), lastReadChatLogId);
}
lastChatLogId = chatState.getChatLogs().get(
chatState.getChatLogs().size() - 1
).getId();
}
}
});
}
The UnreadMessageCounter.class contains an implementation of a ChatState observer in the class constructor. This observer will post updates on any changes made to the ChatState as long as it's active.
You can use this to keep track of the incoming ChatLogs and update your counter while also keeping track of the last received message ID.
Connecting to the websocket
The next and most important part is ensuring that you have an open connection to the WebSocket when the MessagingActivity is no longer being displayed. The code sample linked above uses a very simple method to start the counter logic, save the last chat log received as the last read, and open the web socket connection.
public void startCounter() {
shouldCount = true;
lastReadChatLogId = lastChatLogId;
Chat.INSTANCE.providers().connectionProvider().connect();
}
We don't currently offer any UI lifecycle events so calling this method from within your own app will depend on your implementation rather than updates from a lifecycle observer.
Once the connection is active, the websocket will continue to receive messages as if the chat activity were started.
Note: You will not receive push notifications while the socket is open.
Counting unread messages
Once you have an active WebSocket connection and an observer to receive ChatState changes, you can track the number of messages you've received since the user last saw the Messaging screen.
synchronized private void updateCounter(List<ChatLog> chatLogs, String lastReadId) {
for (ChatLog chatLog : chatLogs) {
if (chatLog.getId().equals(lastReadId)) {
int lastReadIndex = chatLogs.indexOf(chatLog);
List<ChatLog> unreadLogs = chatLogs.subList(lastReadIndex, chatLogs.size() - 1);
unreadMessageCounterListener.onUnreadCountUpdated(unreadLogs.size());
break; }
}
}
The example finds the index of the last read chat log in the list of chat logs and creates a sublist of all logs received since then. It then posts the size of that sublist to the listener.
Expanding upon this implementation
It should be possible to expand upon this simple implementation to suit your own needs. You could use Android’s LiveData interfaces to post updates to observers when the unread counter has been incremented. You could also use background services to control the connection to the WebSocket. However, these are outside the scope of this guide. Hopefully, the basic implementation here will help you implement a more complex version that suits your needs.