Skip to main content

Per-Message Read Receipt Feature

tip
  • The per-message read receipt feature (Message Read V5) is supported starting from SDK version 5.20.0.
  • Before using this feature, please submit a ticket to enable per-message read receipts. Once enabled, the One-to-One and Group Read Receipt feature will become unavailable.

The per-message read receipt feature (Message Read V5) allows setting read status for each received message individually, supporting both one-to-one and group conversation types.

Sending Messages

To support read receipts, set needReceipt to true in the Message object when sending a message.

Example Code

Message message = ...;
message.setNeedReceipt(true); // Set to true

RongCoreClient.getInstance().sendMessage(message, null, null, new IRongCoreCallback.ISendMessageCallback() {
/**
* Pre-send callback, triggered when the message has been stored in the database.
* @param message The stored message object.
*/
@Override
public void onAttached(Message message) {
}
/**
* Message sent successfully.
* @param message The successfully sent message object.
*/
@Override
public void onSuccess(Message message) {
}
/**
* Message failed to send.
* @param message The failed message object.
* @param errorCode Specific error code.
*/
@Override
public void onError(Message message, IRongCoreEnum.CoreErrorCode coreErrorCode) {
}
});

New Message Object Attributes

ParameterTypeDescription
needReceiptBooleanWhether to support read receipts
sentReceiptBooleanWhether read receipt has been sent

Sending Read Receipts

After reading a message, the recipient must actively send a read receipt to the sender by calling the sendReadReceiptResponseV5() method with the conversation identifier (identifier) and message UID.

ParameterTypeDescription
identifierConversationIdentifierConversation identifier for the message
messageUIdsListList of message UIDs requiring read receipts
callbackIRongCoreCallback.OperationCallbackResult callback

Example Code

ConversationIdentifier identifier = ConversationIdentifier.obtain(
Conversation.ConversationType.GROUP,
"targetId",
""
);
List<String> messageUIds = new ArrayList<>();
messageUIds.add("MessageUID");

RongCoreClient.getInstance().sendReadReceiptResponseV5(identifier, messageUIds, new IRongCoreCallback.OperationCallback() {
@Override
public void onSuccess() {
}
@Override
public void onError(IRongCoreEnum.CoreErrorCode coreErrorCode) {
}
});

Receiving Read Receipt Callbacks

After a recipient sends a read receipt, the sender will receive a callback. Developers can register a read receipt listener addMessageReadReceiptV5Listener() and implement the onMessageReceiptResponse() method to receive receipt information.

ParameterTypeDescription
responsesListList of read receipt responses ReadReceiptResponseV5

Example Code

RongCoreClient.getInstance().addMessageReadReceiptV5Listener(new IRongCoreListener.MessageReadReceiptV5Listener() {
@Override
public void onMessageReceiptResponse(List<ReadReceiptResponseV5> responses) {
}
});

Retrieving Message Read Receipt Information

Senders can query read receipt information for specific messages using the getMessageReadReceiptInfoV5() interface by providing the conversation identifier (identifier) and message UID.

ParameterTypeDescription
identifierConversationIdentifierConversation identifier for the message
messageUIdsListList of message UIDs to query
callbackIRongCoreCallback.ResultCallbackResult callback

In the result callback, infoV5s is a list of ReadReceiptInfoV5 objects containing:

ParameterTypeDescription
messageUIdStringMessage UID
unreadCountIntUnread count
readCountIntRead count
totalCountIntTotal count

Example Code

ConversationIdentifier identifier = ConversationIdentifier.obtain(
Conversation.ConversationType.GROUP,
"targetId",
""
);
List<String> messageUIds = new ArrayList<>();
messageUIds.add("MessageUID");

RongCoreClient.getInstance().getMessageReadReceiptInfoV5(identifier, messageUIds, new IRongCoreCallback.ResultCallback<List<ReadReceiptInfoV5>>() {
@Override
public void onSuccess(List<ReadReceiptInfoV5> infoV5s) {
}
@Override
public void onError(IRongCoreEnum.CoreErrorCode e) {
}
});

Batch Retrieving Read Receipt Information for Multiple Conversations

Senders can batch query read receipt information for messages across multiple conversations using the getMessageReadReceiptInfoV5ByIdentifiers() interface.

Parameter Description

