跳到主要内容

单群聊已读回执

从 1.3.0 版本开始支持该功能。

已读回执功能可以让发送方知道消息是否被对方已读。

  • 在单聊场景下,当接收方已读消息后,可以主动发送已读回执给发送方,发送方通过监听已读回执消息来获得已读通知。
  • 在群聊场景下,当一条消息发送到群组后,发送方可以在消息发送完成后主动发起已读回执请求。群组中的其他成员在读到这条消息后,可以对请求进行响应。发送方通过监听已读回执响应结果来获知哪些群成员已读了这条消息。

SDK 提供了一个已读回执监听器 MessageReadReceiptListener,用于处理单聊、群聊已读回执相关的事件通知。

单聊已读回执

单聊具体流程描述:

  1. 发送方发送消息:发送方 App/IMKit 发送任何的记录未读的消息,比如文本、图片等
  2. 接收方进入聊天页面看到最新消息
  3. 接收方发送单聊已读回执(带时间戳):接收方 App/IMKit 将当前会话最后一条消息的 sentTime 调用 IMEngine.sendReadReceiptMessage() 发出去
  4. 发送方接收单聊已读回执,将时间戳前的消息都置为已读:发送方收到单聊已读回执之后, SDK 将时间戳之前的本地消息都置为已读(SentStatus 设置为 Read),然后触发 MessageReadReceiptListener.onMessageReadReceiptReceived
  5. 发送方将聊天页面该回执前的消息变为已读:发送方 App/IMKit 的聊天页面收到 MessageReadReceiptListener.onMessageReadReceiptReceived 之后,把时间戳之前的消息 UI 都置为已读

备注:单聊如何查看消息已读?看 Message SentStatus == Read 代表已读

发送单聊已读回执

消息接收方在阅读过某条消息后,需要主动发送已读回执给发送方。调用 sendReadReceiptMessage 方法时需要传入一个时间戳。可以传入指定消息的发送时间(message.sentTime),或者传入会话最后一条消息的发送时间(conversation.sentTime)。

let conId = new ConversationIdentifier();
conId.conversationType = ConversationType.Private;
conId.targetId = "TestTargetId"; // 按需填写实际的会话 id

// 传入 message.sentTime 或 conversation.sentTime,此处用本地时间做示例
let time = Date.now();

IMEngine.getInstance().sendReadReceiptMessage(conId, time).then(result => {
if (EngineError.Success !== result.code) {
// 失败
return;
}
// 成功
});

单聊已读回执实际是一条已读通知消息,由 SDK 内部构建并发出。回调中返回的 Message 对象的content 属性包含类型为 ReadReceiptMessage 的消息内容体对象。

接收单聊已读回执

发送方需要使用 addMessageReadReceiptListener 设置已读回执监听器,才能在收到单聊已读回执时收到通知。SDK 收到单聊消息的已读回执后,会读取其中携带的时间戳,将本地消息数据库中该单聊会话的早于该时间戳的所有消息的 SentStatus 属性改为 READ,同时触发 MessageReadReceiptListeneronMessageReadReceiptReceived 方法。

let listener: MessageReadReceiptListener = {
onMessageReadReceiptReceived: (message: Message): void => {
// 此处为单聊消息回执回调方法,可在这做回执消息处理
},
onMessageReceiptRequest: (conId: ConversationIdentifier, messageUid: string): void => {

},
onMessageReceiptResponse: (conId: ConversationIdentifier, messageUid: string, respondUserIdList: Map<string, number>): void => {

}
}
IMEngine.getInstance().addMessageReadReceiptListener(listener);

应用程序可以从 onMessageReadReceiptReceived 方法中获取 Message 对象,并从其 content 属性中的消息内容体对象 ReadReceiptMessage 中获取其携带的时间戳。在 UI 展示本端已发送的消息时,可以将早于该时间戳的消息均展示为对方已读。

群聊已读回执

群聊已读回执功能基于消息的全局唯一 ID(UID)。通过在群聊会话中传递消息的 UID,消息发送者可获得一条指定消息的阅读进度和已读用户列表。在群聊会话中,本端发出的消息的 ReadReceiptInfo 属性中记录了该条消息的群组已读回执数据。

群聊已读回执的工作流程如下:

