logo
In-app Chat
SDK Error Codes
Powered Byspreading
On this page

Read receipts


Overview

Message reading receipt helps users know whether other users have read the messages they sent in a session. This feature applies to enterprise office businesses and other scenarios in which the message reading status needs to be known in real time.

This document describes how to use APIs of the In-app Chat SDK to send messages that require a reading receipt, query the receipt status of messages, and set messages as read.

Warning

The In-app Chat SDK supports reading receipts for one-to-one messages and group messages (only common messages and rich media messages) and does not support reading receipts for in-room messages.

Implementation process

The sender sends a message through the In-app Chat SDK and sets the hasReceipt field of ZIMMessageSendConfig to identify whether a reading receipt is required for the message. Based on the receiptStatus field, the receiver determines whether a reading receipt is required for the message or whether the message is read or unread to render different UI effects. The message receiver can use different reading methods based on the scenario.

Send a message that requires a reading receipt

When Client A wants to send a message that requires a reading receipt to Client B:

  1. Client A and Client B log in to the In-app Chat service.
  2. Client A calls the sendMessage or sendMediaMessage API to send a message (common message or rich media message in one-to-one or group chats) to Client B and sets the hasReceipt field of ZIMMessageSendConfig to true.
  3. By listening for related callback (onReceivePeerMessage or onReceiveGroupMessage), Client B receives a message whose receiptStatus is set to PROCESSING.

Set the reading receipt status as read

In this operation, set a message as read and set a session as read are both supported.

Set a message as read

The receiver can set a message that requires a reading receipt from the sender as read. Then, the sender will receive a message read notification.

Warning
  • A single message or a batch of messages are supported. The sender and receiver must be in the same session. Cross-session operations are not supported.

  • To perform operations on the historical messages of the conversation, you need to get the historical messages and determine the receipt status of the historical messages. For details, see Get message history.

  1. Through related callback (onReceivePeerMessage or onReceiveGroupMessage), Client B receives a message that requires a reading receipt from Client A.
  2. Based on the receiptStatus field of the callback, Client B determines the receipt status of the message. If this field is set to PROCESSING, the message is unread. Developers can call the sendMessageReceiptsRead API to set the message as read based on the service logic.
  3. Client B determines whether the setting is successful based on ZIMMessageReceiptsReadSentCallback.
  4. Based on onMessageReceiptChanged of ZIMEventHandler, Client A receives a callback notification, indicating that the message is set as read. Developers can implement the service logic of setting the message as read on Client A based on this callback.

Set a session as read

The receiver can set all messages received from the sender in a specified session as read.

Warning
  • The In-app Chat SDK supports this feature only in one-to-one chats.

  • This feature takes effect only on messages received before setting the feature.

  • It is recommended that this feature be used when a user switches from the session list page to a session. It is not recommended that this feature be used together with the sendMessageReceiptsRead API on a message chat page.

  • To perform operations on the historical messages of the conversation, you need to get the historical messages and determine the receipt status of the historical messages. For details, see Get message history.

  1. Based on the receiptStatus field of the onReceivePeerMessage callback, Client B determines the receipt status of the message. If this field is set to PROCESSING, the message is unread. Developers can call the sendConversationMessageReceiptRead API to set all messages sent by Client A in the session as read based on the service logic.
  2. Client B determines whether the setting is successful based on ZIMConversationMessageReceiptReadSentCallback .
  3. Based on onConversationMessageReceiptChanged of ZIMEventHandler , Client A receives a callback notification, indicating that all messages in the session are set as read. Developers can implement the logic of setting all messages sent from the sender in the session as read based on this callback. Developers can implement the service logic of knowing all sent messages in a session are set as read by Client B on Client A based on this callback.

More features

Batch query the message receipt status, number of users who have read the message, and number of users who have not read the message

To query the message receipt status, the number of users who have read the message, and the number of users who have not read the message of a message or a batch of messages, call the queryMessageReceiptsInfo API. Call ZIMMessageReceiptsInfoQueriedCallback to obtain related information.

Warning
  • If messages sent by other users are queried, the number of users who have read the message and the number of users who have not read the message are 0.

  • To perform operations on the historical messages of the conversation, you need to get the historical messages and determine the receipt status of the historical messages. For details, see Get message history.

Query the list of members who have or have not read a group message

The In-app Chat SDK supports querying the list of members who have or have not read a group message.

Query the list of members who have read a group message

To query the list of members who have read a group message, call the queryGroupMessageReceiptReadMemberList API.

Warning

To perform operations on the historical messages of the conversation, you need to get the historical messages and determine the receipt status of the historical messages. For details, see Get message history.

Query the list of members who have not read a group message

To query the list of members who have not read a group message, call the queryGroupMessageReceiptUnreadMemberList API.

Warning
  • If the SDK version is older than 2.16.0, when the number of group members is greater than 100, this API will not return the list of members who have not read a group message. To use this feature, contact ZEGOCLOUD technical support.

  • To perform operations on the historical messages of the conversation, you need to get the historical messages and determine the receipt status of the historical messages. For details, see Get message history.

Sample code

Untitled
// 1. Create an In-app Chat object and introduce the appID, appSign, and Application in Android.
ZIMAppConfig appConfig = new ZIMAppConfig();
appConfig.appID = 12345;    // Enter the appID you applied for from the ZEGOCLOUD Admin Console.
appConfig.appSign = "appSign";    // Enter the appSign you applied for from the ZEGOCLOUD Admin Console.
zim = ZIM.create(appConfig, application);

