消息收发
更新时间: 2025/04/29 09:37:32
本文已不再维护,请前往全新的消息收发及其他消息相关文档查看。
消息收发
功能概述
SDK 提供一套完善的消息传输管理服务,包括收发消息,存储消息,上传下载附件等。支持发送文本,语音,图片,视频,文件,地理位置等类型消息,同时支持用户发送自定义类型的消息。
SDK 中用于表示消息的结构为 NIMMessage
,不同消息类型以 NIMMessageType
作区分。
NIMMessage
部分重要参数说明
参数 | 类型 | 说明 |
---|---|---|
uuid | String? | 消息的客户端 ID |
serverId | int? | 消息的服务端 ID |
sessionId | String? | 聊天对象的 ID/群 ID 等 |
fromAccount | String? | 该条消息发送方的帐号 |
sessionType | NIMSessionType? | 会话类型,如群聊类型 |
senderClientType | NIMClientType? | 消息发送方类型 |
fromNickname | String? | 消息发送者的昵称(Windows 和 macOS 暂不支持) |
messageType | NIMMessageType | 消息类型 |
messageSubType | NIMMessageType? | 消息的子类型 |
status | NIMMessageStatus? | 消息接收/发送状态 |
messageDirection | NIMMessageDirection | 消息方向 |
isInBlackList | bool | 发送消息给对方, 是不是被对方拉黑了 |
content | String? | 消息具体内容,除了文本消息和提示消息外,其他消息为空 |
timestamp | int | 消息时间,单位为 ms |
messageAttachment | NIMMessageAttachment? | 消息附件对象。仅当 messageType 返回为非 text 时有效 |
attachmentDownloadState | NIMMessageAttachmentDownloadState? | 消息附件接收/发送状态(Windows 和 macOS 暂不支持) |
config | NIMCustomMessageConfig? | 消息配置。具体见 NIMCustomMessageConfig 参数说明 |
remoteExtension | Map<String, dynamic>? | 扩展字段(该字段会发送到其他端), 最大长度 1024 。 开发者需要保证此 Map 能够转换为 JsonObject |
localExtension | Map<String, dynamic>? | 本地扩展字段(该字段仅在本地使用有效,不会发送给其他端), 最大长度 1024 。 开发者需要保证此 Map 能够转换为 JsonObject |
callbackExtension | String? | 第三方回调返回的自定义扩展字段 |
pushContent | String? | 推送文案 |
pushPayload | Map<String, dynamic>? | 推送属性 |
memberPushOption | NIMMemberPushOption? | 群成员强制推送属性 |
isRemoteRead | bool? | 单聊场景下,判断自己发送的消息对方是否已读 |
antiSpamOption | NIMAntiSpamOption? | 反垃圾配置项 |
yidunAntiCheating | Map<String, dynamic>? | 易盾反垃圾 |
sessionUpdate | bool | 消息是否需要刷新到 session 服务 |
目前提供如下几种消息类型:
NIMMessageType 参数 |
说明 |
---|---|
text | 文本消息 |
image | 图片消息 |
audio | 音频消息 |
video | 视频消息 |
location | 位置消息 |
file | 文件消息 |
avchat | 音视频通话事件消息(Windows 和 macOS 暂不支持) |
notification | 通知消息 |
tip | 提醒消息 |
custom | 自定义消息 |
消息发送
先通过 MessageBuilder
提供的接口创建对应的消息对象,然后调用 MessageService
的 sendMessage
接口发出。
dart /// 发送消息
/// 如果需要更新发送进度,请监听 [onMessageStatus]。
/// 如果需要监听附件进度,请监听 [onAttachmentProgress]。
/// 如果消息发送失败后需要重发,请使用[resend] 参数。
Future<NIMResult<NIMMessage>> sendMessage(
{required NIMMessage message, bool resend = false});
注意事项
一分钟内默认最多可调用发送消息接口 300 次。
文本消息发送
文本消息创建原型
dart /// 创建文本消息
static Future<NIMResult<NIMMessage>> createTextMessage(
{required String sessionId,
required NIMSessionType sessionType,
required String text});
- 参数说明
参数 | 说明 |
---|---|
sessionId | 聊天对象的 ID,如果是单聊,为用户帐号,如果是群聊,为群组 ID |
sessionType | 聊天类型, NIMSessionType.p2p 为单聊类型,NIMSessionType.team 为群聊类型 |
text | 文本消息内容 |
- 示例
dart// 该帐号为示例
String account = 'testAccount';
// 以单聊类型为例
NIMSessionType sessionType = NIMSessionType.p2p;
String text = 'this is an example';
// 创建并且发送一个文本消息
Future<NIMResult<NIMMessage>> result = MessageBuilder.createTextMessage(
sessionId: account, sessionType: sessionType, text: text)
.then((value) => value.isSuccess
? NimCore.instance.messageService
.sendMessage(message: value.data!, resend: false)
: Future.value(value));
图片消息发送
图片消息创建原型
dart /// 创建图片消息
/// [base64] 字段为web端专用,web端[filePath] 可传空字符串
static Future<NIMResult<NIMMessage>> createImageMessage(
{required String sessionId,
required NIMSessionType sessionType,
required String filePath,
required int fileSize,
String? displayName,
String? base64,
NIMNosScene nosScene = NIMNosScenes.defaultIm});
- 参数说明
参数 | 类型 | 说明 |
---|---|---|
sessionId | String | 聊天对象的 ID,如果是单聊,为用户帐号,如果是群聊,为群组 ID |
sessionType | NIMSessionType | 聊天类型, NIMSessionType.p2p 为单聊类型,NIMSessionType.team 为群聊类型 |
filePath | String | 文件路径,web端可传空字符串 |
base64 | String | web端使用,传经过base64编码的文件, 1.3.3 版本以上生效 |
fileSize | int | 文件大小 |
displayName | String? | 图片文件的显示名,可不同于文件名,可设置为 null |
nosScene | NIMNosScene | 图片上传时使用的 nos scene ,默认为NIMNosScene.defaultIm ,详见文件资源场景章节 |
- 示例
dart // 该帐号为示例
String account = 'testAccount';
// 以单聊类型为例
NIMSessionType sessionType = NIMSessionType.p2p;
// 示例图片,需要开发者在相应目录下有图片
File file = new File('filePath');
// 显示名称
String displayName = 'this is a file';
// web 端需要base64,其他端可忽略
String base64 = 'this is base64';
// 发送图片消息
Future<NIMResult<NIMMessage>> result =
MessageBuilder.createImageMessage(
sessionId: account,
sessionType: sessionType,
filePath: file.path,
fileSize: file.lengthSync(),
displayName: displayName,
base64: base64,
nosScene: NIMNosScene.defaultIm)
.then((value) => value.isSuccess
? NimCore.instance.messageService
.sendMessage(message: value.data!, resend: false)
: Future.value(value));
语音消息发送
音频消息创建原型:
dart /// 创建音频消息
/// [base64] 字段为web端专用,web端[filePath] 可传空字符串
static Future<NIMResult<NIMMessage>> createAudioMessage(
{required String sessionId,
required NIMSessionType sessionType,
required String filePath,
required int fileSize,
required int duration,
String? base64,
String? displayName,
NIMNosScene nosScene = NIMNosScenes.defaultIm});
- 参数说明
参数 | 类型 | 说明 |
---|---|---|
sessionId | String | 聊天对象的 ID,如果是单聊,为用户帐号,如果是群聊,为群组 ID |
sessionType | NIMSessionType | 聊天类型, NIMSessionType.p2p 为单聊类型,NIMSessionType.team 为群聊类型 |
filePath | String | 文件路径,web端可传空字符串 |
base64 | String | web端使用,传经过base64编码的文件, 1.3.3 版本以上生效 |
fileSize | int | 文件大小 |
displayName | String? | 图片文件的显示名,可不同于文件名,可设置为 null |
duration | int | 音频文件持续时间,单位是 ms |
nosScene | NIMNosScene | 音频文件上传时使用的 nos scene ,默认为NIMNosScene.defaultIm ,详见文件资源场景章节 |
- 示例
dart // 该帐号为示例
String account = 'testAccount';
// 以单聊类型为例
NIMSessionType sessionType = NIMSessionType.p2p;
// 示例音频,需要开发者在相应目录下有文件
File file = new File('filePath');
// 显示名称
String displayName = 'this is a file';
// web 端需要base64,其他端可忽略
String base64 = 'this is base64';
// 发送语音消息
Future<NIMResult<NIMMessage>> result =
MessageBuilder.createAudioMessage(
sessionId: account,
sessionType: sessionType,
filePath: file.path,
fileSize: file.lengthSync(),
base64: base64,
duration: 2000,
displayName: displayName,
nosScene: NIMNosScene.defaultIm)
.then((value) => value.isSuccess
? NimCore.instance.messageService
.sendMessage(message: value.data!, resend: false)
: Future.value(value));
视频消息发送
视频消息创建原型:
dart /// 创建视频消息
/// [base64] 字段为web端专用,web端[filePath] 可传空字符串
static Future<NIMResult<NIMMessage>> createVideoMessage(
{required String sessionId,
required NIMSessionType sessionType,
required String filePath,
int? fileSize,
String? base64,
required int duration,
required int width,
required int height,
required String displayName,
NIMNosScene nosScene = NIMNosScenes.defaultIm});
- 参数说明
参数 | 类型 | 说明 |
---|---|---|
sessionId | String | 聊天对象的 ID,如果是单聊,为用户帐号,如果是群聊,为群组 ID |
sessionType | NIMSessionType | 聊天类型, NIMSessionType.p2p 为单聊类型,NIMSessionType.team 为群聊类型 |
filePath | String | 文件路径,web端可传空字符串 |
base64 | String | web端使用,传经过 base64 编码的文件, 1.3.3 版本以上生效 |
fileSize | int? | 文件大小 |
duration | int | 视频文件持续时间,单位 ms |
width | int | 视频宽度 |
height | int | 视频高度 |
displayName | String | 视频文件显示名,可为 null |
nosScene | NIMNosScene | 视频文件上传时使用的 nos scene ,默认为NIMNosScene.defaultIm ,详见文件资源场景章节 |
- 示例
dart// 该帐号为示例
String account = 'testAccount';
// 以单聊类型为例
NIMSessionType sessionType = NIMSessionType.p2p;
// 示例视频,需要开发者在相应目录下有文件
File file = new File('filePath');
// 显示名称
String displayName = 'this is a file';
// web 端需要base64,其他端可忽略
String base64 = 'this is base64';
// 发送消息
Future<NIMResult<NIMMessage>> result =
MessageBuilder.createVideoMessage(
sessionId: account,
sessionType: sessionType,
filePath: file.path,
fileSize: file.lengthSync(),
base64: base64,
duration: 2000,
width: 1080,
height: 720,
displayName: displayName,
nosScene: NIMNosScene.defaultIm)
.then((value) => value.isSuccess
? NimCore.instance.messageService
.sendMessage(message: value.data!, resend: false)
: Future.value(value));
文件消息发送
文件消息创建原型:
dart /// 创建文件消息
/// [base64] 字段为web端专用,web端[filePath] 可传空字符串
static Future<NIMResult<NIMMessage>> createFileMessage(
{required String sessionId,
required NIMSessionType sessionType,
required String filePath,
String? base64,
int? fileSize,
required String displayName,
NIMNosScene nosScene = NIMNosScenes.defaultIm});
- 参数说明
参数 | 类型 | 说明 |
---|---|---|
sessionId | String | 聊天对象的 ID,如果是单聊,为用户帐号,如果是群聊,为群组 ID |
sessionType | NIMSessionType | 聊天类型, NIMSessionType.p2p 为单聊类型,NIMSessionType.team 为群聊类型 |
filePath | String | 文件路径,web端可传空字符串 |
base64 | String | web 端使用,传经过 base64 编码的文件, 1.3.3 版本以上生效 |
fileSize | int? | 文件大小 |
displayName | String | 文件的显示名,可不同于文件名 |
nosScene | NIMNosScene | 文件上传时使用的 nos scene ,默认为NIMNosScene.defaultIm ,详见文件资源场景章节 |
- 示例
dart// 该帐号为示例
String account = 'testAccount';
// 以单聊类型为例
NIMSessionType sessionType = NIMSessionType.p2p;
// 示例文件,需要开发者在相应目录下有文件
File file = new File('filePath');
// 显示名称
String displayName = 'this is a file';
// web 端需要base64,其他端可忽略
String base64 = 'this is base64';
// 发送消息
Future<NIMResult<NIMMessage>> result = MessageBuilder.createFileMessage(
sessionId: account,
sessionType: sessionType,
filePath: file.path,
fileSize: file.lengthSync(),
base64: base64,
displayName: displayName,
nosScene: NIMNosScene.defaultIm)
.then((value) => value.isSuccess
? NimCore.instance.messageService
.sendMessage(message: value.data!, resend: false)
: Future.value(value));
位置消息发送
地理位置消息创建原型:
dart /// 创建地理位置消息
static Future<NIMResult<NIMMessage>> createLocationMessage(
{required String sessionId,
required NIMSessionType sessionType,
required double latitude,
required double longitude,
required String address});
- 参数说明
参数 | 类型 | 说明 |
---|---|---|
sessionId | String | 聊天对象的 ID,如果是单聊,为用户帐号,如果是群聊,为群组 ID |
sessionType | NIMSessionType | 聊天类型, NIMSessionType.p2p 为单聊类型,NIMSessionType.team 为群聊类型 |
latitude | double | 纬度 |
longitude | double | 经度 |
address | String | 地理位置描述信息 |
- 示例
dart// 该帐号为示例
String account = 'testAccount';
// 以单聊类型为例
NIMSessionType sessionType = NIMSessionType.p2p;
// 显示名称
String address = 'this is a address';
// 发送消息
Future<NIMResult<NIMMessage>> result =
MessageBuilder.createLocationMessage(
sessionId: account,
sessionType: sessionType,
latitude: 30.3,
longitude: 120.2,
address: address)
.then((value) => value.isSuccess
? NimCore.instance.messageService
.sendMessage(message: value.data!, resend: false)
: Future.value(value));
提示消息发送
提示消息(又叫做 Tip 消息)主要用于会话内的通知提醒,可以看做是自定义消息的简化,有独立的消息类型 NIMMessageType.tip
。
区别于自定义消息,Tip 消息暂不支持 messageAttachment
,如果要使用 messageAttachment
请使用自定义消息。
Tip 消息使用场景例如:进入会话时出现的欢迎消息,或是会话过程中命中敏感词后的提示消息等场景,当然也可以用自定义消息实现,只是相对复杂一些。
提示消息创建原型:
dart /// 创建Tip消息
static Future<NIMResult<NIMMessage>> createTipMessage(
{required String sessionId, required NIMSessionType sessionType});
- 示例
dart// 向群里插入一条Tip消息,使得该群能立即出现在最近联系人列表(会话列表)中,满足部分开发者需求。
Map<String, dynamic> content = {'content': '成功创建高级群'};
// 自定义消息配置选项
NIMCustomMessageConfig config =
NIMCustomMessageConfig(enableUnreadCount: false);
// 发送消息
Future<NIMResult<NIMMessage>> result = MessageBuilder.createTipMessage(
sessionId: 'teamId', sessionType: NIMSessionType.team)
.then((value) {
if (value.isSuccess) {
value.data!.config = config;
value.data!.status = NIMMessageStatus.success;
value.data!.remoteExtension = content;
return NimCore.instance.messageService
.sendMessage(message: value.data!, resend: false);
} else {
return Future.value(value);
}
});
自定义消息发送
除了内建消息类型以外,SDK 还支持收发自定义消息类型。SDK 不负责定义和解析自定义消息的具体内容,解释工作由开发者完成。SDK 会将自定义消息存入消息数据库,会和内建消息一并展现在消息记录中。
为了使用更加方便,自定义消息采用附件的方式展示给开发者。体现在 NIMMessage
类中,自定义消息的内容会被解析为 NIMCustomMessageAttachment
对象。
创建自定义消息原型
dart/// 创建自定义消息
static Future<NIMResult<NIMMessage>> createCustomMessage(
{required String sessionId,
required NIMSessionType sessionType,
String? content,
NIMMessageAttachment? attachment,
NIMCustomMessageConfig? config});
消息属性设置
发送消息时可以设置消息配置选项 NIMCustomMessageConfig
,主要用于设定该消息是否存入云端、是否写入漫游等。
- 参数说明
自定义消息配置 NIMCustomMessageConfig
属性
dartclass NIMCustomMessageConfig {
/// 该消息是否要保存到服务器
final bool enableHistory;
/// 该消息是否需要漫游
final bool enableRoaming;
/// 多端同时登录时,发送一条自定义消息后,是否要同步到其他同时登录的客户端
final bool enableSelfSync;
/// 该消息是否要推送提醒,如果为true,那么对方收到消息后,系统通知栏会有提醒
final bool enablePush;
/// 该消息是否需要推送昵称(针对iOS客户端有效),如果为true,那么对方收到消息后,iOS端将显示推送昵称
final bool enablePushNick;
/// 该消息是否要计入未读数,如果为true,那么对方收到消息后,最近联系人列表中未读数加1
final bool enableUnreadCount;
/// 该消息是否支持路由,如果为true,默认按照app的路由开关(如果有配置抄送地址则将抄送该消息)
final bool enableRoute;
/// 该消息是否要存离线
final bool enablePersist;
}
- 示例
dart// 该帐号为示例
String account = 'testAccount';
// 以单聊类型为例
NIMSessionType sessionType = NIMSessionType.p2p;
String text = 'this is an example';
// 自定义消息配置选项
NIMCustomMessageConfig config =
NIMCustomMessageConfig(enableHistory: false,
enableRoaming:false,
enableSelfSync:false);
// 发送消息
Future<NIMResult<NIMMessage>> result = MessageBuilder.createTextMessage(
sessionId: account, sessionType: sessionType, text: text)
.then((value) {
if (value.isSuccess) {
value.data!.config = config;
return NimCore.instance.messageService
.sendMessage(message: value.data!, resend: false);
} else {
return Future.value(value);
}
});
文件资源场景
SDK 支持对图片、语音、视频与文件等设置对应的存活时间。
- 预设文件资源场景
在初始化 SDK 时,可做相应的文件资源场景配置,参考代码:
dart
static SDKOptions getSDKOptions(Context context) {
SDKOptions options = new SDKOptions();
//其他配置
options.mNosTokenSceneConfig = createNosTokenScene();
return options;
}
public static final String TEST_NOS_SCENE_KEY="test_nos_scene_key";
private static NosTokenSceneConfig createNosTokenScene() {
NosTokenSceneConfig nosTokenSceneConfig = new NosTokenSceneConfig();
//更新默认场景(NimNosSceneKeyConstant.NIM_DEFAULT_IM)对应的过期时间(天)
nosTokenSceneConfig.updateDefaultIMSceneExpireTime(1);
//更新默认场景 (NimNosSceneKeyConstant.NIM_DEFAULT_PROFILE) 对应的过期时间(天)
nosTokenSceneConfig.updateDefaultProfileSceneExpireTime(2);
//设置自定义场景及对应的过期时间(天),0代表永不过期。
//建议sceneKey常量化,这样使用的时候比较方便,目前支持自定义最多10种场景
nosTokenSceneConfig.appendCustomScene(TEST_NOS_SCENE_KEY, 4);
return nosTokenSceneConfig;
}
NimNosSceneKeyConstant 主要参数一览:
NimNosSceneKeyConstant | 含义 |
---|---|
NIM_DEFAULT_IM | 私聊、群聊、聊天室发送图片、音频、视频、文件消息等。 |
NIM_DEFAULT_PROFILE | 对应使用云信上传服务上传的用户、群组..资料(eg:头像)等。 |
值得注意的是:
- 如果使用了不存在的场景,那么上传将失败(错误码:5)
- 如果文件过期了,再去下载文件,那么会下载失败(错误码:4)
本地消息插入
当有业务场景需要单纯插入一条消息至本地数据库内,而不发出时,可以使用插入本地消息的方法(saveMessage
或saveMessageToLocalEx
)来实现。
dart/**
* 插入消息到本地数据库,且通知更新UI界面,但不发送到服务器端。发送一条可设置他人为发送方的本地消息给自己。
* 该接口将消息保存到数据库后,会通知到UI,此时会触发{@link MsgServiceObserve#observeReceiveMessage(Observer, boolean)}通知。
*
* @param msg 待插入的消息对象
* @param fromAccount 发送者ID
* @return Future 可以设置回调函数。在消息存入数据库后,就会回调。
*/
Future<NIMResult<NIMMessage>> saveMessage(
{required NIMMessage message, required String fromAccount})
消息更新
扩展字段更新
SDK 支持更新客户端数据库内的消息的客户端扩展字段。
dart/**
* 更新消息的LocalExtension
* @param message 待更新的消息
*/
Future<NIMResult<void>> updateMessage(NIMMessage message);
注意:请不要对notification
类型消息进行更新。
消息重发
消息发送失败之后,可以重发消息。消息重发和消息发送是同一个接口,只是参数的设置不同而已,当 resend 参数为 true 时,表示重发消息。
消息转发
SDK 支持消息转发功能,但不支持通知消息和音视频通话事件消息的转发,其他消息类型均支持。
dart/**
* 转发消息
*
* @param message 要转发的消息
* @param sessionId 聊天对象ID
* @param sessionType 会话类型
* @return 接口调用的结果
*/
Future<NIMResult<void>> forwardMessage(
NIMMessage message, String sessionId, NIMSessionType sessionType)
- 参数说明
参数 | 类型 | 说明 |
---|---|---|
message | NIMMessage | 要转发的消息 |
sessionId | String | 聊天对象的 ID,如果是单聊,为用户帐号,如果是群聊,为群组 ID |
sessionType | NIMSessionType | 聊天类型,NIMSessionType.p2p 为单聊类型,NIMSessionType.team 为群聊类型 |
- 示例
dartNIMResult<NIMMessage> message = await MessageBuilder.createTextMessage(sessionId: '123', sessionType: NIMSessionType.p2p, text: '转发');
if (message.isSuccess) {
NimCore.instance.messageService.forwardMessage(message.data!, '123', NIMSessionType.p2p);
}
消息接收
消息接收流 MessageService#onMessage
,在有新消息到达时,第三方 APP 就可以接收到通知。
- API 原型
dart /// 消息接收
Stream<List<NIMMessage>> get onMessage =>
MessageServicePlatform.instance.onMessage.stream;
- 示例
dartNimCore.instance.messageService.onMessage.listen((List<NIMMessage> list) {
// 处理新收到的消息,为了上传处理方便,SDK 保证参数 messages 全部来自同一个聊天对象。
});
通知类消息接收
一些特定场景的行为,云信服务器预置了一些通知消息。通知消息也是一种特定消息,开发者需要解析消息中附带的信息,来获取通知内容。如最常见的通知消息是群通知事件,如有新成员进群,则群内已有成员将收到此通知消息。目前不支持从客户端发出通知消息。
通知消息属于会话内的一种消息,其对应的数据结构为 NIMMessage
,消息类型为 NIMMessageType.notification
。目前用于群通知和聊天室通知事件。
通知消息需要进行解析,具体参见群组通知消息。
多媒体类消息接收
多媒体类消息,如语音消息、图片消息、文件消息和视频消息,需要考虑收到消息后下载资源的情况。 针对使用云信上传服务的多媒体类消息:
- 如果收到的是图片,视频消息,SDK 默认会在收到消息时,自动下载缩略图和封面图片。
- 如果收到的是语音消息,SDK 默认会在收到消息时,自动下载原音频。
- 如果收到的是文件消息,不会下载原文件。
若要关闭默认策略,自主选择下载时机,可以使用以下方法来完成:
- 关闭自动下载
修改初始化配置参数 SDKOptions - preloadAttach
为 false 。
- 主动下载附件:
原型
dart/**
* 正常情况收到消息后附件会自动下载。如果下载失败,可调用该接口重新下载
*
* @param message 附件所在的消息体
* @param thumb 是否只下载缩略图。为true时,仅下载缩略图。
* 该参数仅对图片和视频类消息有效
* @return Future 调用跟踪。可设置回调函数,可中止下载操作
*/
Future<NIMResult<void>> downloadAttachment(NIMChatroomMessage message,
[bool thumb = false])
- 参数说明
参数 | 类型 | 说明 |
---|---|---|
message | NIMChatroomMessage | 附件所在的消息体 |
thumb | bool | 是否只下载缩略图。为 true 时,仅下载缩略图。该参数仅对图片和视频类消息有效(Windows 和 macOS 暂不支持) |
- 示例
dartNimCore.instance.messageService.downloadAttachment(message, true);
- 附件参数说明
下载完成后,可以通过对应的 NIMMessageAttachment 获取到具体的附件内容。多媒体附件的基类是 NIMFileAttachment,继承自 NIMMessageAttachment。它的子类主要有:
- 视频消息附件 NIMVideoAttachment
- 图片消息附件 NIMImageAttachment
- 音频消息附件 NIMAudioAttachment
以 NIMFileAttachment 为例,说明附件参数:
NIMFileAttachment 参数 | 类型 | 说明 | |
---|---|---|---|
path | String | 可选参数,文件本地路径,若文件不存在,返回 null。 语音消息的文件路径,在附件下载完成之后可以获取。 图片或视频的文件路径,需要手动下载之后获取,收到消息时,SDK 只默认自动下载缩略图文件 |
|
thumbPath | String | 可选参数,缩略图文件的本地路径,若文件不存在,返回 null。 当消息状态显示缩略图下载完成之后,可获取缩略图文件路径(Windows 和 macOS 暂不支持) |
|
thumbUrl | String | 可选参数,缩略远程路径(Windows 和 macOS 暂不支持) | |
size | int | 可选参数,获取文件大小,单位为 byte | |
md5 | String | 可选参数,获取文件内容 MD5 | |
url | String | 可选参数,获取文件在服务器上的下载 url。若文件还未上传,返回 null | |
extension | String | 可选参数,文件后缀名 | |
expire | int | 可选参数,过期时间(Windows 和 macOS 暂不支持) | |
nosScene | NIMNosScene | 上传文件时用的对 token 对应的场景,默认 [NIMNosScenes.defaultIm] | |
displayName | String | 可选参数,文件的显示名。可以和文件名不同,仅用于界面展示 | |
base64 | String | 通用可选字段,目前用于 Web 传入文件信息,Web 端发送文件必传 |
其他类型附件属性详见客户端 API 文档。
监听消息状态
该接口可以监听消息接收或发送状态 NIMMessageStatus 和 消息附件接收或发送状态 NIMMessageAttachmentDownloadState 的变化。当状态更改为 NIMMessageAttachmentDownloadState.downloaded 表示附件下载成功。
- 原型
dart/// 消息状态变化
Stream<NIMMessage> get onMessageStatus =>
MessageServicePlatform.instance.onMessageStatus.stream;
- 参数说明
NIMMessageStatus
属性说明
NIMMessageStatus 属性说明 | 说明 |
---|---|
draft | 草稿 |
sending | 正在发送中 |
success | 发送成功 |
fail | 发送失败 |
read | 一般用于收到的音频消息,当前登录用户有无听过 |
unread | 未读状态 |
NIMMessageAttachmentDownloadState 属性说明
NIMMessageAttachmentDownloadState 属性说明 | 说明 |
---|---|
needDownload | 默认状态,未开始 |
downloading | 正在传输 |
downloaded | 传输成功, 附件下载成功标志 |
failed | 传输失败 |
- 示例
dartNimCore.instance.messageService.onMessageStatus.listen((NIMMessage message) {
// 1、根据sessionId判断是否是自己的消息
// 2、更改内存中消息的状态
// 3、刷新界面
});
聊天室接收消息
详见聊天室章节。
文件传输过程管理
监听文件传输进度
SDK 提供文件传输管理功能,开发可以通过注册消息附件上传/下载进度观察者来监控文件传输。
dart/**
* 注册/注销消息附件上传/下载进度观察者
*/
StreamController<NIMAttachmentProgress> onAttachmentProgress;
Web 端不支持该接口。
取消上传消息附件
MessageService
接口提供了取消上传消息附件的方法。
dart/**
* 取消上传消息附件(图片、视频、文件类型的),如果附件已经上传成功,操作将会失败 。如果成功取消了附件的上传,那么相应的消息会发送失败,对应的消息状态是NIMMessageStatus.fail,附件状态是NIMMessageAttachmentDownloadState.cancel。注意:此操作暂时不支持聊天室。
* @param message 要取消上传附件的消息
*/
Future<NIMResult<void>> cancelUploadAttachment(NIMMessage message)
Web SDK 不支持该接口。
消息撤回
消息撤回
允许用户撤回一定时间内发送过的消息,客户端可允许撤回时长默认 2 分钟,可在网易云信控制台配置。
8.5.0 起,支持撤回自己发送给自己的消息
- API 原型
dart/**
* 消息撤回 , 并设置相应的第三方推送配置(包括IOS平台的推送)与未读数变化,如果想要关闭App内的返回消息提醒,参考{@link NIMClient#toggleRevokeMessageNotification(boolean on)}
*
* @param message 待撤回的消息
* @param customApnsText 第三方透传消息推送文本,不填则不推送
* @param pushPayload 第三方自定义的推送属性,限制json类型,长度2048
* @param shouldNotifyBeCount 撤回通知是否更新未读数
* @param postscript 附言
* @param attach 扩展字段
*
* @return Future 可设置回调函数,监听发送结果。
*/
Future<NIMResult<void>> revokeMessage(
{required NIMMessage message,
String? customApnsText,
Map<String, Object>? pushPayload,
bool? shouldNotifyBeCount,
String? postscript,
String? attach});
- 参数说明
参数 | 类型 | 说明 |
---|---|---|
message | NIMMessage | 待撤回的消息 |
customApnsText | String? | 第三方透传消息推送文本,不填则不推送 |
pushPayload | Map<String, Object>? | 第三方自定义的推送属性,限制 json 类型,长度 2048 |
shouldNotifyBeCount | bool? | 撤回通知是否更新未读数(Windows 和 macOS 暂不支持) |
postscript | String? | 附言(Windows 和 macOS 暂不支持) |
attach | String? | 扩展字段 |
- 示例
dartNimCore.instance.messageService.revokeMessage(message: message);
在撤回消息请求调用成功后, SDK 会先回调给上层成功,再自动将本地的这条消息删除。如果需要在撤回后显示一条本方已撤回的提示,开发者可以自行构造一条提醒消息并调用插入本地消息的方法。
以下情况消息撤回会失败:
- 消息为空
- 消息没有发送成功
- 消息超过撤回时限
针对撤回场景的通知栏内容覆盖需求:如 A 发消息给 B,产生 APNs 推送,文案内容为“你好“。然后 A 撤回了这条消息,此时通知栏中的“你好”变为预设的“对方撤回了一条消息”。
一种建议的实现方式是:
- 在发送消息时,需要通过 NIMMessage - setPushPayload(Map pushPayload)方法 插入 key 为 apns-collapse-id 的键值对,value 的内容建议使用 uuid 等字符串,用以唯一标识该消息。
- 当要撤回这条消息时,在撤回接口传参 customApnsText 中设置覆盖文案,在 pushPayload 中插入与被撤回消息相同的 apns-collapse-id 键值对。
监听消息撤回
被撤回方会收到消息撤回通知。
- API 原型
dart/**
* 注册/注销消息撤回的观察者
*/
StreamController<NIMRevokeMessage> onMessageRevoked
- NIMRevokeMessage 说明
属性 | 类型 | 说明 | |
---|---|---|---|
message | NIMMessage? | 撤回消息 | |
attach | String? | 撤回附件字段 | |
revokeAccount | String? | 撤回者 | |
customInfo | String? | 消息撤回时设置的 msg 字段(eg: 通过服务端 API 撤回)。 | |
notificationType | int? | 通知类型: 1 表示是离线通知,2 表示是漫游通知 , 默认 0 | |
revokeType | RevokeMessageType? | 撤回类型:分为点对点双向撤回, 群双向撤回, 超大群双向撤回, 点对点单向撤回和未定义(Windows 和 macOS 暂不支持) | |
callbackExt | String? | 第三方扩展字段 |
- 示例
dart NimCore.instance.messageService.onMessageRevoked.listen((event) {
print('Test_Observer onMessageRevoked ${event.toString()}');
});
已读回执
当发送方需要知道接收方是否已经阅读了自己发送的消息时,需要使用已读回执的功能。
单聊消息已读回执
发送已读回执:
在会话界面中调用发送已读回执的接口并传入当前会话的最后一条消息,即表示这之前的消息本方都已读。
- API 原型
dart/**
* 发送消息已读回执
* @param sessionId 会话ID(聊天对象账号)
* @param message 已读的消息(一般是当前接收的最后一条消息)
*/
Future<NIMResult<void>> sendMessageReceipt(
{required String sessionId, required NIMMessage message});
- 示例
dart NimCore.instance.messageService.onMessage.listen((event) {
print('Test_Observer onMessage ${event.toString()}');
for (NIMMessage m in event) {
if (m.sessionType == NIMSessionType.p2p) {
NimCore.instance.messageService.sendMessageReceipt(sessionId: m.fromAccount!, message: m);
} else if (m.sessionType == NIMSessionType.team) {
NimCore.instance.messageService.sendTeamMessageReceipt(m);
}
}
});
监听已读回执:
- API 原型
dart/**
* 注册/注销消息已读回执观察者
*/
StreamController<List<NIMMessageReceipt>> onMessageReceipt
- 参数说明
NIMMessageReceipt 属性 | 类型 | 说明 |
---|---|---|
sessionId | String | 聊天对象的 ID,如果是单聊,为用户帐号,如果是群聊,为群组 ID |
time | int | 该会话最后一条已读消息的时间,比该时间早的消息都视为已读 |
- 示例
dart NimCore.instance.messageService.onMessageReceipt.listen((event) {
print('Test_Observer onMessageReceipt ${event.toString()}');
});
此外,可以根据 NIMMessage 中的 isRemoteRead()
方法来判断该条消息对方是否已读。
群聊消息已读回执
群消息已读回执功能,需要联系商务顾问申请开通后才能使用。同时,使用该功能时需要将群成员控制在 100 人以内。
- 启用群消息已读回执功能
初始化 SDK 时,配置SDKOptions - enableTeamMsgAck
参数为 true 来启用群消息已读回执功能。
- 设置其他群成员收到此消息需要发送已读回执
发送群消息时,通过NIMMessage - setMsgAck()
方法标记该消息需要已读回执。接收群消息时,通过NIMMessage - needMsgAck
属性获取该消息是否需要已读回执。
示例
dart// 创建待发送消息
NIMResult<NIMMessage> result = await MessageBuilder.createTextMessage(sessionId: '123', sessionType: NIMSessionType.team, text: 'text');
if (result.isSuccess) {
var message = result.data!;
message.messageAck = true;
NimCore.instance.messageService.sendMessage(message: message);
}
- 消息接收方发送群消息已读回执
原型
dart/**
* (群消息接收方)标记群组消息已读
*
* @param message 群组消息
* @return Future 可设置回调函数,监听发送结果。
*/
Future<NIMResult<void>> sendTeamMessageReceipt(NIMMessage message);
示例
dartNimCore.instance.messageService.sendTeamMessageReceipt(message)
此外,可以通过NIMMessage - hasSendAck()
来判断是否已经发送过群消息已读回执。
- 消息发送方监听群消息已读回执
原型
dart/**
* 注册/注销群消息已读回执观察者(群成员发出需要已读回执的消息时,当有群成员已读后,该观察者会回调)
*/
StreamController<NIMTeamMessageReceipt> onTeamMessageReceipt
参数说明
NIMTeamMessageReceipt 接口说明
NIMTeamMessageReceipt 属性 | 类型 | 说明 |
---|---|---|
messageId | String | 获取消息 id |
ackCount | int? | 获取已读人数 |
unAckCount | int? | 获取未读人数 |
示例
dart NimCore.instance.messageService.onTeamMessageReceipt.listen((event) {
print('Test_Observer onTeamMessageReceipt ${event.toString()}');
});
- 批量刷新群组消息已读、未读的数量
原型
dart/**
* (群消息发送方)批量刷新群组消息已读、未读的数量信息,没有异步回调(Windows和macOS暂支持列表中的第一个)
* 如果已读、未读数有变更,会通过 {@link com.netease.nimlib.sdk.msg.MsgServiceObserve#observeTeamMessageReceipt(Observer, boolean)}来批量通知,没有变更则不会通知
*
* @param messageList 请求刷新的群组消息集合
*/
Future<NIMResult<void>> refreshTeamMessageReceipt(List<NIMMessage> messageList)
一般在加载消息进行批量刷新。反复刷新,SDK 实际上不会发出网络请求。只有已读、未读数量有变更,才会通过观察者接口进行通知。该 API 为异步无回调接口。
示例
dart// messages为接收到的批量消息
NimCore.instance.messageService.refreshTeamMessageReceipt(messages);
- 查询单条群组消息的已读、未读账号列表
原型
dart/**
* (群消息发送方)查询单条群组消息在指定用户中的已读、未读账号列表
*
* @param message 待查询的消息
* @param accountList 指定的用户的账号组成的{@link Set<String>}。
* 如果传空,则返回的列表也是空
* @return 该消息的已读、未读账号列表
*/
Future<NIMResult<NIMTeamMessageAckInfo>> fetchTeamMessageReceiptDetail(
{required NIMMessage message, List<String>? accountList})
示例
dartNimCore.instance.messageService.fetchTeamMessageReceiptDetail(message: message, accountList: ['123', '456']);
- 从数据库查询单条群组消息已读、未读账号列表
注意:这里直接从数据库获取,很可能是陈旧信息
原型
dart/**
* 从本地数据库查询单条群组消息在指定用户中的已读、未读账号列表(同步接口)
* 注意!!!:这里获取的数据通常比离线前的列表信息更陈旧
*
* @param message 待查询的消息
* @param accountList 指定的用户的账号组成的{@link Set<String>}。
* 如果传空,则返回的列表也是空
* @return 该消息的已读、未读账号列表
*/
Future<NIMResult<NIMTeamMessageAckInfo>> queryTeamMessageReceiptDetail(
{required NIMMessage message, List<String>? accountList}) ;
示例
dartNimCore.instance.messageService. queryTeamMessageReceiptDetail(message: message, accountList: ['123', '456']);
- 查询单条群组消息已读、未读账号数量
通过 IMMessage 接口的 getTeamMsgAckCount()方法来获取群消息已读账号数量,通过 getTeamMsgUnAckCount() 方法来获取群消息未读账号数量。
广播消息接收
网易云信支持全员广播消息,广播消息由服务端接口发起,对应用内的所有用户发送一条广播消息。客户端不支持发送, SDK 收到广播之后直接往上层通知,不支持客户端存储。
1秒内默认最多可调该接口10次。如需上调上限,请在官网首页通过微信、在线消息或电话等方式咨询商务人员。
- API 原型
dart/**
* 注册/注销全员广播消息观察者
*/
StreamController<NIMBroadcastMessage> onBroadcastMessage
- NIMBroadcastMessage 参数说明
属性 | 类型 | 说明 |
---|---|---|
id | int? | 广播 id |
fromAccount | String? | 广播发送者账号 |
time | int? | 广播消息时间戳 |
content | String? | 广播消息内容 |
- 示例
dart NimCore.instance.messageService.onBroadcastMessage.listen((event) {
print('Test_Observer onBroadcastMessage ${event.toString()}');
});
语音消息处理
云信 SDK 提供了高清语音的录制与播放的功能,用于处理语音消息。(macOS 和 Web 暂不支持)
播放
采用系统提供 AudioPlayer 类进行语音播放的功能即可。
录制
SDK 提供 AudioRecordService 来支持语音的录制。
AudioRecordService 接口说明:
接口 | 返回值 | 说明 |
---|---|---|
startAudioRecord(Map<String, dynamic>? param) | void | 开始录音,map 中支持参数 recordType 录音格式类型默认 acc,maxLength 最大录音长度默认支持 120 秒 |
stopAudioRecord() | void | 停止录音 |
getAmplitude() | int | 获取当前录音时最大振幅, 40ms 更新一次数据(Windows 暂不支持) |
isRecording() | bool | 是否正在录音(Windows 暂不支持) |
cancelAudioRecord() | void | 启动(开始)录音,如果成功,会按照顺序回调 onRecordStateChange#中 recordState = onRecordReady 和 onRecordStateChange#recordState = onRecordStart |
StreamController |
Stream | 在 RecordInfo 中 recordState 分别代表录制过程中的不同状态变化,具体参考 RecordState |
构造录制实例
- API 原型
dart/**
* 获取录音service
*
*/
NimCore.instance.eventSubscribeService
- 参数说明
参数 | 类型 | 说明 |
---|---|---|
recordType | int | 录制音频类型(aac/amr),0 代表 aac,1 代表 amr |
maxDuration | int | 最长录音时长,到该长度后,会自动停止录音 |
- onAudioRecordStatus 返回 RecordInfo,RecordInfo 字段说明:
字段 | 类型 | 说明 |
---|---|---|
CANCEL | 枚举 | 录音结束, 用户主动取消录音 |
FAIL | 枚举 | 录音结束,出错(Windows 暂不支持) |
REACHED_MAX | 枚举 | 到达指定的最长录音时间,RecordInfo 中包含 int maxTime(Windows 暂不支持) |
READY | 枚举 | 录音器已就绪,提供此接口用于在录音前关闭本地音视频播放(可选)(Windows 暂不支持) |
START | 枚举 | 开始录音回调,RecordInfo 中包含 File audioFile, RecordType recordType |
SUCCESS | 枚举 | 录音结束,成功,RecordInfo 中包含 File audioFile, long audioLength, RecordType recordType |
- 示例
dart/// 监听录音过程事件
NimCore.instance.audioService.onAudioRecordStatus.listen((RecordInfo recordInfo) {
});
录制控制
- 录制音频
dart/// 启动(开始)录音,如果成功,会按照顺序回调onRecordReady和onRecordStart。
NimCore.instance.audioService.startRecord(Map<String,dynamic> param);
/// 参数配置param中支持 int参数recordType, 0代表acc,1代表amr录制音频类型,maxLength,最长录音时长,到该长度后,会自动停止录音, 默认120s
);
- 结束/取消录制
dart// 结束录音
NimCore.instance.audioService.stopAudioRecord();
- 取消录音
dartNimCore.instance.audioService.cancelAudioRecord();
- 其他方法
dart
/// 是否正在录音
NimCore.instance.audioService.isRecording();
/// 获取当前录音时最大振幅, 40ms更新一次数据。
NimCore.instance.audioService.getAmplitude();
语音转文字
要使用语音转文字功能,请联系商务顾问申请开通「语音识别」。如果未开通功能的情况下调用接口,将返回 403。
语音转文字的原理:
- 录制音频文件(目前最大支持 60 秒)。
- 上传到云信存储服务器,返回文件 url。
- 通过语音转文字接口传入该 url 和相关参数,返回转换后的文字。
使用 messageService 接口中如下方法进行语音转文字:
dart
/// 语音转文字并指定上传文件的场景以及是否要强制重新上传文件
/// [message] - 需要转换成文字的消息对象。
/// [scene] - 消息场景信息,非必须参数
Future<NIMResult<String>> voiceToText(
{required NIMMessage message, String? scene});
示例:
dartvar result = await NimCore.instance.messageService
.voiceToText(message);