Receive real-time messages, fetch missed and unread messages, retrieve message history, search messages, and get unread counts using the CometChat Android SDK.
Register a MessageListener to receive incoming messages as they arrive. For every activity or fragment you wish to receive messages in, register the listener using addMessageListener(). We suggest adding it in the onResume() method.
Java
Kotlin
private String listenerID = "UNIQUE_LISTENER_ID";CometChat.addMessageListener(listenerID, new CometChat.MessageListener() { @Override public void onTextMessageReceived(TextMessage textMessage) { Log.d(TAG, "Text message received successfully: " + textMessage.toString()); } @Override public void onMediaMessageReceived(MediaMessage mediaMessage) { Log.d(TAG, "Media message received successfully: " + mediaMessage.toString()); } @Override public void onCustomMessageReceived(CustomMessage customMessage) { Log.d(TAG, "Custom message received successfully: " + customMessage.toString()); }});
val listenerID:String = "UNIQUE_LISTENER_ID"CometChat.addMessageListener(listenerID, object : MessageListener() { override fun onTextMessageReceived(textMessage: TextMessage) { Log.d(TAG, "Text message received successfully: $textMessage") } override fun onMediaMessageReceived(mediaMessage: MediaMessage) { Log.d(TAG, "Media message received successfully: $mediaMessage") } override fun onCustomMessageReceived(customMessage: CustomMessage) { Log.d(TAG, "Custom message received successfully: $customMessage") }})
Parameter
Description
listenerID
An ID that uniquely identifies that listener. We recommend using the activity or fragment name
Remove the listener when you no longer need it. Typically, this can be added in the onPause() method.
val listenerID:String = "UNIQUE_LISTENER_ID"CometChat.removeMessageListener(listenerID)
Always remove listeners when they’re no longer needed (e.g., in onPause()). Failing to do so can cause memory leaks and duplicate event handling.
As a sender, you will not receive your own message in a real-time message event. However, if a user is logged-in using multiple devices, they will receive an event for their own message in other devices.
Fetch messages that arrived while your app was offline. Use getLastDeliveredMessageId() to find where you left off, then call fetchNext() to get everything after that point. Call fetchNext() repeatedly on the same request object to paginate.
One-on-One
Group
Java
Kotlin
private int limit = 30;private int latestId = CometChat.getLastDeliveredMessageId();private String UID = "cometchat-uid-1";MessagesRequest messagesRequest = new MessagesRequest.MessagesRequestBuilder() .setMessageId(latestId) .setLimit(limit) .setUID(UID) .build();messagesRequest.fetchNext(new CometChat.CallbackListener<List<BaseMessage>>() { @Override public void onSuccess(List<BaseMessage> list) { for (BaseMessage message : list) { if (message instanceof TextMessage) { Log.d(TAG, "Text message received successfully: " + ((TextMessage) message).toString()); } else if (message instanceof MediaMessage) { Log.d(TAG, "Media message received successfully: " + ((MediaMessage) message).toString()); } } } @Override public void onError(CometChatException e) { Log.d(TAG, "Message fetching failed with exception: " + e.getMessage()); }});
lateinit var messagesRequest: MessagesRequestval latestId = CometChat.getLastDeliveredMessageId()val limit: Int = 30val UID: String = "cometchat-uid-1"val messagesRequest = MessagesRequestBuilder() .setMessageId(latestId) .setLimit(limit) .setUID(UID) .build()messagesRequest.fetchNext(object : CallbackListener<List<BaseMessage?>>() { override fun onSuccess(list: List<BaseMessage?>) { for (message in list) { if (message is TextMessage) { Log.d( TAG, "Text message received successfully: " + message.toString() ) } else if (message is MediaMessage) { Log.d( TAG, "Media message received successfully: " + message.toString() ) } } } override fun onError(e: CometChatException) { Log.d(TAG, "Message fetching failed with exception: " + e.message) }})
Java
Kotlin
private int limit = 30;private int latestId = CometChat.getLastDeliveredMessageId();private String GUID = "cometchat-guid-1";MessagesRequest messagesRequest = new MessagesRequest.MessagesRequestBuilder() .setMessageId(latestId) .setLimit(limit) .setGUID(GUID) .build();messagesRequest.fetchNext(new CometChat.CallbackListener<List<BaseMessage>>() { @Override public void onSuccess(List<BaseMessage> list) { for (BaseMessage message : list) { if (message instanceof TextMessage) { Log.d(TAG, "Text message received successfully: " + ((TextMessage) message).toString()); } else if (message instanceof MediaMessage) { Log.d(TAG, "Media message received successfully: " + ((MediaMessage)message).toString()); } } } @Override public void onError(CometChatException e) { Log.d(TAG, "Message fetching failed with exception: " + e.getMessage()); }});
lateinit var messagesRequest: MessagesRequestval latestId = CometChat.getLastDeliveredMessageId()val limit: Int = 30val GUID: String = "cometchat-uid-1"messagesRequest = MessagesRequestBuilder() .setMessageId(latestId) .setLimit(limit) .setGUID(GUID) .build()messagesRequest.fetchNext(object : CallbackListener<List<BaseMessage?>>() { override fun onSuccess(list: List<BaseMessage?>) { for (message in list) { if (message is TextMessage) { Log.d( TAG, "Text message received successfully: " + message.toString() ) } else if (message is MediaMessage) { Log.d( TAG, "Media message received successfully: " + message.toString() ) } } } override fun onError(e: CometChatException) { Log.d(TAG, "Message fetching failed with exception: " + e.message) }})
Fetch unread messages by adding setUnread(true) to the builder. Use fetchPrevious() to retrieve them.
One-on-One
Group
Java
Kotlin
String UID = "cometchat-uid-1";MessagesRequest messagesRequest = new MessagesRequest.MessagesRequestBuilder() .setUnread(true) .setLimit(20) .setUID(UID) .build();messagesRequest.fetchPrevious(new CometChat.CallbackListener<List<BaseMessage>>() { @Override public void onSuccess(List<BaseMessage> list) { for (BaseMessage message : list) { if (message instanceof TextMessage) { Log.d(TAG, "Text message received successfully: " +((TextMessage) message).toString()); } else if (message instanceof MediaMessage) { Log.d(TAG, "Media message received successfully: " +((MediaMessage) message).toString()); } } } @Override public void onError(CometChatException e) { Log.d(TAG, "Message fetching failed with exception: " + e.getMessage()); }});
val UID:String = "cometchat-uid-1"val messagesRequest = MessagesRequestBuilder() .setUnread(true) .setLimit(20) .setUID(UID) .build()messagesRequest.fetchPrevious(object : CallbackListener<List<BaseMessage?>>() { override fun onSuccess(list: List<BaseMessage?>) { for (message in list) { if (message is TextMessage) { Log.d(TAG, "Text message received successfully: $message") } else if (message is MediaMessage) { Log.d(TAG, "Media message received successfully: $message") } } } override fun onError(e: CometChatException) { Log.d(TAG, "Message fetching failed with exception: " + e.message) }})
Java
Kotlin
String GUID = "cometchat-guid-1";MessagesRequest messagesRequest = new MessagesRequest.MessagesRequestBuilder() .setUnread(true) .setLimit(20) .setGUID(GUID) .build();messagesRequest.fetchPrevious(new CometChat.CallbackListener<List<BaseMessage>>() { @Override public void onSuccess(List<BaseMessage> list) { for (BaseMessage message : list) { if (message instanceof TextMessage) { Log.d(TAG, "Text message received successfully: " + ((TextMessage) message).toString()); } else if (message instanceof MediaMessage) { Log.d(TAG, "Media message received successfully: " + ((MediaMessage)message).toString()); } } } @Override public void onError(CometChatException e) { Log.d(TAG, "Message fetching failed with exception: " + e.getMessage()); }});
val GUID:String = "cometchat-guid-1"val messagesRequest = MessagesRequestBuilder() .setUnread(true) .setLimit(20) .setGUID(GUID) .build()messagesRequest.fetchPrevious(object : CallbackListener<List<BaseMessage?>>() { override fun onSuccess(list: List<BaseMessage?>) { for (message in list) { if (message is TextMessage) { Log.d(TAG, "Text message received successfully: $message") } else if (message is MediaMessage) { Log.d(TAG, "Media message received successfully: $message") } } } override fun onError(e: CometChatException) { Log.d(TAG, "Message fetching failed with exception: " + e.message) }})
The list of messages received is in the form of objects of BaseMessage class. A BaseMessage can either be an object of the TextMessage, MediaMessage, CustomMessage, Action or Call class. You can use the instanceOf operator to check the type of object.
Fetch the full conversation history using fetchPrevious(). Call it repeatedly on the same request object to paginate — useful for implementing upward scrolling.
One-on-One
Group
Java
Kotlin
private int limit = 30;private String UID = "cometchat-uid-1"MessagesRequest messagesRequest = new MessagesRequest.MessagesRequestBuilder() .setLimit(limit) .setUID(UID) .build();messagesRequest.fetchPrevious(new CometChat.CallbackListener<List<BaseMessage>>() { @Override public void onSuccess(List<BaseMessage> list) { for (BaseMessage message : list) { if (message instanceof TextMessage) { Log.d(TAG, "Text message received successfully: " + ((TextMessage) message).toString()); } else if (message instanceof MediaMessage) { Log.d(TAG, "Media message received successfully: " + ((MediaMessage)message).toString()); } } } @Override public void onError(CometChatException e) { Log.d(TAG, "Message fetching failed with exception: " + e.getMessage()); }});
val limit: Int = 30val UID: String = "cometchat-uid-1"val messagesRequest = MessagesRequestBuilder() .setLimit(limit) .setUID(UID) .build()messagesRequest.fetchPrevious(object : CallbackListener<List<BaseMessage?>>() { override fun onSuccess(list: List<BaseMessage?>) { for (message in list) { if (message is TextMessage) { Log.d(TAG, "Text message received successfully: $message") } else if (message is MediaMessage) { Log.d(TAG, "Media message received successfully: $message") } } } override fun onError(e: CometChatException) { Log.d(TAG, "Message fetching failed with exception: " + e.message) }})
Java
Kotlin
private int limit = 30;private String GUID = "cometchat-guid-1"MessagesRequest messagesRequest = new MessagesRequest.MessagesRequestBuilder() .setLimit(limit) .setGUID(GUID) .build();messagesRequest.fetchPrevious(new CometChat.CallbackListener<List<BaseMessage>>() { @Override public void onSuccess(List<BaseMessage> list) { for (BaseMessage message : list) { if (message instanceof TextMessage) { Log.d(TAG, "Text message received successfully: " + ((TextMessage) message).toString()); } else if (message instanceof MediaMessage) { Log.d(TAG, "Media message received successfully: " + ((MediaMessage)message).toString()); } } } @Override public void onError(CometChatException e) { Log.d(TAG, "Message fetching failed with exception: " + e.getMessage()); }});
val limit: Int = 30val GUID: String = "cometchat-guid-1"val messagesRequest = MessagesRequestBuilder() .setLimit(limit) .setGUID(GUID) .build()messagesRequest.fetchPrevious(object : CallbackListener<List<BaseMessage?>>() { override fun onSuccess(list: List<BaseMessage?>) { for (message in list) { if (message is TextMessage) { Log.d(TAG, "Text message received successfully: $message") } else if (message is MediaMessage) { Log.d(TAG, "Media message received successfully: $message") } } } override fun onError(e: CometChatException) { Log.d(TAG, "Message fetching failed with exception: ${e.message}") }})
Add setSearchKeyword() to the builder to filter messages by keyword.
One-on-One
Group
Java
Kotlin
private int limit = 30;private String UID = "cometchat-uid-1";MessagesRequest messagesRequest = new MessagesRequest.MessagesRequestBuilder().setSearchKeyword("Hello").setUID(UID).setLimit(limit).build();messagesRequest.fetchPrevious(new CometChat.CallbackListener<List<BaseMessage>>() { @Override public void onSuccess(List<BaseMessage> list) { for (BaseMessage message : list) { if (message instanceof TextMessage) { Log.d(TAG, "Text message received successfully: " + ((TextMessage) message).toString()); } else if (message instanceof MediaMessage) { Log.d(TAG, "Media message received successfully: " + ((MediaMessage)message).toString()); } } } @Override public void onError(CometChatException e) { Log.d(TAG, "Message fetching failed with exception: " + e.getMessage()); }});
val limit: Int = 30val UID: String = "cometchat-uid-1"val messagesRequest = MessagesRequestBuilder().setSearchKeyword("Hello").setUID(UID).setLimit(limit).build()messagesRequest.fetchPrevious(object : CallbackListener<List<BaseMessage?>>() { override fun onSuccess(list: List<BaseMessage?>) { for (message in list) { if (message is TextMessage) { Log.d(TAG, "Text message received successfully: $message") } else if (message is MediaMessage) { Log.d(TAG, "Media message received successfully: $message") } } } override fun onError(e: CometChatException) { Log.d(TAG, "Message fetching failed with exception: ${e.message}") }})
Java
Kotlin
private int limit = 30;private String GUID = "cometchat-guid-1";MessagesRequest messagesRequest = new MessagesRequest.MessagesRequestBuilder().setSearchKeyword("Hello").setGUID(GUID).setLimit(limit).build();messagesRequest.fetchPrevious(new CometChat.CallbackListener<List<BaseMessage>>() { @Override public void onSuccess(List<BaseMessage> list) { for (BaseMessage message : list) { if (message instanceof TextMessage) { Log.d(TAG, "Text message received successfully: " + ((TextMessage) message).toString()); } else if (message instanceof MediaMessage) { Log.d(TAG, "Media message received successfully: " + ((MediaMessage)message).toString()); } } } @Override public void onError(CometChatException e) { Log.d(TAG, "Message fetching failed with exception: " + e.getMessage()); }});
val limit = 30val GUID = "cometchat-guid-1"val messagesRequest = MessagesRequestBuilder().setSearchKeyword("Hello").setGUID(GUID).setLimit(limit).build()messagesRequest.fetchPrevious(object : CallbackListener<List<BaseMessage?>>() { override fun onSuccess(list: List<BaseMessage?>) { for (message in list) { if (message is TextMessage) { Log.d(TAG, "Text message received successfully: $message") } else if (message is MediaMessage) { Log.d(TAG, "Media message received successfully: $message") } } } override fun onError(e: CometChatException) { Log.d(TAG, "Message fetching failed with exception: ${e.message}") }})
By default, search only matches message text. With Conversation & Advanced Search enabled, it also matches file names, mentions, and MIME types.
Feature
Basic Search
Advanced Search
Text search
✅
✅
File name search
❌
✅
Mentions search
❌
✅
Mime type search
❌
✅
Conversation & Advanced Search is available on Advanced and Customplans. Enable it from the CometChat Dashboard under Chats → Settings → General Configuration.
CometChat provides several methods to get unread counts at different scopes. All return results via a callback listener with a HashMap mapping IDs to counts.Each method accepts an optional boolean parameter to exclude messages from blocked users.
The BaseMessage object returned by SDK methods contains the following fields. TextMessage, MediaMessage, and CustomMessage extend this base structure with additional type-specific fields.