群聊具体流程描述:

  1. 发送方发送消息:发送方 App/IMKit 发送任何的记未读消息,比如文本、图片等
  2. 发送方发送群聊已读回执请求:发送方 App/IMKit 进入聊天页面手动点击回执请求按钮,发送方调用 IMEngine.sendReadReceiptRequest()
  3. 接收方接收群聊已读回执请求:接收方 SDK 接收已读请求,并更新消息的 isReadReceiptMessage 为 true,触发 MessageReadReceiptListener.onMessageReceiptRequest()
  4. 接收方进入聊天页面,遍历所有的消息:接收方 App/IMKit 进入聊天页面,查到当前页面 isReadReceiptMessage 为 true 的消息
  5. 接收方发送群聊已读回执响应:接收方 App/IMKit 过滤聊天页面内所有 (isReadReceiptMessage == true && hasRespond == false) 的消息,调用 IMEngine.sendReadReceiptResponse() 发送已读回执响应,证明接收方这些消息已读过,接收方 SDK 会将这些消息的 hasRespond 设为 true,避免重复调用 sendReadReceiptResponse
  6. 发送方接收群聊已读回执响应:发送方 SDK 接收到已读响应时,将本地消息的 respondUserIdList 更新,然后触发 MessageReadReceiptListener.onMessageReceiptResponse()
  7. 发送方将聊天页面对应消息更新已读状态:发送方 App/IMKit 在对应的聊天页面,找到对应的消息,更新对应的 UI 备注:群聊如何查看消息已读?看 Message ReadReceiptInfo 的具体数据

发起群聊已读回执请求

发送者向群组中发送消息后,必须先主动发起已读回执请求,获取群成员的主动响应,才能获取该条消息的阅读状态。在一个群组会话中,只有消息发送者可以发起群聊已读回执请求。

消息发送完成后,消息发送者使用 sendReadReceiptRequest 方法,传入已发送的 Message 对象,对这条消息发起已读回执请求,SDK 内部会构建并发出一条群聊已读回执请求消息。

// 应该使用发送成功的消息,此处进行了简写
let msg : Message;

IMEngine.getInstance().sendReadReceiptRequest(msg).then(result => {
if (EngineError.Success !== result.code) {
// 失败
return;
}
// 成功
});

接收群聊已读回执请求

群组成员均需要使用 addMessageReadReceiptListener 设置已读回执监听器,才能接收到群组内的已读回执请求。在任意群成员发起已读回执请求后,其他群成员会通过 MessageReadReceiptListeneronMessageReceiptRequest 回调收到已读回执请求。


let listener: MessageReadReceiptListener = {
onMessageReadReceiptReceived: (message: Message): void => {

},
onMessageReceiptRequest: (conId: ConversationIdentifier, messageUid: string): void => {
// 收到群聊消息已读回执请求
},
onMessageReceiptResponse: (conId: ConversationIdentifier, messageUid: string, respondUserIdList: Map<string, number>): void => {

}
}
IMEngine.getInstance().addMessageReadReceiptListener(listener);

onMessageReceiptRequest 方法中会返回消息的 UID,您可以通过 getMessageByUid 方法获取消息对象,用于后续响应已读回执请求。

响应群聊已读回执请求

应用程序可以根据用户的阅读进度,对已读回执请求进行响应。如果一次接收到多个请求,可以批量响应已读回执请求,但一次只能批量响应同一个会话中的已读回执请求。

使用 sendReadReceiptResponse 方法,传入会话类型、群组 ID 和 Message 对象列表,发起已读回执响应。注意会话类型一定是 ConversationType.Group

let conId = new ConversationIdentifier();
conId.conversationType = ConversationType.Group;
conId.targetId = "TestTargetId"; // 按需填写实际的会话 id

// 需要具体的消息,此处进行了简写
let msgArray = new Array<Message>();
let msg : Message;
msgArray.push(msg);

IMEngine.getInstance().sendReadReceiptResponse(conId, msgArray).then(result => {
if (EngineError.Success !== result.code) {
// 失败
return;
}
if (!result.data) {
// 成功的消息体列表为空
return;
}
// 发送响应成功的消息列表
let msgList = result.data as List<Message>;
});

接收群聊已读回执响应

群组内有用户响应成功后,请求发起方会通过 MessageReadReceiptListeneronMessageReceiptResponse 收到通知及响应结果。注意只有请求发起者可以收到响应。

let listener: MessageReadReceiptListener = {
onMessageReadReceiptReceived: (message: Message): void => {

},
onMessageReceiptRequest: (conId: ConversationIdentifier, messageUid: string): void => {

},
onMessageReceiptResponse: (conId: ConversationIdentifier, messageUid: string, respondUserIdList: Map<string, number>): void => {
// 收到对群聊已读回执请求的响应
}
}
IMEngine.getInstance().addMessageReadReceiptListener(listener);

应用程序可以从 onMessageReceiptResponse 方法中获取消息的 UID 和所有已响应的用户列表。在 UI 展示本端发送的该条消息时,可以展示已读人数和具体的已读用户列表。SDK 会在消息的(ReadReceiptInfo)属性中存储该条群聊消息的已读回执数据。