====== 消息管理–发送和接收消息 ======
更新时间:2022-09-07
登录 Chat app 后,用户可以在单聊、群聊、聊天室中发送如下类型的消息:
* 文字消息,包含超链接和表情消息。
* 附件消息,包含图片、语音、视频及文件消息。
* 位置消息。
* CMD 消息。
* 自定义消息。
本文介绍如何使用即时通讯 IM SDK 实现发送和接收这些类型的消息。
===== 技术原理 =====
环信即时通讯 IM Flutter SDK 通过 ''%%EMChatManager%%'' 和 ''%%EMMessage%%'' 类实现消息的发送、接收与撤回。
其中,发送和接收消息的逻辑如下:
- 发送方调用相应 Create 方法创建文本、文件、附件等类型的消息;
- 发送方再调用 ''%%SendMessage%%'' 发送消息;
- 接收方通过 ''%%EMChatEventHandler%%'' 中的方法监听消息回调事件。在收到 ''%%onMessagesReceived%%'' 后,即表示成功接收到消息。
===== 前提条件 =====
开始前,请确保满足以下条件:
* 完成 SDK 初始化,详见 [[https://docs-im.easemob.com/ccim/flutter/quickstart|快速开始]]。
* 了解环信即时通讯 IM 的使用限制,详见 [[https://docs-im.easemob.com/ccim/limitation|使用限制]]。
===== 实现方法 =====
==== 发送消息 ====
- 首先,利用 ''%%EMMessage%%'' 类构造一个消息。
示例代码:
// 设置发送的消息类型。消息类型共支持 8 种。具体详见 `MessageType` 枚举类型。
MessageType messageType = MessageType.TXT;
// 设置消息接收对象 ID。
String targetId = "tom";
// 设置消息接收对象类型。消息接收对象类型包括单人、群组和聊天室。具体详见 `ChatType` 枚举类型。
ChatType chatType = ChatType.Chat;
// 构造消息。构造不同类型的消息,需要不同的参数。
// 构造文本消息
EMMessage txtMsg = EMMessage.createTxtSendMessage(
targetId: targetId,
content: "This is text message",
);
// 构建图片消息,需要图片的本地地址,长宽,和界面用来显示的名称。
String imgPath = "/data/.../image.jpg";
double imgWidth = 100;
double imgHeight = 100;
String imgName = "image.jpg";
int imgSize = 3000;
EMMessage imgMessage = EMMessage.createImageSendMessage(
targetId: targetId,
filePath: imgPath,
width: imgWidth,
height: imgHeight,
displayName: imgName,
fileSize: imgSize,
);
// 构建命令消息。根据命令消息可以执行具体的命令,命令的内容格式自定义的。
String action = "writing";
EMMessage cmdMsg = EMMessage.createCmdSendMessage(
targetId: targetId,
action: action,
);
// 自定义消息。消息内容由两部分组成:消息事件和扩展字段。
// 扩展字段用户可以自行实现和使用。
String event = "gift";
Map
EMClient.getInstance.chatManager.sendMessage(message).then((value) {
});
你可以设置发送消息结果回调,用于接收消息发送进度或者发送结果,如发送成功或失败。为此,需实现 ''%%MessageStatusCallBack%%'' 接口。
对于命令消息可能并不需要结果,可以不用赋值。
// 实现回调对象
message.setMessageStatusCallBack(
MessageStatusCallBack(
onSuccess: () {
// 收到成功回调之后,可以对发送的消息进行更新处理,或者其他操作。
},
onError: (error) {
// 收到回调之后,可以将发送的消息状态进行更新,或者进行其他操作。
},
onProgress: (progress) {
// 对于附件类型的消息,如图片,语音,文件,视频类型,上传或下载文件时会收到相应的进度值,表示附件的上传或者下载进度。
},
),
);
// 消息发送结果会通过回调对象返回,该返回结果仅表示该方法的调用结果,与实际消息发送状态无关。
EMClient.getInstance.chatManager.sendMessage(message).then((value) {
// 消息发送动作完成。
});
==== 接收消息 ====
你可以添加 ''%%EMChatEventHandler%%'' 监听器接收消息。
该 ''%%EMChatEventHandler%%'' 可以多次添加。请记得在不需要的时候移除该监听器,如在 ''%%dispose%%'' 的卸载组件的时候。
在新消息到来时,你会收到 ''%%onMessagesReceived%%'' 的事件,消息接收时可能是一条,也可能是多条。你可以在该回调里遍历消息队列,解析并显示收到的消息。
// 添加监听
EMClient.getInstance.chatManager.addEventHandler(
"UNIQUE_HANDLER_ID",
EMChatEventHandler(
onMessagesReceived: (messages) {},
),
);
// 移除监听
EMClient.getInstance.chatManager.removeEventHandler("UNIQUE_HANDLER_ID");
文件消息不会自动下载。图片消息和视频消息默认会生成缩略图,接收到图片消息和视频消息,默认会自动下载缩略图。语音消息接收到后会自动下载。
若手动下载附件,需进行如下设置:
- 在初始化 SDK 时将 ''%%isAutoDownloadThumbnail%%'' 设置为 ''%%false%%''。
EMOptions options = EMOptions(
appKey: appKey,
isAutoDownloadThumbnail: false,
);
message.setMessageStatusCallBack(
MessageStatusCallBack(
onProgress: (progress) {},
onSuccess: () {},
onError: (e) {},
),
);
EMClient.getInstance.chatManager.downloadThumbnail(message);
下载完成后,调用相应消息 body 的 ''%%thumbnailLocalPath%%'' 获取缩略图路径。
// 获取图片消息 body。
EMImageMessageBody imgBody = message.body as EMImageMessageBody;
// 从本地获取图片缩略图路径。
String? thumbnailLocalPath = imgBody.thumbnailLocalPath;
EMClient.getInstance.chatManager.downloadAttachment(message);
下载完成后,调用相应消息 body 的 ''%%localPath%%'' 获取附件路径。
示例代码如下:
// 获取文件消息 body。
EMFileMessageBody fileBody = message.body as EMFileMessageBody;
// 从本地获取文件路径。
String? localPath = fileBody.localPath;
==== 撤回消息 ====
消息发送后 2 分钟之内,消息的发送方可以撤回该消息。如果需要调整可撤回时限,可以联系商务。
try {
await EMClient.getInstance.chatManager.recallMessage(msgId);
} on EMError catch (e) {
}
设置消息撤回监听器:
// 消息被撤回时触发的回调(此回调位于 EMChatEventHandler 中)。
void onMessagesRecalled(List messages) {}
==== 更多操作 ====
你可以参考如下文档,在项目中实现更多的消息相关功能:
* [[https://docs-im.easemob.com/ccim/flutter/message1|消息概述]];
* [[https://docs-im.easemob.com/ccim/flutter/message3|管理本地消息数据]];
* [[https://docs-im.easemob.com/ccim/flutter/message4|从服务器获取会话和消息(消息漫游)]];
* [[https://docs-im.easemob.com/ccim/flutter/message5|获取消息的已读回执和送达回执]];
* [[https://docs-im.easemob.com/ccim/flutter/translation|实现翻译功能]]。