====== 消息管理–管理消息回执 ======
更新时间:2022-09-07
用户在单聊和群聊中发送完信息后,可以查看该信息的送达和已读状态,了解接收方是否及时收到并阅读了信息。
本文介绍如何使用环信即时通讯 IM Flutter SDK 的消息已读回执和送达回执在 app 中实现上述功能。
===== 技术原理 =====
环信即时通讯 IM Flutter SDK 通过 ''%%EMChatManager%%'' 类提供消息已回执功能,回执主要分为两类:已读回执和送达回执。核心方法如下:
* ''%%EMOptions.requireDeliveryAck%%'' 送达回执的全局开关;
* ''%%EMOptions.requireAck%%'' 已读回执的全局开关;
* ''%%EMChatManager.sendConversationReadAck%%'' 发送会话的已读回执;
* ''%%EMChatManager.sendMessageReadAck%%'' 发送单聊消息的已读回执;
* ''%%EMChatManager.sendGroupMessageReadAck%%'' 发送群组消息的已读回执;
实现送达和已读回执的逻辑分别如下:
* 消息送达回执
- 消息发送方在发送消息前通过 ''%%EMOptions.requireDeliveryAck%%'' 开启送达回执功能
- 消息接收方收到消息后,SDK 自动向发送方触发送达回执
- 消息发送方通过监听 ''%%onMessageDelivered%%'' 回调接收消息送达回执
* 会话及消息已读回执
- 消息发送方在发送消息前通话 ''%%EMOptions.requireAck%%'' 开启已读回执功能
- 消息接收方收到消息后,调用 API ''%%SendConversationReadAck%%'' 或 ''%%SendMessageReadAck%%'' 发送会话或消息已读回执
- 消息发送方通过监听 ''%%onConversationRead%%'' 或 ''%%onMessagesRead%%'' 回调接收会话或消息已读回执
===== 前提条件 =====
开始前,请确保满足以下条件:
* 完成 SDK 初始化,并连接到服务器,详见 [[https://docs-im.easemob.com/ccim/flutter/quickstart|快速开始]]。
* 了解环信即时通讯 IM 的使用限制,详见 [[https://docs-im.easemob.com/ccim/limitation|使用限制]]。
* 在群组中实现消息已读回执功能默认不开启。如需使用,请联系商务开通。
===== 实现方法 =====
==== 消息送达回执 ====
- 发送方开启全局送达回执。当接收方收到消息后,SDK 底层会自动进行消息送达回执。
// sdk app key
String appKey = "appKey";
// 开启消息送达回执
bool requireDeliveryAck = true;
EMOptions options = EMOptions(
appKey: appKey,
requireDeliveryAck: requireDeliveryAck,
);
await EMClient.getInstance.init(options);
// 注册监听
EMClient.getInstance.chatManager.addEventHandler(
"UNIQUE_HANDLER_ID",
EMChatEventHandler(
onMessagesDelivered: (messages) {},
),
);
// 移除监听
EMClient.getInstance.chatManager.removeEventHandler("UNIQUE_HANDLER_ID");
==== 消息和会话的已读回执 ====
消息已读回执用于告知单聊或群聊中的用户接收方已阅读其发送的消息。为降低消息已读回执方法的调用次数,SDK 还支持在单聊中使用会话已读回执功能,用于获知接收方是否阅读了会话中的未读消息。
=== 单聊 ===
单聊既支持消息已读回执,也支持会话已读回执。我们建议你按照如下逻辑结合使用两种回执结合使用,减少发送消息已读回执数量。
* 聊天页面未打开时,若有未读消息,进入聊天页面,发送会话已读回执;
* 聊天页面打开时,若收到消息,发送消息已读回执。
== 会话已读回执 ==
参考如下步骤在单聊中实现会话已读回执。
- 开启全局的消息已读回执开关。如果全局设置不开启,消息和会话的相应设置也无法生效。
EMOptions options = EMOptions(
appKey: appKey,
requireAck: true,
);
EMClient.getInstance.init(options);
String convId = "convId";
try {
await EMClient.getInstance.chatManager.sendConversationReadAck(convId);
} on EMError catch (e) {
}
// 注册监听
EMClient.getInstance.chatManager.addEventHandler(
"UNIQUE_HANDLER_ID",
EMChatEventHandler(
onConversationRead: (String from, String to) {},
),
);
// 移除监听
EMClient.getInstance.chatManager.removeEventHandler("UNIQUE_HANDLER_ID");
> 同一用户 ID 登录多设备的情况下,用户在一台设备上发送会话已读回执,服务器会将会话的未读消息数置为 ''%%0%%'',同时其他设备会收到 ''%%onConversationRead%%'' 回调。
== 消息已读回执 ==
参考如下步骤在单聊中实现消息已读回执。
- 开启全局的消息已读回执开关。如果全局设置不开启,消息和会话的相应设置也无法生效。
EMOptions options = EMOptions(
appKey: "appKey",
requireAck: true,
);
EMClient.getInstance.init(options);
// 注册监听
EMClient.getInstance.chatManager.addEventHandler(
"UNIQUE_HANDLER_ID",
EMChatEventHandler(
onMessagesRead: (messages) {},
),
);
// 移除监听
EMClient.getInstance.chatManager.removeEventHandler("UNIQUE_HANDLER_ID");
try {
EMClient.getInstance.chatManager.sendMessageReadAck(msg);
} on EMError catch (e) {
}
==== 群聊 ====
对于群组消息,消息发送方(目前为群主和群管理员)可设置指定消息是否需要已读回执。
- 消息发送方需要知道群组消息是否已读,需要监听 ''%%onGroupMessageRead%%'' 事件。
// 注册监听
EMClient.getInstance.chatManager.addEventHandler(
"UNIQUE_HANDLER_ID",
EMChatEventHandler(
onGroupMessageRead: (groupMessageAcks) {},
),
);
// 移除监听
EMClient.getInstance.chatManager.removeEventHandler("UNIQUE_HANDLER_ID");
// 设置消息类型为群消息
msg.chatType = ChatType.GroupChat;
// 设置本条消息需要群消息回执
msg.needGroupAck = true;
try {
await EMClient.getInstance.chatManager.sendMessage(msg);
} on EMError catch (e) {
}
try {
EMClient.getInstance.chatManager.sendGroupMessageReadAck(msgId, groupId);
} on EMError catch (e) {
}
==== 更多操作 ====
你可以参考如下文档,在项目中实现更多的消息相关功能:
* [[https://docs-im.easemob.com/ccim/flutter/message1|消息概述]];
* [[https://docs-im.easemob.com/ccim/flutter/message2|发送和接收消息]];
* [[https://docs-im.easemob.com/ccim/flutter/message3|管理本地消息数据]];
* [[https://docs-im.easemob.com/ccim/flutter/message4|获取消息的已读回执和送达回执]];