ParameterTypeDescription
identifiersListList of message identifiers MessageIdentifier
callbackIRongCoreCallback.ResultCallbackResult callback

In the result callback, infoList is a list of ReadReceiptInfoV5 objects containing:

ParameterTypeDescription
messageUIdStringMessage UID
unreadCountIntUnread count
readCountIntRead count
totalCountIntTotal count

Example Code

List<MessageIdentifier> identifiers = new ArrayList<>();
MessageIdentifier identifier = new MessageIdentifier();
ConversationIdentifier conversationIdentifier = ConversationIdentifier.obtain(Conversation.ConversationType.PRIVATE, "targetId", "");
identifier.setIdentifier(conversationIdentifier);
identifier.setMessageUId("messageUId");
identifiers.add(identifier);

RongCoreClient.getInstance().getMessageReadReceiptInfoV5ByIdentifiers(identifiers, new IRongCoreCallback.ResultCallback<List<ReadReceiptInfoV5>>() {
@Override
public void onSuccess(List<ReadReceiptInfoV5> infoV5s) {
}
@Override
public void onError(IRongCoreEnum.CoreErrorCode e) {
}
});

Paginated Retrieval of Read Receipt User List

Paginated Retrieval of Read Receipt User List

The message sender can use the getMessagesReadReceiptUsersByPageV5() interface to paginate through the list of users who have read receipts for a message.

ParameterTypeDescription
identifierConversationIdentifierConversation identifier for the message
messageUIdStringUnique message ID
optionReadReceiptUsersOptionPagination configuration
callbackIRongCoreCallback.ResultCallbackResult callback

The paginated result readReceiptUsersResult is encapsulated in ReadReceiptUsersResult, containing:

ParameterTypeDescription
usersListList of queried users (ReadReceiptUser)
pageTokenStringPagination token (empty means no more pages)
totalCountIntTotal user count

Sample Code

ConversationIdentifier identifier = ConversationIdentifier.obtain(
Conversation.ConversationType.GROUP,
"targetId",
""
);
ReadReceiptUsersOption option = new ReadReceiptUsersOption();
option.setPageToken("PAGE_TOKEN"); // Can be empty for first call
option.setPageCount(20);
option.setOrder(ReadReceiptUsersOption.Order.DESCEND);
option.setReadStatus(ReadReceiptUsersOption.ReadStatus.UNREAD);

RongCoreClient.getInstance().getMessagesReadReceiptUsersByPageV5(identifier, "messageUId", option, new IRongCoreCallback.ResultCallback<ReadReceiptUsersResult>() {
@Override
public void onSuccess(ReadReceiptUsersResult readReceiptUsersResult) {
}
@Override
public void onError(IRongCoreEnum.CoreErrorCode e) {
}
});


## Retrieving Read Receipt Information for Specified Users

The message sender can use the `getMessagesReadReceiptByUsersV5()` interface to retrieve read receipt information for specified users.

| Parameter | Type | Description |
| :---------- | :----------------------- | :---------------------- |
| `identifier`| `ConversationIdentifier` | Conversation identifier for the message |
| `messageUId`| `String` | Unique message ID |
| `userIds` | `List` | List of user IDs |
| `callback` | `IRongCoreCallback.ResultCallback` | Result callback |

The result `readReceiptUsersResult` is encapsulated in `ReadReceiptUsersResult`, containing:

| Parameter | Type | Description |
| :---------- | :------- | :---------------------------------- |
| `users` | `List` | List of queried users (`ReadReceiptUser`) |
| `pageToken` | `String` | Pagination token (not applicable for this interface) |
| `totalCount`| `Int` | Total user count (not applicable for this interface) |


### Sample Code

```java
ConversationIdentifier identifier = ConversationIdentifier.obtain(
Conversation.ConversationType.GROUP,
"targetId",
""
);
List<String> userIds = new ArrayList<>();
userIds.add("UserId1");

RongCoreClient.getInstance().getMessagesReadReceiptByUsersV5(identifier, "messageUId", userIds, new IRongCoreCallback.ResultCallback<ReadReceiptUsersResult>() {
@Override
public void onSuccess(ReadReceiptUsersResult readReceiptUsersResult) {
}
@Override
public void onError(IRongCoreEnum.CoreErrorCode e) {
}
});