// 2. Log in to the In-app Chat service.
ZIMUserInfo zimUserInfo = new ZIMUserInfo();
zimUserInfo.userID = "xxxx";
zimUserInfo.userName = "xxxx";
zim.login(zimUserInfo, new ZIMLoggedInCallback() {
    @Override
    public void onLoggedIn(ZIMError error) {
          // Developers can determine whether the login is successful based on ZIMError.          
    }
 });

zim.setEventHandler(new ZIMEventHandler() {
    @Override
    public void onReceivePeerMessage(ZIM zim, ArrayList<ZIMMessage> messageList,
                                             String fromUserID) {
        // Receive a one-to-one message.
    }
    @Override
    public void onMessageReceiptChanged(ZIM zim, ArrayList<ZIMMessageReceiptInfo> infos) {
        // The other user sets a message as read.
    }
    @Override
    public void onConversationMessageReceiptChanged(ZIM zim, ArrayList<ZIMMessageReceiptInfo> infos) {
        // The other user sets all messages in a session as read.
    }
})

String conversationID = "xxx" ; // The session ID

// 3. User A sends a message that requires a reading receipt. A text one-to-one message is used as an example.

ZIMTextMessage message = new ZIMTextMessage("test");
ZIMMessageSendConfig sendConfig = new ZIMMessageSendConfig();
sendConfig.hasReceipt = true;    // Set that the messages require a reading receipt.
zim.sendMessage(message, conversationID, ZIMConversationType.PEER,sendConfig, new ZIMMessageSentCallback() {
            @Override
            public void onMessageAttached(ZIMMessage message) {}
            @Override
            public void onMessageSent(ZIMMessage message, ZIMError errorInfo) {
                if (errorInfo.code == ZIMErrorCode.SUCCESS) {
                    // This indicates that the message is sent successfully. receiptStatus of the message is set to PROCESSING. The service layer can display the logic that a message is unread based on this flag.
                }
            }
        });

// 4. User B receives the message that requires a reading receipt and sets the message as read by calling any of the following APIs.

// 4.1 Set a message as read

List<ZIMMessage> messages = new ArrayList<>();
messages.add(message);
zim.sendMessageReceiptsRead(messages, conversationID, ZIMConversationType.PEER, 
        new ZIMMessageReceiptsReadSentCallback() {
            @Override
            public void onMessageReceiptsReadSent(String conversationID, ZIMConversationType conversationType, 
ArrayList<Long> errorMessageIDs, ZIMError errorInfo) {
             if (errorInfo.code == ZIMErrorCode.SUCCESS) {
                // Callback for setting a message as read.
             }
            }
        });

// 4.2 Set a session as read

zim.sendConversationMessageReceiptRead(conversationID, ZIMConversationType.PEER, 
            new ZIMConversationMessageReceiptReadSentCallback() {
            @Override
            public void onConversationMessageReceiptReadSent(String conversationID, 
                ZIMConversationType conversationType, ZIMError errorInfo) {
                if (errorInfo.code == ZIMErrorCode.SUCCESS) {
                    // A session is read. Developers can listen for this callback to set all messages sent by the sender in this session as read.
                }
            }
        });

// 5. (Optional) Batch query the message receipt status, number of users who have read the message, and number of users who have not read the message.

List<ZIMMessage> messages = new ArrayList<>();
messages.add(message);
zim.queryMessageReceiptsInfo(messages, conversationID, ZIMConversationType.PEER, new ZIMMessageReceiptsInfoQueriedCallback() {
            @Override
            public void onMessageReceiptsInfoQueried(ArrayList<ZIMMessageReceiptInfo> infos, 
                ArrayList<Long> errorMessageIDs, ZIMError errorInfo) {
                if (errorInfo.code == ZIMErrorCode.SUCCESS) {
                    // The status and quantity of this batch of messages are queried, and the corresponding message ID and count are obtained by traversing the information.
                }
            }
        });
// 6. (Optional) Query the list of members who have or have not read a group message.

// 6.1 The list of members who have read a group message
ZIMGroupMessageReceiptMemberQueryConfig config = new ZIMGroupMessageReceiptMemberQueryConfig();
config.nextFlag = 0;    // The query flag. It is set to 0 in the first query. In subsequent queries, it is set to the flag returned in the callback.
config.count = 10;    // The user quantity to be queried.
zim.queryGroupMessageReceiptReadMemberList(message, groupID, config, 
    new ZIMGroupMessageReceiptMemberListQueriedCallback() {
            @Override
            public void onGroupMessageReceiptMemberListQueried(String groupID, ArrayList<ZIMGroupMemberInfo> userList,
             int nextFlag, ZIMError errorInfo) {
                if (errorInfo.code == ZIMErrorCode.SUCCESS) {
                   // The corresponding member list is queried.
                }
            }
        });

// 6.2 The list of members who have not read a group message
ZIMGroupMessageReceiptMemberQueryConfig config = new ZIMGroupMessageReceiptMemberQueryConfig();
config.nextFlag = 0;    // The query flag. It is set to 0 in the first query. In subsequent queries, it is set to the flag returned in the callback.
config.count = 10;    // The user quantity to be queried.

zim.queryGroupMessageReceiptUnreadMemberList(message, groupID, config, 
    new ZIMGroupMessageReceiptMemberListQueriedCallback() {
            @Override
            public void onGroupMessageReceiptMemberListQueried(String groupID, ArrayList<ZIMGroupMemberInfo> userList,
             int nextFlag, ZIMError errorInfo) {
                if (errorInfo.code == ZIMErrorCode.SUCCESS) {
                   // The corresponding member list is queried.
                }
            }
        });
1
Copied!

Previous

Recall messages

Next

Set message extension field