收发消息
功能简介
本文档适用于开发以下平台的应用:iOS、Android、macOS、Windows、Web。
ZIM SDK 支持单聊消息、群组消息、房间消息等的收发,以及查询历史消息、删除消息等功能。可广泛应用于娱乐社交、电商购物、在线教育、互动直播等多种场景下。
本文档介绍了如何使用 ZIM SDK 的接口,实现各类消息的收发功能与监听消息的状态。
消息类型
目前 ZIM 支持的消息类型如下:
消息类型 | 说明 | 特性及适用场景 |
---|
ZIMCommandMessage(2) | 开发者可自定义数据内容的信令消息。消息大小不超过 5 KB,单个客户端发送频率限制为 10 次/秒。 | 不可存储,支持更高的并发;一般适用于“语聊房”、“在线课堂”等房间内的信令传输,比如上下麦操作、送礼物,发送在线课堂课件等。 相关接口:sendMessage |
ZIMBarrageMessage(20) | 房间内弹幕文本消息。消息大小不超过 5 KB,单个客户端发送频率无限制。 | 不可存储,专门用于房间内的高频、不可靠、允许丢掉的消息,一般适用于发送“弹幕消息”的场景中。 支持高并发,但不可靠,不保证消息送达。 相关接口:sendMessage |
ZIMTextMessage(1) | 文本消息。消息大小不超过 32 KB,单个客户端发送频率限制为 10 次/秒。 | 消息可靠有序,可存储为历史消息(保存时间请参考 计费说明 - 版本说明 中“历史消息存储天数”)。
可用于单聊、房间、群聊等即时聊天场景。房间解散后,“房间聊天”的消息不存储。
- 图片、文件、语音、视频:通常用于发送富媒体文件类型的消息。
- 自定义消息:通常用于发送投票类型、接龙类型、视频卡片类型等消息。
- 组合消息:常用于发送图文消息。
相关接口:sendMessage、replyMessage |
ZIMMultipleMessage(10) | 组合消息,即包含多个 item 的消息,可包括多条文本、至多 10 张图片、1 个文件、1 个音频、1 个视频和 1 条自定义消息。- Item 总量不得超过 20。
- 图片、音频、文件和视频的大小和格式限制与对应的富媒体消息类型相同。
|
ZIMImageMessage(11) | 图片消息。支持主流图片格式,包括 JPG、PNG、BMP、TIFF、GIF、WebP,大小不超过 10 MB,单个客户端发送频率限制为 10 次/秒。 |
ZIMFileMessage(12) | 文件消息。消息内容为文件,格式不限,大小不超过 100 MB,单个客户端发送频率限制为 10 次/秒。 |
ZIMAudioMessage(13) | 语音消息。支持 MP3、M4A 格式的语音文件,时长不超过 300 秒,大小不超过 6 MB,单个客户端发送频率限制为 10 次/秒。 |
ZIMVideoMessage(14) | 视频消息。支持 MP4、MOV 格式的视频文件,大小不超过 100 MB,单个客户端发送频率限制为 10 次/秒。若要在消息发送成功后获取视频首帧的宽高信息,视频必须使用 H.264 或 H.265 编码格式。 |
ZIMCombineMessage(100) | 合并消息,消息大小无限制,单个客户端发送频率限制为 10 次/秒。 |
ZIMCustomMessage(200) | 自定义消息。开发者可自定义消息的类型,并自行完成消息的解析,ZIM SDK 不负责定义和解析自定义消息的具体内容。 |
收发普通消息
普通消息,包含 ZIMTextMessage、ZIMBarrageMessage 等消息类型。
发送消息
以客户端 A 向客户端 B 发送消息为例:
- 客户端 A、B 分别创建自己的 ZIM 实例,并注册 setEventHandler 监听的 onPeerMessageReceived 回调接口,用于接收单聊消息通知。
- 客户端 A、B 分别登录 ZIM SDK。
- 客户端 A 调用 sendMessage 接口,设置
conversationType
为 ZIMConversationType.Peer
发送一条单聊消息到客户端 B。
- 客户端 B 将通过 onPeerMessageReceived 回调接口,收到客户端 A 的消息。
目前 ZIM 不支持调用 sendMessage 接口,向自己发送消息(即 toConversationID = 自己的 ID)。如果尝试向自己发送消息,会返回错误 6000001,并提示传入参数错误。
// 发送单聊 `Text` 信息
String toConversationID = "xxxx1";
ZIMTextMessage zimMessage = new ZIMTextMessage();
zimMessage.message = "消息内容";
ZIMMessageSendConfig config = new ZIMMessageSendConfig();
// 设置消息优先级
config.priority = ZIMMessagePriority.LOW;
// 设置消息的离线推送配置
ZIMPushConfig pushConfig = new ZIMPushConfig();
pushConfig.title = "离线推送的标题";
pushConfig.content= "离线推送的内容";
pushConfig.extendedData = "离线推送的扩展信息";
config.pushConfig = pushConfig;
ZIMConversationType type = ZIMConversationType.Peer;
zim.sendMessage(zimMessage, toConversationID, type, config, new ZIMMessageSentFullCallback() {
@Override
public void onMessageAttached(ZIMMessage zimMessage) {
// 开发者可以通过该回调,监听消息是否开始准备发送。只有当通过本地基础参数检验的消息才会抛出该回调,否则通过 onMessageSent 回调抛出错误。
}
@Override
public void onMessageSent(ZIMMessage zimMessage, ZIMError error) {
// 开发者可以通过该回调监听消息是否发送成功。
}
});
1
// 发送单聊 `Text` 信息
NSString *toConversationID = @"xxxx1";
ZIMTextMessage *textMessage = [[ZIMTextMessage alloc] init];
textMessage.message = @"消息内容";
ZIMMessageSendConfig *config = [[ZIMMessageSendConfig alloc] init];
// 设置消息优先级
config.priority = ZIMMessagePriorityLow;
// 设置消息的离线推送配置。若使用该功能,需要先开通离线推送服务
ZIMPushConfig *pushConfig = [[ZIMPushConfig alloc] init];
pushConfig.title = @"离线推送的标题";
pushConfig.content= @"离线推送的内容";
pushConfig.extendedData = @"离线推送的扩展信息";
config.pushConfig = pushConfig
ZIMMessageSendNotification *notification = [[ZIMMessageSendNotification alloc] init];
notification.onMessageAttached = ^(ZIMMessage * _Nonnull message) {
// 发送前的回调,客户可以在这里获取一个临时对象,该对象与开发者创建的 zimMessage 对象属于同一对象,开发者可利用此特性做一些业务逻辑,如提前展示 UI 等
};
ZIMConversationType type = ZIMConversationTypePeer;
[self.zim sendMessage:textMessage toConversationID:toConversationID conversationType:type config:config notification:notification callback:^((ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo)) {
// 开发者可以通过该回调监听消息是否发送成功。
}];
1
// 发送单聊 `Text` 信息
zim::ZIMMessage* message = nullptr;
zim::ZIMTextMessage text_message;
text_message.message = "message";
// 设置消息优先级
zim::ZIMMessageSendConfig config;
config.priority = zim::ZIM_MESSAGE_PRIORITY_LOW;
message = &text_message;
zim::ZIMConversationType type = zim::ZIMConversationType::ZIM_CONVERSATION_TYPE_PEER
auto notification = std::make_shared<zim::ZIMMessageSendNotification>(
[=](const std::shared_ptr<zim::ZIMMessage> &message) { int i = 0; });
zim_->sendMessage(message, "toConversationID", type, config, notification,
[=](const std::shared_ptr<zim::ZIMMessage> &message,
const zim::ZIMError &errorInfo) { int i = 0; });
1
// 发送单聊 `Text` 信息
var toConversationID = ''; // 对方 userID
var conversationType = 0; // 会话类型,取值为 单聊:0,房间:1,群组:2
var config = {
priority: 1, // 设置消息优先级,取值为 低:1(默认),中:2,高:3
};
var notification = {
onMessageAttached: function(message) {
}
}
var messageTextObj = {
type: 1,
message: 'xxxx'
};
zim.sendMessage(messageTextObj, toConversationID, conversationType, config, notification)
.then(function ({ message }) {
// 发送成功
})
.catch(function (err) {
// 发送失败
});
1
// 发送单聊 `Text` 信息
ZIMTextMessage textMessage = ZIMTextMessage(message: "message");
ZIMMessageSendConfig sendConfig = ZIMMessageSendConfig();
// 设置消息优先级
sendConfig.priority = ZIMMessagePriority.low;
ZIMPushConfig pushConfig = ZIMPushConfig();
pushConfig.title = "离线推送的标题";
pushConfig.content = "离线推送的内容";
pushConfig.extendedData = "离线推送的扩展信息";
sendConfig.pushConfig = pushConfig;
ZIMMessageSendNotification notification = ZIMMessageSendNotification(onMessageAttached: (message){
// 发送前的回调,开发者可以在这里获取一个临时对象,该对象与开发者创建的 zimMessage 对象属于同一对象,开发者可利用此特性做一些业务逻辑,如提前展示 UI 等
});
ZIMConversationType type = ZIMConversationType.peer;
ZIM.getInstance()!.sendMessage(textMessage, toConversationID, type, sendConfig).then((value) => {
// 开发者可以通过该回调监听消息是否发送成功。
}).catchError((onError){
// 开发者可以捕获发送失败的异常。
});
1
接收消息
- 发送消息时,统一使用 sendMessage 接口,并根据会话类型传入对应的 conversationType 取值。
- 接收消息时:
zim.setEventHandler(new ZIMEventHandler() {
@Override
public void onPeerMessageReceived(ZIM zim, ArrayList<ZIMMessage> messageList, ZIMMessageReceivedInfo info, String fromUserID) {
// 收到“单聊”通信的消息回调
for (ZIMMessage zimMessage : messageList) {
if (zimMessage instanceof ZIMTextMessage) {
ZIMTextMessage zimTextMessage = (ZIMTextMessage) zimMessage;
Log.e(TAG, "收到的文本消息:"+ zimTextMessage.message);
} else if (zimMessage instanceof ZIMCommandMessage) {
ZIMCommandMessage zimCommandMessage = (ZIMCommandMessage) zimMessage;
Log.e(TAG, "收到的信令消息:"+ zimCommandMessage.message);
}
}
}
@Override
public void onGroupMessageReceived(ZIM zim, ArrayList<ZIMMessage> messageList, ZIMMessageReceivedInfo info, String fromGroupID) {
// 收到群组消息的回调
for (ZIMMessage zimMessage : messageList) {
if (zimMessage instanceof ZIMTextMessage) {
ZIMTextMessage zimTextMessage = (ZIMTextMessage) zimMessage;
Log.e(TAG, "收到的文本消息:"+ zimTextMessage.message);
} else if (zimMessage instanceof ZIMCommandMessage) {
ZIMCommandMessage zimCommandMessage = (ZIMCommandMessage) zimMessage;
Log.e(TAG, "收到的信令消息:"+ zimCommandMessage.message);
}
}
}
@Override
public void onRoomMessageReceived(ZIM zim, ArrayList<ZIMMessage> messageList, ZIMMessageReceivedInfo info, String fromRoomID) {
// 收到房间消息的回调
for (ZIMMessage zimMessage : messageList) {
if (zimMessage instanceof ZIMTextMessage) {
ZIMTextMessage zimTextMessage = (ZIMTextMessage) zimMessage;
Log.e(TAG, "收到的文本消息:"+ zimTextMessage.message);
} else if (zimMessage instanceof ZIMCommandMessage) {
ZIMCommandMessage zimCommandMessage = (ZIMCommandMessage) zimMessage;
Log.e(TAG, "收到的信令消息:"+ zimCommandMessage.message);
}
}
}
});
1
//注册 ZIMEventHander 回调
[zim setEventHandler:self];
// 收到单聊消息的回调
- (void)zim:(ZIM *)zim
peerMessageReceived:(NSArray<ZIMMessage *> *)messageList
info:(ZIMMessageReceivedInfo *)info
fromUserID:(NSString *)fromUserID{
// 在此编写收到消息后的业务逻辑
}
// 收到群组消息的回调
- (void)zim:(ZIM *)zim
groupMessageReceived:(NSArray<ZIMMessage *> *)messageList
info:(ZIMMessageReceivedInfo *)info
fromGroupID:(NSString *)fromGroupID{
// 在此编写收到消息后的业务逻辑
}
// 收到房间消息的回调
- (void)zim:(ZIM *)zim
roomMessageReceived:(NSArray<ZIMMessage *> *)messageList
info:(ZIMMessageReceivedInfo *)info
fromRoomID:(NSString *)fromRoomID{
// 在此编写收到消息后的业务逻辑
}
1
// 收到单聊消息的回调
void onPeerMessagedReceived(ZIM *zim*,
const std::vector<std::shared_ptr<ZIMMessage>> & messageList,
const ZIMMessageReceivedInfo & info,
const std::string &fromUserID) {
//在此编写收到消息后的业务逻辑
}
// 收到群组消息的回调
void onGroupMessagedReceived(ZIM *zim*,
const std::vector<std::shared_ptr<ZIMMessage>> & messageList,
const ZIMMessageReceivedInfo & info,
const std::string &fromGroupID) {
//在此编写收到消息后的业务逻辑
}
// 收到房间消息的回调
void onRoomMessagedReceived(ZIM *zim*,
const std::vector<std::shared_ptr<ZIMMessage>> & messageList,
const ZIMMessageReceivedInfo & info,
const std::string &fromRoomID) {
//在此编写收到消息后的业务逻辑
}
1
// 收到单聊通信的消息回调
zim.on('peerMessageReceived', function (zim, { messageList, info, fromConversationID }) {
console.log(messageList, info, fromConversationID);
});
// 收到群组消息的回调
zim.on('groupMessageReceived', function (zim, { messageList, info, fromConversationID }) {
console.log(messageList, info, fromConversationID);
});
// 收到房间消息的回调
zim.on('roomMessageReceived', function (zim, { messageList, info, fromConversationID }) {
console.log(messageList, info, fromConversationID);
});
1
ZIMEventHandler.onPeerMessageReceived = (zim, messageList, info, fromUserID) {
//收到单聊消息触发此处
};
ZIMEventHandler.onGroupMessageReceived = (zim, messageList, info, fromGroupID) {
//收到群聊消息触发此处
};
ZIMEventHandler.onRoomMessageReceived = (zim, messageList, info, fromGroupID) {
//收到房间消息触发此处
};
1
收发富媒体消息
ZIM SDK 支持发送多种类型的富媒体消息,包含图片、文件、音频、视频等消息类型,开发者可以通过以下步骤实现富媒体文件消息的收发。
- 用户登录成功后,指定消息类型(图片、文件、音频、视频)、会话类型(单聊、房间、群组)等,向指定会话发送富媒体消息。
- 接收方用户登录成功后,根据会话类型(单聊、房间、群组)的相关回调监听,接收富媒体消息的相关通知,以及下载富媒体消息文件到本地。
- 用户登录成功后,指定消息类型(图片、文件、音频、视频)、会话类型(单聊、房间、群组)等,向指定会话发送富媒体消息。
- 接收方用户登录成功后,根据会话类型(单聊、房间、群组)的相关回调监听,接收富媒体消息的相关通知。
发送富媒体消息
用户登录成功后,调用 sendMessage 接口,指定会话、消息类型(图片、文件、音频、视频)、会话类型(单聊、房间、群组)、以及相关消息配置,向指定会话发送富媒体消息。
- 发送富媒体消息时,填写的待发送文件路径,必须使用
UTF-8
编码格式。
- 如果需要向房间/群组内发送富媒体消息,消息发送者必须要在这个房间/群组内。
// 发送富媒体消息消息示例 - 单聊 发送图片消息
ZIMImageMessage message = new ZIMImageMessage("/storage/emulated/0/Android/data/packagename/picture/xxx.jpg");
// 如果此处填了网络 URL,SDK 则会透传该路径,而不会经过 ZIM 后台服务处理,同时填入网络 URL 与本地路径,SDK 会优先认为用户想要使用网络 URL
message.setLargeImageDownloadUrl("url");
message.setFileDownloadUrl("url");
message.setThumbnailDownloadUrl("url");
ZIMMessageSendConfig config = new ZIMMessageSendConfig();
// 设置消息优先级
config.priority = ZIMMessagePriority.LOW;
// 设置消息的离线推送配置
// 不支持设置房间消息的离线推送配置,如果需要发送房间离线消息,请联系 ZEGO 技术支持开通相关权限
ZIMPushConfig pushConfig = new ZIMPushConfig();
pushConfig.title = "离线推送的标题";
pushConfig.content= "离线推送的内容";
pushConfig.extendedData = "离线推送的扩展信息";
config.pushConfig = pushConfig;
zim.sendMessage(message, toConversationID, ZIMConversationType.PEER, config, new ZIMMessageSentFullCallback() {
@Override
public void onMessageSent(ZIMMessage message, ZIMError errorInfo) {
// 开发者可以通过该回调,监听消息是否开始准备发送。只有当通过本地基础参数检验的消息才会抛出该回调,否则通过 onMessageSent 回调抛出错误。
}
@Override
public void onMessageAttached(ZIMMessage message){
}
@Override
public void onMediaUploadingProgress(ZIMMediaMessage message, long currentFileSize, long totalFileSize, ) {
// 开发者可以通过该回调监听消息是否发送成功。
}
});
1
// 发送富媒体消息消息示例 - 单聊 发送文件消息
ZIMFileMessage message = new ZIMFileMessage("/storage/emulated/0/Android/data/packagename/picture/xxx.zip");
// 如果此处填了网络 URL,SDK 则会透传该路径,而不会经过 ZIM 后台服务处理,同时填入网络 URL 与本地路径,SDK 会优先认为用户想要使用网络 URL
message.setFileDownloadUrl("url");
ZIMMessageSendConfig config = new ZIMMessageSendConfig();
config.priority = ZIMMessagePriority.HIGH;
zim.sendMessage(message, conversationID, ZIMConversationType.PEER, config, new ZIMMessageSentFullCallback() {
@Override
public void onMessageSent(ZIMMessage message, ZIMError errorInfo) {
}
@Override
public void onMessageAttached(ZIMMessage message){
}
@Override
public void onMediaUploadingProgress(ZIMMediaMessage message, long currentFileSize, long totalFileSize) {
}
});
1
// 发送富媒体消息消息示例 - 单聊 发送音频消息
ZIMAudioMessage message = new ZIMAudioMessage("/storage/emulated/0/Android/data/packagename/picture/xxx.mp3", 300); // 这里的300只是举例,单位是秒。
// 如果此处填了网络 URL,SDK 则会透传该路径,而不会经过 ZIM 后台服务处理,同时填入网络 URL 与本地路径,SDK 会优先认为用户想要使用网络 URL
message.setFileDownloadUrl("url");
ZIMMessageSendConfig config = new ZIMMessageSendConfig();
ZIMMessageSendConfig config = new ZIMMessageSendConfig();
config.priority = ZIMMessagePriority.HIGH;
zim.sendMessage(message, conversationID, ZIMConversationType.PEER, config, new ZIMMessageSentFullCallback() {
@Override
public void onMessageSent(ZIMMessage message, ZIMError errorInfo) {
}
@Override
public void onMessageAttached(ZIMMessage message){
}
@Override
public void onMediaUploadingProgress(ZIMMediaMessage message, long currentFileSize, long totalFileSize) {
}
});
1
// 发送富媒体消息消息示例 - 单聊 发送视频消息
ZIMVideoMessage message = new ZIMVideoMessage("/storage/emulated/0/Android/data/packagename/picture/xxx.mp4", 300);//这里单位是秒
// 如果此处填了网络 URL,SDK 则会透传该路径,而不会经过 ZIM 后台服务处理,同时填入网络 URL 与本地路径,SDK 会优先认为用户想要使用网络 URL
message.setFileDownloadUrl("url");
message.videoFirstFrameDownloadUrl("url");
ZIMMessageSendConfig config = new ZIMMessageSendConfig();
config.priority = ZIMMessagePriority.HIGH;
zim.sendMessage(message, conversationID, ZIMConversationType.PEER, config, new ZIMMessageSentFullCallback() {
@Override
public void onMessageSent(ZIMMessage message, ZIMError errorInfo) {
}
@Override
public void onMessageAttached(ZIMMessage message){
}
@Override
public void onMediaUploadingProgress(ZIMMediaMessage message, long currentFileSize, long totalFileSize) {
}
});
1
// 发送多媒体消息示例 - 单聊 发送图片消息
ZIMImageMessage *imgMsg = [[ZIMImageMessage alloc] init];
//需填入 UTF-8 格式的本地路径(建议填写 app 本地图片的路径)
//此处以一个相册图片临时路径为例
imgMsg.fileLocalPath = @"/private/var/mobile/Containers/Data/Application/C142EFE6-9DEC-449D-89B7-BF99F2578F98/tmp/D1513E30-2641-440B-B897-48CD43BE1D04.jpeg";
//如果此处填入了网络 URL, SDK 会透传该路径,而不会经过 ZIM 后台服务处理, 同时填入网络 URL 与本地路径,SDK 会优先认为用户想要使用网路 URL
imgMsg.fileDownloadUrl = @"";
ZIMMessageSendConfig *sendConfig = [[ZIMMessageSendConfig alloc] init];
sendConfig.priority = 1;
ZIMMessageSendNotification *notification = [[ZIMMessageSendNotification alloc] init];
notification.onMessageAttached = ^(ZIMMessage * _Nonnull message) {
// 开发者可以监听这个回调执行消息发送前的业务逻辑
};
notification.onMediaUploadingProgress = ^(ZIMMediaMessage * _Nonnull message, unsigned long long currentFileSize, unsigned long long totalFileSize) {
// 开发者可以监听这个回调获取多媒体上传的进度
};
[[ZIM getInstance] sendMessage:imgMsg toConversationID:@"conversationID" conversationType:ZIMConversationTypePeer config:sendConfig notification:notification callback:^(ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo) {
}];
1
// 发送多媒体消息示例 - 单聊 发送音频消息
//需填入 UTF-8 格式的本地路径(建议填写 app 本地音频的路径),音频时间(单位秒)
//此处以一个本地音频文件路径为例
ZIMAudioMessage audioMessage = [[ZIMAudioMessage alloc] initWithFileLocalPath:@"/private/var/mobile/Containers/Shared/AppGroup/D5144D14-3FE8-4C6C-8527-01F368B8E49E/File Provider Storage/IMG_0131.mp3" audioDuration:10];
//如果此处填入了网络 URL, SDK 会透传该路径,而不会经过 ZIM 后台服务处理, 同时填入网络 URL 与本地路径,SDK 会优先任务用户想要使用网路 URL
audioMessage.fileDownloadUrl = @"";
ZIMMessageSendConfig *sendConfig = [[ZIMMessageSendConfig alloc] init];
sendConfig.priority = ZIMMessagePriorityHigh;
ZIMMessageSendNotification *notification = [[ZIMMessageSendNotification alloc] init];
notification.onMessageAttached = ^(ZIMMessage * _Nonnull message) {
// 开发者可以监听这个回调执行消息发送前的业务逻辑
};
notification.onMediaUploadingProgress = ^(ZIMMediaMessage * _Nonnull message, unsigned long long currentFileSize, unsigned long long totalFileSize) {
// 开发者可以监听这个回调获取多媒体上传的进度
};
[[ZIM getInstance] sendMessage:audioMessage toConversationID:@"conversationID" conversationType:ZIMConversationTypePeer config:sendConfig notification:notification callback:^(ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo) {
}];
1
// 发送多媒体消息示例 - 单聊 发送视频消息
ZIMVideoMessage *videoMessage = [[ZIMVideoMessage alloc] init];
//需填入 UTF-8 格式的本地路径
//此处以一个本地视频路径为例
videoMessage.fileLocalPath = @"/var/mobile/Containers/Data/Application/C142EFE6-9DEC-449D-89B7-BF99F2578F98/Documents/22-08-31-10:23:49.mp4";
//如果此处填入了网络 URL, SDK 会透传该路径,而不会经过 ZIM 后台服务处理, 同时填入网络 URL 与本地路径,SDK 会优先认为用户想要使用网路 URL
videoMessage.fileDownloadUrl = @"";
ZIMMessageSendConfig *sendConfig = [[ZIMMessageSendConfig alloc] init];
sendConfig.priority = ZIMMessagePriorityHigh;
ZIMMessageSendNotification *notification = [[ZIMMessageSendNotification alloc] init];
notification.onMessageAttached = ^(ZIMMessage * _Nonnull message) {
// 开发者可以监听这个回调执行消息发送前的业务逻辑
};
notification.onMediaUploadingProgress = ^(ZIMMediaMessage * _Nonnull message, unsigned long long currentFileSize, unsigned long long totalFileSize) {
// 开发者可以监听这个回调获取多媒体上传的进度
};
[[ZIM getInstance] sendMessage:videoMessage toConversationID:@"conversationID" conversationType:ZIMConversationTypePeer config:sendConfig notification:notification callback:^(ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo) {
}];
1
// 发送多媒体消息示例 - 单聊 发送文件消息
ZIMFileMessage *fileMsg = [[ZIMFileMessage alloc] init];
//需填入 UTF-8 格式的本地路径
//此处以文件选择器选中的某个文件地址为例
fileMsg.fileLocalPath = @"/private/var/mobile/Containers/Shared/AppGroup/D5144D14-3FE8-4C6C-8527-01F368B8E49E/File Provider Storage/IMG_0131.HEIC";
//如果此处填入了网络 URL, SDK 会透传该路径,而不会经过 ZIM 后台服务处理, 同时填入网络 URL 与本地路径,SDK 会优先认为用户想要使用网路 URL
fileMsg.fileDownloadUrl = @"";
ZIMMessageSendConfig *sendConfig = [[ZIMMessageSendConfig alloc] init];
sendConfig.priority = ZIMMessagePriorityHigh;
ZIMMessageSendNotification *notification = [[ZIMMessageSendNotification alloc] init];
notification.onMessageAttached = ^(ZIMMessage * _Nonnull message) {
// 开发者可以监听这个回调执行消息发送前的业务逻辑
};
notification.onMediaUploadingProgress = ^(ZIMMediaMessage * _Nonnull message, unsigned long long currentFileSize, unsigned long long totalFileSize) {
// 开发者可以监听这个回调获取多媒体上传的进度
};
[[ZIM getInstance] sendMessage:fileMsg toConversationID:@"conversationID" conversationType:ZIMConversationTypePeer config:sendConfig notification:notification callback:^(ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo) {
}];
1
// 发送多媒体消息示例 - 单聊 发送图片消息
zim::ZIMMediaMessage *message = nullptr;
auto imageMessage = zim::ZIMImageMessage();
zim::ZIMMessageSendConfig sendConfig;
zim::ZIMPushConfig pushConfig;
// 离线推送标题,需要离线推送时,请填入该字段
pushConfig.title = "win_push_title";
// 离线推送内容,需要离线推送时,请填入该字段
pushConfig.content = "win_push_content";
// 离线推送附加字段,需要离线推送带上额外信息时,可酌情填入该字段
pushConfig.extendedData = "win_push_extended_data";
sendConfig.priority = zim::ZIM_MESSAGE_PRIORITY_MEDIUM;
// 需要离线推送时赋值;如不需要,可赋值为 nullptr
sendConfig.pushConfig = &pushConfig;
// 需填入 UTF-8 格式的本地路径
imageMessage.fileLocalPath = "D:\\image\\img.jpg";
// 如果此处填入了网络 URL,SDK 则会透传该路径,而不会经过 ZIM 后台服务处理。同时填入网络 URL 与本地路径,SDK 会优先认为用户想要使用网络 URL
imageMessage.fileDownloadUrl = "";
imageMessage.largeImageDownloadUrl = "";
imageMessage.thumbnailDownloadUrl = "";
message = &imageMessage;
auto notification = std::make_shared<zim::ZIMMessageSendNotification>(
[=](const std::shared_ptr<zim::ZIMMessage> &message) {
// 开发者可监听此回调,执行消息发送前的逻辑
},
[=](const std::shared_ptr<zim::ZIMMediaMessage> &message,
unsigned long long currentFileSize,
unsigned long long totalFileSize) {
// 开发者可监听此回调,获取资源上传的进度
});
zim_->sendMessage(message, receiver_id, zim::ZIMConversationType::ZIM_CONVERSATION_TYPE_PEER,
sendConfig,notification,
[=](const std::shared_ptr<zim::ZIMMessage> &message, const zim::ZIMError &errorInfo) {
});
1
// 发送多媒体消息示例 - 单聊 发送文件消息
zim::ZIMMediaMessage *message = nullptr;
auto fileMessage = zim::ZIMFileMessage();
zim::ZIMMessageSendConfig sendConfig;
zim::ZIMPushConfig pushConfig;
// 离线推送标题,需要离线推送时,请填入该字段
pushConfig.title = "win_push_title";
// 离线推送内容,需要离线推送时,请填入该字段
pushConfig.content = "win_push_content";
// 离线推送附加字段,需要离线推送带上额外信息时,可酌情填入该字段
pushConfig.extendedData = "win_push_extended_data";
sendConfig.priority = zim::ZIM_MESSAGE_PRIORITY_MEDIUM;
// 需要离线推送时赋值;如不需要,可赋值为 nullptr
sendConfig.pushConfig = &pushConfig;
// 需填入 UTF-8 格式的本地路径
fileMessage.fileLocalPath = "D:\\file\\files.zip";
// 如果此处填入了网络 URL,SDK 则会透传该路径,而不会经过 ZIM 后台服务处理。同时填入网络 URL 与本地路径,SDK 会优先认为用户想要使用网络 URL
fileMessage.fileDownloadUrl = "";
message = &fileMessage;
auto notification = std::make_shared<zim::ZIMMessageSendNotification>(
[=](const std::shared_ptr<zim::ZIMMessage> &message) {
// 开发者可监听此回调,执行消息发送前的逻辑
},
[=](const std::shared_ptr<zim::ZIMMediaMessage> &message,
unsigned long long currentFileSize,
unsigned long long totalFileSize) {
// 开发者可监听此回调,获取资源上传的进度
});
zim_->sendMessage(message, receiver_id, zim::ZIMConversationType::ZIM_CONVERSATION_TYPE_PEER,
sendConfig,,notification,
[=](const std::shared_ptr<zim::ZIMMessage> &message, const zim::ZIMError &errorInfo) {
auto media_message = std::static_pointer_cast<zim::ZIMFileMessage>(message);
int code = errorInfo.code;
});
1
// 发送多媒体消息示例 - 单聊 发送音频消息
zim::ZIMMediaMessage *message = nullptr;
auto audioMessage = zim::ZIMAudioMessage();
zim::ZIMMessageSendConfig sendConfig;
zim::ZIMPushConfig pushConfig;
// 离线推送标题,需要离线推送时,请填入该字段
pushConfig.title = "win_push_title";
// 离线推送内容,需要离线推送时,请填入该字段
pushConfig.content = "win_push_content";
// 离线推送附加字段,需要离线推送带上额外信息时,可酌情填入该字段
pushConfig.extendedData = "win_push_extended_data";
sendConfig.priority = zim::ZIM_MESSAGE_PRIORITY_MEDIUM;
// 需要离线推送时赋值;如不需要,可赋值为 nullptr
sendConfig.pushConfig = &pushConfig;
// 需填入 UTF-8 格式的本地路径
audioMessage.fileLocalPath = "D:\\audio\\audio.mp3";
// 如果此处填入了网络 URL,SDK 则会透传该路径,而不会经过 ZIM 后台服务处理。同时填入网络 URL 与本地路径,SDK 会优先认为用户想要使用网络 URL
audioMessage.fileDownloadUrl = "";
// 音频时长的单位为 秒
audioMessage.audioDuration = 15;
message = &audioMessage;
auto notification = std::make_shared<zim::ZIMMessageSendNotification>(
[=](const std::shared_ptr<zim::ZIMMessage> &message) {
// 开发者可监听此回调,执行消息发送前的逻辑
},
[=](const std::shared_ptr<zim::ZIMMediaMessage> &message,
unsigned long long currentFileSize,
unsigned long long totalFileSize) {
// 开发者可监听此回调,获取资源上传的进度
});
zim_->sendMessage(message, receiver_id, zim::ZIMConversationType::ZIM_CONVERSATION_TYPE_PEER,
sendConfig,notification ,
[=](const std::shared_ptr<zim::ZIMMessage> &message, const zim::ZIMError &errorInfo) {
auto media_message = std::static_pointer_cast<zim::ZIMAudioMessage>(message);
int code = errorInfo.code;
});
1
// 发送多媒体消息示例 - 单聊 发送视频消息
zim::ZIMMediaMessage *message = nullptr;
auto videoMessage = zim::ZIMVideoMessage();
zim::ZIMMessageSendConfig sendConfig;
zim::ZIMPushConfig pushConfig;
// 离线推送标题,需要离线推送时,请填入该字段
pushConfig.title = "win_push_title";
// 离线推送内容,需要离线推送时,请填入该字段
pushConfig.content = "win_push_content";
// 离线推送附加字段,需要离线推送带上额外信息时,可酌情填入该字段
pushConfig.extendedData = "win_push_extended_data";
sendConfig.priority = zim::ZIM_MESSAGE_PRIORITY_MEDIUM;
// 需要离线推送时赋值;如不需要,可赋值为 nullptr
sendConfig.pushConfig = &pushConfig;
// 需填入 UTF-8 格式的本地路径
videoMessage.fileLocalPath = "D:\\file\\video.mp4";
// 如果此处填入了网络 URL,SDK 则会透传该路径,而不会经过 ZIM 后台服务处理。同时填入网络 URL 与本地路径,SDK 会优先认为用户想要使用网络 URL
videoMessage.fileDownloadUrl = "";
videoMessage.videoFirstFrameDownloadUrl = "";
// 视频时长的单位为 秒
videoMessage.videoDuration = 100;
message = &videoMessage;
auto notification = std::make_shared<zim::ZIMMessageSendNotification>(
[=](const std::shared_ptr<zim::ZIMMessage> &message) {
// 开发者可监听此回调,执行消息发送前的逻辑
},
[=](const std::shared_ptr<zim::ZIMMediaMessage> &message,
unsigned long long currentFileSize,
unsigned long long totalFileSize) {
// 开发者可监听此回调,获取资源上传的进度
});
zim_->sendMessage(message, receiver_id, zim::ZIMConversationType::ZIM_CONVERSATION_TYPE_PEER,
sendConfig,notification,
[=](const std::shared_ptr<zim::ZIMMessage> &message, const zim::ZIMError &errorInfo) {
auto media_message = std::static_pointer_cast<zim::ZIMVideoMessage>(message);
int code = errorInfo.code;
});
1
// 发送多媒体消息示例 - 单聊 发送图片消息
ZIMImageMessage imageMessage = ZIMImageMessage('xxx/xxx.jpeg');
ZIMMessageSendConfig sendConfig = ZIMMessageSendConfig();
ZIMMessageSendNotification notification = ZIMMessageSendNotification(onMessageAttached: (message){
// 开发者可以监听这个回调执行消息发送前的业务逻辑
},onMediaUploadingProgress: (message,currentFileSize,totalFileSize){
// 开发者可以监听这个回调获取多媒体上传的进度
});
ZIM.getInstance()!.sendMessage(
imageMessage,
'toConversationID',
ZIMConversationType.peer,
sendConfig, notification).then((value) => {
//成功触发此处
}).catchError((onError){
//失败触发此处
});
1
// 发送多媒体消息示例 - 单聊 发送视频消息
ZIMVideoMessage videoMessage = ZIMVideoMessage('xxx/xxx.mov');
ZIMMessageSendConfig sendConfig = ZIMMessageSendConfig();
ZIMMessageSendNotification notification = ZIMMessageSendNotification(onMessageAttached: (message){
// 开发者可以监听这个回调执行消息发送前的业务逻辑
},onMediaUploadingProgress: (message,currentFileSize,totalFileSize){
// 开发者可以监听这个回调获取多媒体上传的进度
});
ZIM
.getInstance()
!.sendMessage(
videoMessage,
'toConversationID',
ZIMConversationType.peer,
sendConfig, notification)
.then((value) => {
//成功触发此处
})
.catchError((onError) {
//失败触发此处
});
1
// 发送多媒体消息示例 - 单聊 发送音频消息
ZIMAudioMessage audioMessage = ZIMAudioMessage('xxx/xxx.mp3');
ZIMMessageSendConfig sendConfig = ZIMMessageSendConfig();
ZIMMessageSendNotification notification = ZIMMessageSendNotification(onMessageAttached: (message){
// 开发者可以监听这个回调执行消息发送前的业务逻辑
},onMediaUploadingProgress: (message,currentFileSize,totalFileSize){
// 开发者可以监听这个回调获取多媒体上传的进度
});
ZIM
.getInstance()
!.sendMessage(
audioMessage,
'toConversationID',
ZIMConversationType.peer,
ZIMMessageSendConfig(), notification)
.then((value) => {
//成功触发此处
})
.catchError((onError) {
//失败触发此处
});
1
// 发送多媒体消息示例 - 单聊 发送文件消息
ZIMFileMessage fileMessage = ZIMFileMessage('xxx/xxx.txt');
ZIMMessageSendConfig sendConfig = ZIMMessageSendConfig();
ZIMMessageSendNotification notification = ZIMMessageSendNotification(onMessageAttached: (message){
// 开发者可以监听这个回调执行消息发送前的业务逻辑
},onMediaUploadingProgress: (message,currentFileSize,totalFileSize){
// 开发者可以监听这个回调获取多媒体上传的进度
});
ZIM
.getInstance()
!.sendMessage(
fileMessage,
'toConversationID',
ZIMConversationType.peer,
ZIMMessageSendConfig(), notification)
.then((value) => {
//成功触发此处
})
.catchError((onError) {
//失败触发此处
});
1
富媒体文件消息的发送进度回调
开发者可以通过 onMediaUploadingProgress 回调,接收富媒体消息的上传发送进度的相关通知。
void onMediaUploadingProgress(ZIMMediaMessage message, long currentFileSize, long totalFileSize);
1
typedef void (^ZIMMediaUploadingProgress)(ZIMMediaMessage *message, unsigned long long currentFileSize, unsigned long long totalFileSize);
1
using ZIMMediaUploadingProgress = std::function<void(const std::shared_ptr<ZIMMediaMessage> &message, long long currentSize, long long totalSize)>;
1
function onMediaUploadingProgress(message: ZIMMediaMessage, currentFileSize: number, totalFileSize: number);
1
typedef ZIMMediaUploadingProgress = void Function(ZIMMediaMessage message, int currentFileSize, int totalFileSize);
1
其中:
- message:正在发送消息的内容。
- currentFileSize:当前已被发送的消息大小。
- totalFileSize:发送消息的总体大小。
接收富媒体消息
接收方用户登录成功后,根据会话类型(单聊、房间、群组)的相关回调监听( onPeerMessageReceived 、 onRoomMessageReceived 、 onGroupMessageReceived ),接收富媒体消息的相关通知,然后可以直接获取富媒体消息的相关 URL 属性。
如需下载富媒体消息到本地,可调用 downloadMediaFile 接口。
下载富媒体消息时,需要指定对应的媒体消息的文件类型。
- 图片消息:可以选择下载原始文件、大图、缩略图。
- 文件/音频消息:仅能选择下载文件/音频的原始文件。
- 视频消息:可以选择下载视频原始文件、视频首帧的缩略图。
// 接收富媒体消息示例 - 单聊 接收富媒体消息
@Override
public void onPeerMessageReceived(ZIM zim, ArrayList<ZIMMessage> messageList, ZIMMessageReceivedInfo info, String fromUserID) {
super.onPeerMessageReceived(zim, messageList, info, fromUserID);
ZIMMediaDownloadConfig config = new ZIMMediaDownloadConfig();
for (ZIMMessage message : messageList) {
// 收到消息时,可通过消息的 Type 进行判断接收到何种类型的消息
if (message.getType() == ZIMMessageType.IMAGE) {
// 获取图片消息
ZIMImageMessage imageMessage = (ZIMImageMessage) message;
zim.downloadMediaFile(imageMessage, ZIMMediaFileType.ORIGINAL_FILE, config, new ZIMMediaDownloadedCallback() {
@Override
public void onMediaDownloaded(ZIMMessage message, ZIMError errorInfo) {
// 下载完成回调
}
@Override
public void onMediaDownloadingProgress(ZIMMessage message, long currentFileSize, long totalFileSize) {
// 下载进度回调
}
});
} else if (message.getType() == ZIMMessageType.VIDEO) {
// 获取视频消息
ZIMVideoMessage videoMessage = (ZIMVideoMessage) message;
} else if (message.getType() == ZIMMessageType.AUDIO) {
// 获取音频消息
ZIMAudioMessage audioMessage = (ZIMAudioMessage) message;
} else if (message.getType() == ZIMMessageType.FILE) {
// 获取文件消息
ZIMFileMessage fileMessage = (ZIMFileMessage) message;
}
}
}
1
// 接收多媒体消息示例 - 单聊 接收图片消息
- (void)peerMessageReceived:(NSArray<ZIMMessage *> *)messageList
info:(ZIMMessageReceivedInfo *)info
fromUserID:(NSString *)fromUserID{
ZIMMediaDownloadConfig *config = [[ZIMMediaDownloadConfig alloc] init];
for (ZIMMessage *msg in reverseMsgList) {
// 收到消息时,可通过消息的 Type 进行判断接收到何种类型的消息
switch (msg.type) {
case ZIMMessageTypeImage:{
ZIMImageMessage *imageMsg = (ZIMImageMessage *)msg;
[[ZIM getInstance] downloadMediaFileWithMessage:imageMsg fileType:ZIMMediaFileTypeOriginalFile config:config
progress:^(ZIMMessage * _Nonnull message, unsigned long long currentFileSize, unsigned long long totalFileSize) {
} callback:^(ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo) {
}];
break;
}
case ZIMMessageTypeVideo:{
ZIMVideoMessage *videoMsg = (ZIMVideoMessage *)msg;
break;
}
case ZIMMessageTypeAudio:{
ZIMAudioMessage *audioMsg = (ZIMAudioMessage *)msg;
break;
}
case ZIMMessageTypeFile:{
ZIMFileMessage *fileMsg = (ZIMFileMessage *)msg;
break;
}
default:
break;
}
}
}
1
// 接收富媒体消息示例 - 单聊
void onPeerMessageReceived(
zim::ZIM *zim, const std::vector<std::shared_ptr<zim::ZIMMessage>> &messageList,
const ZIMMessageReceivedInfo &info,
const std::string &fromUserID) {
zim::ZIMMediaDownloadConfig download_config;
for (auto &it : messageList) {
// 收到消息时,可通过消息的 Type 进行判断接收到何种类型的消息
if (it->getType() == zim::ZIMMessageType::ZIM_MESSAGE_TYPE_IMAGE) {
// Image message type
auto image_message = std::dynamic_pointer_cast<zim::ZIMImageMessage>(it);
// 下载原图示例如下,如果想下载其他类型,可以换用其他 ZIMMediaFileType
zim_->downloadMediaFile(
image_message.get(),
zim::ZIMMediaFileType::ZIM_MEDIA_FILE_TYPE_ORIGINAL_FILE,
download_config,
[=](const std::shared_ptr<zim::ZIMMessage> &message, unsigned int currentSize,
unsigned int totalSize) {
},
[=](const std::shared_ptr<zim::ZIMMessage> &message,
const zim::ZIMError &errorInfo) {
});
...
} else if (it->getType() == zim::ZIMMessageType::ZIM_MESSAGE_TYPE_FILE) {
// 文件消息
auto media_message = std::dynamic_pointer_cast<zim::ZIMFileMessage>(it);
...
} else if (it->getType() == zim::ZIMMessageType::ZIM_MESSAGE_TYPE_AUDIO) {
// 音频消息
auto media_message = std::dynamic_pointer_cast<zim::ZIMAudioMessage>(it);
...
} else if (it->getType() == zim::ZIMMessageType::ZIM_MESSAGE_TYPE_VIDEO) {
// 视频消息
auto media_message = std::dynamic_pointer_cast<zim::ZIMVideoMessage>(it);
...
}
}
}
1
zim.on('peerMessageReceived', function (zim, { messageList, info, fromConversationID }) {
const config = {messageInfoIndex: 0}
messageList.forEach((msg) => {
if (msg.type == 11) {
zim.downloadMediaFile(msg, 1, config (_msg, currentFileSize, totalFileSize) => {});
}
});
});
1
// 接收多媒体消息示例 - 单聊 接收图片消息
ZIMEventHandler.onPeerMessageReceived = (zim, messageList, info, fromUserID) {
//收到单聊消息触发此处
for (ZIMMessage message in messageList) {
// 收到消息时,可通过消息的 Type 进行判断接收到何种类型的消息
switch (message.type) {
case ZIMMessageType.image:
message as ZIMImageMessage;
break;
case ZIMMessageType.video:
message as ZIMVideoMessage;
break;
case ZIMMessageType.audio:
message as ZIMAudioMessage;
break;
case ZIMMessageType.File:
message as ZIMFileMessage;
break;
default:
}
}
};
1
富媒体文件消息的下载进度回调
开发者可以通过 ZIMMediaDownloadingProgress 回调,接收富媒体消息的下载进度的相关通知。
void onMediaDownloadingProgress(ZIMMessage message, long currentFileSize, long totalFileSize);
1
typedef void (^ZIMMediaDownloadingProgress)(ZIMMessage *message, unsigned long long currentFileSize, unsigned long long totalFileSize);
1
using ZIMMediaDownloadingProgress = std::function<void(const std::shared_ptr<ZIMMessage> &message, unsigned int currentSize, unsigned int totalSize)>;
1
function ZIMMediaDownloadingProgress(message: ZIMMessage, currentFileSize: number, totalFileSize: number);
1
typedef ZIMMediaDownloadingProgress = void Function(ZIMMessage message, int currentFileSize, int totalFileSize);
1
其中:
- message:正在下载的消息内容。
- currentFileSize:当前已被下载的消息大小。
- totalFileSize:下载消息的总体大小。
收发信令消息
ZIM SDK 支持开发者实现信令类型的消息收发,开发者可以通过 ZIMCommandMessage 对象定义自己的消息类型,例如位置消息等。
以下以向指定用户发送信令消息为例。
发送信令消息
//向指定用户发送信令消息
String userID = "xxxx";
ZIMCommandMessage zimCustomMessage = new ZIMCommandMessage();
zimCustomMessage.message = new byte[]{0x1,0x2,0x1,0x2};
ZIMMessageSendConfig config = new ZIMMessageSendConfig();
// 设置消息优先级
config.priority = ZIMMessagePriority.LOW;
// 设置消息的离线推送配置
// 不支持设置房间消息的离线推送配置,如果需要发送房间离线消息,请联系 ZEGO 技术支持开通相关权限
ZIMPushConfig pushConfig = new ZIMPushConfig();
pushConfig.title = "离线推送的标题";
pushConfig.content= "离线推送的内容";
pushConfig.extendedData = "离线推送的扩展信息";
config.pushConfig = pushConfig;
// 发送单聊信息
ZIMConversationType type = ZIMConversationType.Peer;
// 发送群聊信息
// ZIMConversationType type = ZIMConversationType.Gourp;
// 发送房间信息
// ZIMConversationType type = ZIMConversationType.Room;
zim.sendMessage(zimCustomMessage, toConversationID, type, config, new ZIMMessageSentFullCallback() {
@Override
public void onMessageAttached(ZIMMessage zimMessage) {
// 开发者可以通过该回调,监听消息是否开始准备发送。只有当通过本地基础参数检验的消息才会抛出该回调,否则通过 onMessageSent 回调抛出错误。
}
@Override
public void onMessageSent(ZIMMessage zimMessage, ZIMError error) {
// 开发者可以通过该回调监听消息是否发送成功。
}
});
1
//向指定用户发送信令消息
NSData *anyData = [[NSData alloc] init];
NSString *toUserID = @"toUserID";
ZIMCommandMessage * cmdMsg = [[ZIMCommandMessage alloc] initWithMessage:anyData];
ZIMMessageSendConfig *sendConfig = [[ZIMMessageSendConfig alloc] init];
sendConfig.priority = ZIMMessagePriorityMedium;
[self.zim sendMessage:cmdMsg toUserID:toUserID conversationType:type config:config notification:notification callback:^((ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo)) {
// 开发者可以通过该回调监听消息是否发送成功。
}];
1
// 向指定用户发送信令消息
zim::ZIMMessage *message = nullptr;
zim::ZIMCommandMessage commandMessage;
zim::ZIMMessageSendConfig sendConfig;
zim::ZIMPushConfig pushConfig;
pushConfig.content = "win_push_content";
pushConfig.extendedData = "win_push_extended_data";
pushConfig.title = "win_push_title";
sendConfig.priority = zim::ZIM_MESSAGE_PRIORITY_MEDIUM;
sendConfig.pushConfig = &pushConfig;
std::vector<uint8_t> uint8Message;
uint8Message.assign(strMessage.begin(), strMessage.end());
commandMessage.message = uint8Message;
message = &commandMessage;
// 发送单聊信息
zim::ZIMConversationType type = zim::ZIMConversationType::ZIM_CONVERSATION_TYPE_PEER
// 发送群聊信息
// zim::ZIMConversationType type = zim::ZIMConversationType::ZIM_CONVERSATION_TYPE_GROUP
// 发送房间信息
// zim::ZIMConversationType type = zim::ZIMConversationType::ZIM_CONVERSATION_TYPE_ROOM
auto notification = std::make_shared<zim::ZIMMessageSendNotification>(
[=](const std::shared_ptr<zim::ZIMMessage> &message) { int i = 0; });
// 发送消息
zim_->sendMessage(message, "toConversationID", type, config, notification,
[=](const std::shared_ptr<zim::ZIMMessage> &message,
const zim::ZIMError &errorInfo) { int i = 0; });
1
// 发送单聊 `Command` 信息
var toConversationID = ''; // 对方 userID
var conversationType = 0; // 会话类型,取值为 单聊:0,房间:1,群组:2
var config = {
priority: 1, // 设置消息优先级,取值为 低:1(默认),中:2,高:3
};
var notification = {
onMessageAttached: function(message) {
}
}
// 这里以 JSON 字符串 为例,需要将字符串转换为 Uint8Array
// peerMessageReceived 收到 type 为 2 的 Command 消息时,需要将 Uint8Array 转换为 JSON 字符串
var jsonText = JSON.stringify({ id: '111', name: '张三' });
var uint8Array = new Uint8Array(Array.from(unescape(encodeURIComponent(jsonText))).map((val) => val.charCodeAt(0)));
var messageCommandObj = { type: 2, message: uint8Array };
zim.sendMessage(messageCommandObj, toConversationID, conversationType, config, notification)
.then(function ({ message }) {
// 发送成功
})
.catch(function (err) {
// 发送失败
});
1
// 向指定用户发送信令消息
Uint8List cmdMessage = Uint8List.fromList([1, 2, 3]);
ZIMCommandMessage commandMessage = ZIMCommandMessage(message: cmdMessage);
ZIMMessageSendConfig sendConfig = ZIMMessageSendConfig();
ZIM.getInstance()!.sendMessage(cmdMsg, 'toUserID', ZIMConversationType.peer, sendConfig)
.then((value) => {
//成功触发此处
})
.catchError((onError) {
//失败触发此处
});
1
接收信令消息
//用户接收信令消息
zim.setEventHandler(new ZIMEventHandler() {
@Override
public void onPeerMessageReceived(ZIM zim, ArrayList<ZIMMessage> messageList, ZIMMessageReceivedInfo info, String fromUserID) {
// 收到“单聊”通信的消息回调
for (ZIMMessage zimMessage : messageList) {
if (zimMessage instanceof ZIMCommandMessage) {
ZIMCommandMessage zimCommandMessage = (ZIMCommandMessage) zimMessage;
}
}
}
});
1
//用户接收信令消息
- (void)zim:(ZIM *)zim peerMessageReceived:(NSArray<ZIMMessage *> *)messageList info:(ZIMMessageReceivedInfo *)info fromUserID:(NSString *)fromUserID {
if (zim != self.zim) {
return;
}
for (ZIMMessage *msg in messageList) {
if(msg.type == ZIMMessageTypeCommand){
ZIMCommandMessage *cmdMsg = (ZIMCommandMessage *)msg;
NSData *receivedData = cmdMsg.message;
}
}
}
1
//用户接收信令消息
void onPeerMessageReceived(zim::ZIM *zim, const std::vector<std::shared_ptr<zim::ZIMMessage>> &messageList,
const ZIMMessageReceivedInfo &info, const std::string &fromUserID) {
for (auto &it : message_list) {
if (it->getType() == zim::ZIM_MESSAGE_TYPE_COMMAND) {
auto commandMessage = std::dynamic_pointer_cast<zim::ZIMCommandMessage>(it);
}
}
}
1
// 用户接收信令消息
zim.on('peerMessageReceived', function (zim, { messageList, info, fromConversationID }) {
console.log(messageList, info, fromConversationID);
messageList.forEach(function (msg) {
// 收到 `Command` 消息时,这里以 JSON 字符串 为例,将 Uint8Array 消息内容转为 JSON 字符串
if (msg.type == 2) {
var uint8Array = msg.message;
var jsonText = decodeURIComponent(escape(String.fromCharCode(...Array.from(uint8Array))));
var jsonObj = JSON.parse(jsonText);
console.log('peerMessageReceived', jsonObj);
}
})
});
1
// 用户接收信令消息
ZIMEventHandler.onPeerMessageReceived = (zim, messageList, info, fromUserID) {
//收到单聊消息触发此处
for (ZIMMessage message in messageList) {
switch (message.type) {
case ZIMMessageType.command:
message as ZIMCommandMessage;
break;
default:
}
}
};
1
收发自定义消息
ZIM SDK 支持开发者实现自定义类型的消息收发,开发者可以通过 ZIMCustomMessage 对象自行定义消息类型,例如投票类型、接龙类型、视频卡片类型等。开发者可以通过以下步骤实现自定义消息的收发。
- 仅 2.8.0 及以上版本的 ZIM SDK 支持发送自定义类型消息,接收并查看自定义类型消息的内容。
- 如果接收端的 SDK 版本介乎 [2.0.0, 2.8.0) 区间,可以收到自定义消息时,但会显示此消息类型为未知,且无法获取信息内容。如需获取此条消息,请将 SDK 升级为 2.8.0 或以上版本。
- 如果接收端的 SDK 版本为 1.x.x 版本,则无法收到自定义消息,也不会收到未知消息。
发送自定义消息
发送自定义消息使用的接口为 sendMessage ,与发送普通消息所用接口相同,开发者可参考 收发普通消息 - 发送消息 了解此接口参数详情。
开发者需要通过 ZIMCustomMessage 对象定义自定义类型消息,包括以下参数:
以下为用户在单聊会话中发送自定义消息的示例代码:
// 在单聊会话中向指定用户发送自定义消息
String userID = "xxxx";
// 自定义消息的文本内容
String message = "";
// 具体的自定义类型
int subType = 100;
// 自定义消息的检索字段。
String searchedContent = "";
ZIMCustomMessage zimCustomMessage = new ZIMCustomMessage(message,subType);
// 发送消息的高级属性配置
ZIMMessageSendConfig config = new ZIMMessageSendConfig();
// 设置消息优先级
config.priority = ZIMMessagePriority.LOW;
ZIMConversationType type = ZIMConversationType.Peer;
zim.sendMessage(zimCustomMessage, userID, type, config, new ZIMMessageSentFullCallback() {
@Override
public void onMessageAttached(ZIMMessage zimMessage) {
// 开发者可以通过该回调,监听消息是否开始准备发送。只有当通过本地基础参数检验的消息才会抛出该回调,否则通过 onMessageSent 回调抛出错误。
}
@Override
public void onMessageSent(ZIMMessage zimMessage, ZIMError error) {
// 开发者可以通过该回调监听消息是否发送成功。
}
});
1
// 向指定用户发送自定义消息
NSString *message = @"message";
NSString *toUserID = @"toUserID";
ZIMCustomMessage * customMessage = [[ZIMCustomMessage alloc] init];
customMessage.message = message;
customMessage.subType = 1; // 开发者自定义的类型
customMessage.searchContent="";
ZIMMessageSendConfig *sendConfig = [[ZIMMessageSendConfig alloc] init];
sendConfig.priority = ZIMMessagePriorityMedium;
[self.zim sendMessage:customMessage toUserID:toUserID conversationType: ZIMConversationTypePeer config:config notification:notification callback:^((ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo)) {
// 开发者可以通过该回调监听消息是否发送成功。
}];
1
// 向指定用户发送自定义消息
zim::ZIMMessage *message = nullptr;
zim::ZIMCustomMessage customMessage;
zim::ZIMMessageSendConfig sendConfig;
zim::ZIMPushConfig pushConfig;
pushConfig.content = "win_push_content";
pushConfig.extendedData = "win_push_extended_data";
pushConfig.title = "win_push_title";
sendConfig.priority = zim::ZIM_MESSAGE_PRIORITY_MEDIUM;
sendConfig.pushConfig = &pushConfig;
std::string message = "message";
unsigned int subType = 1;
std::string searchedContent = "searchedContent";
customMessage.message = message;
customMessage.subType = subType;
customMessage.searchedContent = searchedContent;
message = &customMessage;
zim::ZIMConversationType type = zim::ZIMConversationType::ZIM_CONVERSATION_TYPE_PEER
auto notification = std::make_shared<zim::ZIMMessageSendNotification>(
[=](const std::shared_ptr<zim::ZIMMessage> &message) { int i = 0; });
zim_->sendMessage(message, "toConversationID", type, config, notification,
[=](const std::shared_ptr<zim::ZIMMessage> &message,
const zim::ZIMError &errorInfo) { int i = 0; });
1
// 发送自定义信息
// 指定用户的 ID
var toConversationID = "xxxx";
var conversationType = 0; // 会话类型,取值为 单聊:0,房间:1,群组:2
// 发送消息的高级属性配置
var config = {
priority: 1, // 设置消息优先级,取值为 低:1(默认),中:2,高:3
};
var notification = {
onMessageAttached: function(message) {
}
}
var zimCustomMessage = {
type: 200,
message: 'xxxx', // 自定义消息的文本内容
subType: 100, // 具体的自定义类型
searchedContent: 'xxxx' // 自定义消息的检索字段
};
zim.sendMessage(zimCustomMessage, toConversationID, conversationType, config, notification)
.then(function ({ message }) {
// 发送成功
})
.catch(function (err) {
// 发送失败
});
1
// 在单聊会话中向指定用户发送自定义消息
// 指定用户的 ID
String userID = "xxxx";
// 自定义消息的文本内容
String message = "";
// 具体的自定义类型
int subType = 100;
// 自定义消息的检索字段。
String searchedContent = "";
ZIMCustomMessage zimCustomMessage = ZIMCustomMessage(message, subType);
// 发送消息的高级属性配置
ZIMMessageSendConfig config = ZIMMessageSendConfig();
// 设置消息优先级
config.priority = ZIMMessagePriority.low;
ZIMConversationType type = ZIMConversationType.Peer;
ZIM.getInstance().sendMessage(zimCustomMessage, userID, type, config, ZIMMessageSendNotification(onMessageAttached: (ZIMMessage message){
// 开发者可以通过该回调,监听消息是否开始准备发送。只有当通过本地基础参数检验的消息才会抛出该回调,否则通过 onMessageSent 回调抛出错误。
})).then((value) {
// 发送成功回调
}).catchError((onError){
// 处理失败
});
1
接收自定义消息
接收自定义消息的回调接口与接收普通消息的回调接口一致,请参考 收发普通消息 - 接收消息 了解具体接口。
以下为用户在单聊会话中接收自定义消息的示例代码:
// 用户在单聊会话中接收自定义消息
zim.setEventHandler(new ZIMEventHandler() {
@Override
public void onPeerMessageReceived(ZIM zim, ArrayList<ZIMMessage> messageList, ZIMMessageReceivedInfo info, String fromUserID) {
// 收到“单聊”消息的回调
for (ZIMMessage zimMessage : messageList) {
if (zimMessage instanceof ZIMCustomMessage) {
ZIMCustomMessage zimCustomMessage = (ZIMCustomMessage) zimMessage;
}
}
}
});
1
// 用户在单聊会话中接收自定义消息
- (void)zim:(ZIM *)zim peerMessageReceived:(NSArray<ZIMMessage *> *)messageList info:(ZIMMessageReceivedInfo *)info fromUserID:(NSString *)fromUserID {
if (zim != self.zim) {
return;
}
for (ZIMMessage *msg in messageList) {
if(msg.type == ZIMMessageTypeCustom){
// 这里表示接收到自定义消息
}
}
}
1
//用户接收自定义消息
void onPeerMessageReceived(zim::ZIM *zim, const std::vector<std::shared_ptr<zim::ZIMMessage>> &messageList,
const ZIMMessageReceivedInfo &info, const std::string &fromUserID) {
for (auto &it : message_list) {
if (it->getType() == zim::ZIM_MESSAGE_TYPE_CUSTOM) {
auto customMessage = std::dynamic_pointer_cast<zim::ZIMCustomMessage>(it);
}
}
}
1
// 用户在单聊会话中接收自定义消息
zim.on('peerMessageReceived', function (zim, { messageList, info, fromConversationID }) {
console.log(messageList, info, fromConversationID);
messageList.forEach(function (msg) {
// 收到 `Custom` 消息时
if (msg.type == 200) {
}
})
});
1
// 用户在单聊会话中接收自定义消息
ZIMEventHandler.onPeerMessageReceived = (zim, messageList, info, fromUserID) {
for (ZIMMessage message in messageList) {
if(message is ZIMCustomMessage){
}
}
};
1
收发组合消息
ZIM SDK 支持开发者实现组合类型的消息收发,开发者可以通过 ZIMMultipleMessage 对象组合多种消息类型,例如图文类型等。
- 仅 2.19.0 及以上版本的 ZIM SDK 支持发送组合类型消息,接收并查看组合类型消息的内容。
- 如果接收端的 SDK 版本介乎 [2.0.0, 2.19.0) 区间,可以收到组合消息时,但会显示此消息类型为未知,且无法获取信息内容。如需获取此条消息,请将 SDK 升级为 2.19.0 或以上版本。
- 如果接收端的 SDK 版本为 1.x.x 版本,则无法收到组合消息,也不会收到未知消息。
发送组合消息
用户登录成功后,通过 ZIMMultipleMessage 对象组合多种消息类型(文本、图片、音频、视频、文件和自定义文本等),调用 sendMessage 接口向单聊、房间或群聊会话发送该消息。
您可以通过 onMultipleMediaUploadingProgress 回调,接收组合消息中富媒体文件的上传进度的相关通知。在此回调中,您可以了解到以下字段:
- currentFileSize:已上传文件总大小,单位为 Byte。
- totalFileSize:组合消息中多媒体文件的总大小,,单位为 Byte。
- messageInfoIndex:接收到此回调时,当前正在上传的文件在 ZIMMultipleMessage 数组的索引。
- currentIndexFileSize: 接收到此回调时,当前正在上传的文件的已上传大小,单位为 Byte。
- totalIndexFileSize:接收到此回调时,当前正在上传的文件的实际大小,单位为 Byte。
上述字段可用于计算多媒体文件的总上传进度、以及当前文档的上传进度:
- 总上传进度 = currentFileSize / totalFileSize。
- 当前文件上传进度 = currentIndexFileSize / totalIndexFileSize。
以下为用户在单聊会话中发送组合消息的示例代码:
// 在单聊会话中向指定用户发送组合消息
String userID = "xxxx";
// 组合消息 Item 列表,最多只可以包含 20 个 Item
ArrayList<ZIMMessageLiteInfo> messageInfoList = new ArrayList();
// 文本
ZIMTextMessageLiteInfo textMsgInfo= new ZIMTextMessageLiteInfo();
textMsgInfo.message = "消息内容";
messageInfoList.add(textMsgInfo);
// 自定义消息:最多支持 1 个
ZIMCustomMessageLiteInfo customMsgInfo= new ZIMCustomMessageLiteInfo();
customMsgInfo.message = "消息内容";
customMsgInfo.searchedContent = "搜索内容";
customMsgInfo.subType = 100;
messageInfoList.add(customMsgInfo);
// 图片:最多支持 10 个
// 网络图片示例
ZIMImageMessageLiteInfo imageMsgInfo= new ZIMImageMessageLiteInfo();
imageMsgInfo.fileDownloadUrl = "https://xxxx.jpeg"; // 原图
imageMsgInfo.thumbnailDownloadUrl = "https://xxxx-thumbnail.jpeg"; // 缩略图
imageMsgInfo.largeImageDownloadUrl = "https://xxxx-large.jpeg"; // 大图
messageInfoList.add(imageMsgInfo);
// 本地图片示例
ZIMImageMessageLiteInfo localImageMsgInfo= new ZIMImageMessageLiteInfo();
localImageMsgInfo.fileLocalPath = "/storage/emulated/0/Android/data/packagename/xxx.jpg"; // 图片的绝对路径
messageInfoList.add(localImageMsgInfo);
// 文件:最多支持 1 个
ZIMFileMessageLiteInfo localFileMsgInfo= new ZIMFileMessageLiteInfo();
localFileMsgInfo.fileLocalPath = "/storage/emulated/0/Android/data/packagename/xxx.zip"; // 文件的绝对路径
messageInfoList.add(localFileMsgInfo);
// 音频:最多支持 1 个
ZIMAudioMessageLiteInfo localAudioMsgInfo= new ZIMAudioMessageLiteInfo();
localAudioMsgInfo.fileLocalPath = "/storage/emulated/0/Android/data/packagename/xxx.mp3"; // 音频的绝对路径
localAudioMsgInfo.audioDuration = 100; // 必填,音频时长,单位秒
messageInfoList.add(localAudioMsgInfo);
// 视频:最多支持 1 个
ZIMVideoMessageLiteInfo localVideoMsgInfo= new ZIMVideoMessageLiteInfo();
localVideoMsgInfo.fileLocalPath = "/storage/emulated/0/Android/data/packagename/xxx.mp4"; // 视频的绝对路径
localVideoMsgInfo.videoDuration = 100; // 必填,视频时长,单位秒
messageInfoList.add(localVideoMsgInfo);
ZIMMultipleMessage zimMultipleMessage = new ZIMMultipleMessage();
zimMultipleMessage.setMessageInfoList(messageInfoList);
// 发送消息的高级属性配置
ZIMMessageSendConfig config = new ZIMMessageSendConfig();
// 设置消息优先级
config.priority = ZIMMessagePriority.LOW;
ZIMConversationType type = ZIMConversationType.Peer;
zim.sendMessage(zimMultipleMessage, userID, type, config, new ZIMMessageSentFullCallback() {
@Override
public void onMessageAttached(ZIMMessage zimMessage) {
// 开发者可以通过该回调,监听消息是否开始准备发送。只有当通过本地基础参数检验的消息才会抛出该回调,否则通过 onMessageSent 回调抛出错误。
}
@Override
public void onMessageSent(ZIMMessage zimMessage, ZIMError error) {
// 开发者可以通过该回调监听消息是否发送成功。
}
@Override
public void onMultipleMediaUploadingProgress(
ZIMMultipleMessage message,
long currentFileSize, // 已上传文件总大小,单位为 Byte。比如已上传了 20,971,520 Byte,则此处为 20,971,520。
long totalFileSize, // 总文件大小,单位为 Byte。比如总文件大小 104,857,600 Byte,则此处为 104,857,600
int messageInfoIndex, // 接收到此回调时,当前正在上传的文件在 messageInfoList 数组的索引
long currentIndexFileSize, // 接收到此回调时,当前正在上传的文件的已上传大小,单位为 Byte。
long totalIndexFileSize, // 接收到此回调时,当前正在上传的文件的实际大小,单位为 Byte。
) {
// 您可以在这里展示上传进度
// 开发者可以监听这个回调获取多媒体上传的进度
// 总文件上传进度: currentFileSize / totalFileSize
// 上述例子中,总文件上传进度为:20,971,520 / 104,857,600 = 20%
// 接收此回调时,当前正在上传的文件的上传进度:currentIndexFileSize / totalIndexFileSize
}
});
1
// 在单聊会话中向指定用户发送组合消息
NSString *toUserID = @"toUserID";
// 组合消息 Item 列表,最多只可以包含 20 个 Item
NSMutableArray<ZIMMessageLiteInfo *> *messageInfoList = [NSMutableArray array];
// 文本
ZIMTextMessageLiteInfo *textMsgInfo = [[ZIMTextMessageLiteInfo alloc] init];
textMsgInfo.message = @"消息内容";
[messageInfoList addObject:textMsgInfo];
// 自定义消息:最多支持 1 个
ZIMCustomMessageLiteInfo *customMsgInfo = [[ZIMCustomMessageLiteInfo alloc] init];
customMsgInfo.message = @"消息内容";
customMsgInfo.searchedContent = @"搜索内容";
customMsgInfo.subType = 100;
[messageInfoList addObject:customMsgInfo];
// 图片:最多支持 10 个
// 网络图片示例
ZIMImageMessageLiteInfo *imageMsgInfo = [[ZIMImageMessageLiteInfo alloc] init];
imageMsgInfo.fileDownloadUrl = @"https://xxxx.jpeg"; // 原图
imageMsgInfo.thumbnailDownloadUrl = @"https://xxxx-thumbnail.jpeg"; // 缩略图
imageMsgInfo.largeImageDownloadUrl = @"https://xxxx-large.jpeg"; // 大图
[messageInfoList addObject:imageMsgInfo];
// 本地图片示例
ZIMImageMessageLiteInfo *localImageMsgInfo = [[ZIMImageMessageLiteInfo alloc] init];
localImageMsgInfo.fileLocalPath = @"/private/var/mobile/Containers/Data/Application/xxx.jpg"; // 图片的绝对路径
[messageInfoList addObject:localImageMsgInfo];
// 文件:最多支持 1 个
ZIMFileMessageLiteInfo *localFileMsgInfo = [[ZIMFileMessageLiteInfo alloc] init];
localFileMsgInfo.fileLocalPath = @"/private/var/mobile/Containers/Data/Application/xxx.zip"; // 文件的绝对路径
[messageInfoList addObject:localFileMsgInfo];
// 音频:最多支持 1 个
ZIMAudioMessageLiteInfo *localAudioMsgInfo = [[ZIMAudioMessageLiteInfo alloc] init];
localAudioMsgInfo.fileLocalPath = @"/private/var/mobile/Containers/Data/Application/xxx.mp3"; // 音频的绝对路径
localAudioMsgInfo.audioDuration = 100; // 必填,音频时长,单位秒
[messageInfoList addObject:localAudioMsgInfo];
// 视频:最多支持 1 个
ZIMVideoMessageLiteInfo *localVideoMsgInfo = [[ZIMVideoMessageLiteInfo alloc] init];
localVideoMsgInfo.fileLocalPath = @"/private/var/mobile/Containers/Data/Application/xxx.mp4"; // 视频的绝对路径
localVideoMsgInfo.videoDuration = 100; // 必填,视频时长,单位秒
[messageInfoList addObject:localVideoMsgInfo];
ZIMMultipleMessage * multipleMessage = [[ZIMMultipleMessage alloc] init];
multipleMessage.messageInfoList = messageInfoList;
ZIMMessageSendNotification *notification = [[ZIMMessageSendNotification alloc] init];
notification.onMessageAttached = ^(ZIMMessage * _Nonnull message) {
// 开发者可以监听这个回调执行消息发送前的业务逻辑
};
notification.onMultipleMediaUploadingProgress = ^(
ZIMMultipleMessage * _Nonnull message,
unsigned long long currentFileSize, // 已上传文件总大小,单位为 Byte。比如已上传了 20,971,520 Byte,则此处为 20,971,520。
unsigned long long totalFileSize, // 总文件大小,单位为 Byte。比如总文件大小 104,857,600B,则此处为 104,857,600
unsigned int messageInfoIndex, // 接收到此回调时,当前正在上传的文件在 messageInfoList 数组的索引
unsigned long long currentIndexFileSize, // 接收到此回调时,当前正在上传的文件的已上传大小,单位为 Byte。
unsigned long long totalIndexFileSize // 接收到此回调时,当前正在上传的文件的实际大小,单位为 Byte。
) {
// 开发者可以监听这个回调获取多媒体上传的进度
// 总文件上传进度: currentFileSize / totalFileSize
// 上述例子中,总文件上传进度为:20,971,520 / 104,857,600 = 20%
// 接收此回调时,当前正在上传的文件的上传进度:currentIndexFileSize / totalIndexFileSize
};
ZIMMessageSendConfig *sendConfig = [[ZIMMessageSendConfig alloc] init];
sendConfig.priority = ZIMMessagePriorityMedium;
[self.zim sendMessage:multipleMessage toUserID:toUserID conversationType: ZIMConversationTypePeer config:config notification:notification callback:^((ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo)) {
// 开发者可以通过该回调监听消息是否发送成功。
}];
1
// 在单聊会话中向指定用户发送组合消息
auto multiMsg = std::make_shared<ZIMMultipleMessage>();
// 文本
auto textMsgInfo = std::make_shared<ZIMTextMessageLiteInfo>();
textMsgInfo->message = "消息内容";
multiMsg->messageInfoList.push_back(textMsgInfo);
// 自定义消息:最多支持 1 个
auto customMsgInfo = std::make_shared<ZIMCustomMessageLiteInfo>();
customMsgInfo->message = "消息内容";
customMsgInfo->searchedContent = "搜索内容";
customMsgInfo->subType = 100;
multiMsg->messageInfoList.push_back(customMsgInfo);
// 图片:最多支持 10 个
// 网络图片示例
auto imageMsgInfo = std::make_shared<ZIMImageMessageLiteInfo>();
imageMsgInfo->fileDownloadUrl = "https://xxxx.jpeg"; // 原图
imageMsgInfo->thumbnailDownloadUrl = "https://xxxx-thumbnail.jpeg"; // 缩略图
imageMsgInfo->largeImageDownloadUrl = "https://xxxx-large.jpeg"; // 大图
multiMsg->messageInfoList.push_back(imageMsgInfo);
// 本地图片示例
auto localImageMsgInfo = std::make_shared<ZIMImageMessageLiteInfo>();
localImageMsgInfo->fileLocalPath = "D:\\files\\xxx.jpg"; // 图片的绝对路径
multiMsg->messageInfoList.push_back(localImageMsgInfo);
// 文件:最多支持 1 个
auto localFileMsgInfo = std::make_shared<ZIMFileMessageLiteInfo>();
localFileMsgInfo->fileLocalPath = "D:\\files\\xxx.zip"; // 文件的绝对路径
multiMsg->messageInfoList.push_back(localFileMsgInfo);
// 音频:最多支持 1 个
auto localAudioMsgInfo = std::make_shared<ZIMAudioMessageLiteInfo>();
localAudioMsgInfo->fileLocalPath = "D:\\files\\xxx.mp3"; // 音频的绝对路径
localAudioMsgInfo->audioDuration = 100; // 必填,音频时长,单位秒
multiMsg->messageInfoList.push_back(localAudioMsgInfo);
// 视频:最多支持 1 个
auto localVideoMsgInfo = std::make_shared<ZIMVideoMessageLiteInfo>();
localVideoMsgInfo->fileLocalPath = "D:\\files\\xxx.mp4"; // 文件绝对路径
localVideoMsgInfo->videoDuration = 100; // 必填,视频时长,单位秒
multiMsg->messageInfoList.push_back(localVideoMsgInfo);
zim::ZIMMessageSendConfig sendConfig;
zim::ZIMPushConfig pushConfig;
pushConfig.content = "win_push_content";
pushConfig.payload = "win_push_payload";
pushConfig.title = "win_push_title";
sendConfig.priority = zim::ZIM_MESSAGE_PRIORITY_MEDIUM;
sendConfig.pushConfig = &pushConfig;
auto type = zim::ZIMConversationType::ZIM_CONVERSATION_TYPE_PEER;
auto notification = std::make_shared<zim::ZIMMessageSendNotification>(
[=](const std::shared_ptr<zim::ZIMMessage> &message) {
// 开发者可监听此回调,执行消息发送前的逻辑
},
[=](const std::shared_ptr<ZIMMediaMessage> &message,
unsigned long long currentFileSize, unsigned long long totalFileSize) {
// 发送组合消息时,该通知不会触发
},
[=](const std::shared_ptr<zim::ZIMMultipleMessage> &message,
unsigned long long currentFileSize, // 已上传文件总大小,单位为 Byte。比如已上传了 20,971,520 Byte,则此处为 20,971,520。
unsigned long long totalFileSize, // 总文件大小,单位为 Byte。比如总文件大小 104,857,600 Byte,则此处为 104,857,600
unsigned int messageInfoIndex, // 接收到此回调时,当前正在上传的文件在 messageInfoList 数组的索引
unsigned long long currentIndexFileSize, // 接收到此回调时,当前正在上传的文件的已上传大小,单位为 Byte。
unsigned long long totalIndexFileSize // 触发该回调对应的文件的大小
) {
// 发送组合消息的上传回调,如果组合消息中没有媒体类型,则该回调不会触发
});
zim_->sendMessage(multiMsg, "toConversationID", type, sendConfig, notification,
[=](const std::shared_ptr<zim::ZIMMessage> &message,
const zim::ZIMError &errorInfo) {
// 发送结果的回调
});
1
// 选择本地文件的方法
var file = null; // 上传的文件对象
var input = document.createElement('input');
input.type = 'file';
input.onchange = function() {
file = this.files[0];
}
1
// 选择本地文件的方法
var file = ''; // 上传的文件的临时路径
// 拍摄或从手机相册中选择图片或视频
// 请参考小程序官方文档:https://developers.weixin.qq.com/miniprogram/dev/api/media/video/wx.chooseMedia.html
wx.chooseMedia({
count: 1,
success(res) {
file = res.tempFiles[0].tempFilePath);
}
})
// 从微信客户端会话选择文件
// 请参考小程序官方文档:https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.chooseMessageFile.html
wx.chooseMessageFile({
count: 1,
success(res) {
file = res.tempFiles[0].path);
}
})
1
// 选择本地文件的方法
var file = ''; // 上传的文件的绝对路径
1
// 在单聊会话中向指定用户发送组合消息
// 指定用户的 ID
var toConversationID = "xxxx";
// 发送消息的高级属性配置
var conversationType = 0; // 会话类型,取值为 单聊:0,房间:1,群组:2
var config = {
priority: 1, // 设置消息优先级,取值为 低:1(默认),中:2,高:3
};
var notification = {
onMessageAttached: function(message) {
},
onMultipleMediaUploadingProgress: function(
message,
currentFileSize, // 已上传文件总大小,单位为 Byte。比如已上传了 20,971,520 Byte,则此处为 20,971,520。
totalFileSize, // 总文件大小,单位为 Byte。比如总文件大小 104,857,600 Byte,则此处为 104,857,600
messageInfoIndex, // 接收到此回调时,当前正在上传的文件在 messageInfoList 数组的索引
currentIndexFileSize, // 接收到此回调时,当前正在上传的文件的已上传大小,单位为 Byte。
totalIndexFileSize // 接收到此回调时,当前正在上传的文件的实际大小,单位为 Byte。
) {
// 开发者可以监听这个回调获取多媒体上传的进度
// 总文件上传进度: currentFileSize / totalFileSize
// 上述例子中,总文件上传进度为:20,971,520 / 104,857,600 = 20%
// 接收此回调时,当前正在上传的文件的上传进度:currentIndexFileSize / totalIndexFileSize
}
};
var zimMultipleMessage = {
type: 10,
// 组合消息 Item 列表,最多只可以包含 20 个 Item
messageInfoList: [
// 文本
{
type: 1,
message: 'xxxx',
},
// 自定义消息:最多支持 1 个
{
type: 200,
message: 'xxxx',
subType: 100,
searchedContent: 'xxxx'
},
// 图片:最多支持 10 个
// 网络图片示例
{
type: 11,
fileDownloadUrl: 'https://xxxx.jpeg', // 原图
thumbnailDownloadUrl: 'https://xxxx-thumbnail.jpeg', // 缩略图
largeImageDownloadUrl: 'https://xxxx-large.jpeg', // 大图
},
// 本地图片示例
{
type: 11,
fileLocalPath: file, // 上传的文件
},
// 文件:最多支持 1 个
{
type: 12,
fileLocalPath: file, // 上传的文件
},
// 音频:最多支持 1 个
{
type: 13,
fileLocalPath: file, // 上传的文件
audioDuration: 100, // 请填写音频时长,单位秒(必填)
},
// 视频:最多支持 1 个
{
type: 14,
fileLocalPath: file, // 上传的文件
videoDuration: 100, // 请填写视频时长,单位秒(必填)
}
]
};
zim.sendMessage(zimMultipleMessage, toConversationID, conversationType, config, notification)
.then(function ({ message }) {
// 发送成功
})
.catch(function (err) {
// 发送失败
});
1
// 在单聊会话中向指定用户发送组合消息
// 指定用户的 ID
String userID = "xxxx";
// 组合消息 Item 列表,最多只可以包含 20 个 Item
List<ZIMMessageLiteInfo> messageInfoList = [];
// 文本消息
ZIMTextMessageLiteInfo textMsgInfo = ZIMTextMessageLiteInfo();
textMsgInfo.message = "消息内容";
messageInfoList.add(textMsgInfo);
// 自定义消息:最多支持 1 个
ZIMCustomMessageLiteInfo customMsgInfo = ZIMCustomMessageLiteInfo();
customMsgInfo.message = "消息内容";
customMsgInfo.searchedContent = "搜索内容";
customMsgInfo.subType = 100;
messageInfoList.add(customMsgInfo);
// 图片:最多支持 10 个
// 网络图片
ZIMImageMessageLiteInfo imageMsgInfo = ZIMImageMessageLiteInfo();
imageMsgInfo.fileDownloadUrl = "https://xxxx.jpeg"; // 原图
imageMsgInfo.thumbnailDownloadUrl = "https://xxxx-thumbnail.jpeg"; // 缩略图
imageMsgInfo.largeImageDownloadUrl = "https://xxxx-large.jpeg"; // 大图
messageInfoList.add(imageMsgInfo);
// 本地图片
ZIMImageMessageLiteInfo localImageMsgInfo = ZIMImageMessageLiteInfo();
localImageMsgInfo.fileLocalPath = "/path/xxx.jpg"; // 图片绝对路径
messageInfoList.add(localImageMsgInfo);
// 文件:最多支持 1 个
ZIMImageMessageLiteInfo localFileMsgInfo = ZIMFileMessageLiteInfo();
localFileMsgInfo.fileLocalPath = "/path/xxx.zip"; // 文件绝对路径
messageInfoList.add(localFileMsgInfo);
// 音频:最多支持 1 个
ZIMAudioMessageLiteInfo localAudioMsgInfo = ZIMAudioMessageLiteInfo();
localAudioMsgInfo.fileLocalPath = "/path/xxx.mp3"; // 音频绝对路径
localAudioMsgInfo.audioDuration = 100; // 必填,播放时长,单位秒
messageInfoList.add(localAudioMsgInfo);
// 视频:最多支持 1 个
ZIMVideoMessageLiteInfo localVideoMsgInfo = ZIMVideoMessageLiteInfo();
localVideoMsgInfo.fileLocalPath = "/path/xxx.mp4"; // 视频绝对路径
localVideoMsgInfo.videoDuration = 100; // 必填,播放时长,单位秒
messageInfoList.add(localVideoMsgInfo);
ZIMMultipleMessage zimMultipleMessage = ZIMMultipleMessage(messageInfos);
zimMultipleMessage.messageInfoList = messageInfoList;
ZIMMessageSendNotification notification = ZIMMessageSendNotification(
onMessageAttached: (message){
// 开发者可以监听这个回调执行消息发送前的业务逻辑
},
onMultipleMediaUploadingProgress: (
message,
currentFileSize, // 已上传文件总大小,单位为 Byte。比如已上传了 20,971,520 Byte,则此处为 20,971,520。
totalFileSize, // 总文件大小,单位为 Byte。比如总文件大小 104,857,600 Byte,则此处为 104,857,600
messageInfoIndex, // 接收到此回调时,当前正在上传的文件在 messageInfoList 数组的索引
currentIndexFileSize, // 接收到此回调时,当前正在上传的文件的已上传大小,单位为 Byte。
totalIndexFileSize // 接收到此回调时,当前正在上传的文件的实际大小,单位为 Byte。
){
// 开发者可以监听这个回调获取多媒体上传的进度
// 总文件上传进度: currentFileSize / totalFileSize
// 上述例子中,总文件上传进度为:20,971,520 / 104,857,600 = 20%
// 接收此回调时,当前正在上传的文件的上传进度:currentIndexFileSize / totalIndexFileSize
}
);
// 发送消息的高级属性配置
ZIMMessageSendConfig config = ZIMMessageSendConfig();
// 设置消息优先级
config.priority = ZIMMessagePriority.low;
ZIMConversationType type = ZIMConversationType.Peer;
ZIM.getInstance().sendMessage(zimMultipleMessage, userID, type, config, notification).then((value) {
// 发送成功回调
}).catchError((onError){
// 处理失败
});
1
接收组合消息
接收组合消息的回调接口与接收普通消息的回调接口一致,请参考 收发普通消息 - 接收消息 了解具体接口。
以下为用户在单聊会话中接收组合消息的示例代码:
// 用户在单聊会话中接收组合消息
zim.setEventHandler(new ZIMEventHandler() {
@Override
public void onPeerMessageReceived(ZIM zim, ArrayList<ZIMMessage> messageList, ZIMMessageReceivedInfo info, String fromUserID) {
// 收到“单聊”消息的回调
for (ZIMMessage zimMessage : messageList) {
if (zimMessage instanceof ZIMMultipleMessage) {
ZIMMultipleMessage zimMultipleMessage = (ZIMMultipleMessage) zimMessage;
}
}
}
});
1
// 用户在单聊会话中接收组合消息
- (void)zim:(ZIM *)zim peerMessageReceived:(NSArray<ZIMMessage *> *)messageList info:(ZIMMessageReceivedInfo *)info fromUserID:(NSString *)fromUserID {
if (zim != self.zim) {
return;
}
for (ZIMMessage *msg in messageList) {
if(msg.type == ZIMMessageTypeMultiple){
// 这里表示接收到组合消息
}
}
}
1
// 用户接收组合消息
void onPeerMessageReceived(zim::ZIM *zim, const std::vector<std::shared_ptr<zim::ZIMMessage>> &messageList,
const ZIMMessageReceivedInfo &info, const std::string &fromUserID) {
for (auto &it : message_list) {
if (it->getType() == zim::ZIM_MESSAGE_TYPE_MULTIPLE ) {
auto multipleMessage = std::dynamic_pointer_cast<zim::ZIMMultipleMessage>(it);
}
}
}
1
// 用户在单聊会话中接收组合消息
zim.on('peerMessageReceived', function (zim, { messageList, info, fromConversationID }) {
console.log(messageList, fromConversationID);
messageList.forEach(function (msg) {
// 收到 `Multiple` 消息时
if (msg.type == 10) {
msg.messageInfoList.forEach(function (info) {
// 根据消息类型展示 UI
console.log('组合消息 item 类型:' + info.type);
}
}
})
});
1
// 用户在单聊会话中接收组合消息
ZIMEventHandler.onPeerMessageReceived = (zim, messageList, info, fromUserID) {
for (ZIMMessage message in messageList) {
if(message is ZIMMultipleMessage){
}
}
};
1
收发 @ 消息
@ 消息,是指包含“@ + 用户”内容的消息。被 @ 的用户在收到消息时会强提醒。
@ 消息不属于消息类型。一条消息既可以是文本消息或其他类型消息,同时也是 @ 消息。
发送 @ 消息
在调用 sendMessage 发送消息时,可以通过以下方法(可同时使用)将一条消息设置为 @ 信息:
仅 2.14.0 及以上版本的 ZIM SDK 支持发送消息中带 @ 信息。
// 以下为用户在单聊会话中发送 @ 消息的示例代码:
// 创建提醒用户列表
ArrayList<String> mentionArrayList = new ArrayList<>();
// 添加提醒用户(用户可以不在当前会话)
mentionArrayList.add("userId1");
mentionArrayList.add("userId2");
// message 可以为任何类型消息
// 调用接口提醒列表中用户查看消息
message.setMentionedUserIDs(mentionArrayList);
// 提醒会话内所有其他用户查看消息
boolean isMentionAll = true;
message.setIsMentionAll(isMentionAll);
ZIMMessageSendConfig config = new ZIMMessageSendConfig();
// 设置消息优先级
config.priority = ZIMMessagePriority.LOW;
// 是否强推送给被提醒用户(不管对方是否开启了会话免打扰),默认为fasle;
config.isNotifyMentionedUsers = true;
// 以发送单聊信息为例子
ZIMConversationType type = ZIMConversationType.Peer;
zim.sendMessage(message, "conv_id", type, config, new ZIMMessageSentFullCallback() {
@Override
public void onMessageAttached(ZIMMessage zimMessage) {
// 开发者可以通过该回调,监听消息是否开始准备发送。只有当通过本地基础参数检验的消息才会抛出该回调,否则通过 onMessageSent 回调抛出错误。
}
@Override
public void onMessageSent(ZIMMessage zimMessage, ZIMError error) {
// 开发者可以通过该回调监听消息是否发送成功。
}
});
1
// 以下为用户在单聊会话中发送 @ 消息的示例代码:
// 创建提醒用户列表
NSMutableArray<NSString *> *mentionArrayList = [[NSMutableArray alloc] init];
// 添加提醒用户(用户可以不在当前会话)
[mentionArrayList addObject:@"userId1"];
[mentionArrayList addObject:@"userId2"];
// message 可以为任何类型消息
// 调用接口提醒列表中用户查看消息
[message mentionedUserIDs:mentionArrayList];
// 提醒会话内所有其他用户查看消息
BOOL isMentionAll = YES;
[message isMentionAll:isMentionAll];
ZIMMessageSendConfig *config = [[ZIMMessageSendConfig alloc] init];
// 是否强推送给被提醒用户(不管对方是否开启了会话免打扰),默认为 NO;
config.isNotifyMentionedUsers = YES;
// 以发送单聊信息为例
ZIMConversationType type = ZIMConversationTypePeer;
[zim sendMessage:message convId:@"conv_id" type:type config:config callback:^(ZIMMessage *zimMessage, ZIMError *error) {
if (error) {
// 开发者可以通过该回调监听消息是否发送成功。
}
}];
1
// 创建提醒用户列表
std::vector<std::string> mentionArrayList;
// 添加提醒用户(用户可以不在当前会话)
mentionArrayList.push_back("userId1");
mentionArrayList.push_back("userId2");
// message 可以为任何类型消息
message->mentionedUserIDs = mentionArrayList;
// 提醒会话内所有其他用户查看消息
bool isMentionAll = true;
message->isMentionAll = true;
ZIMMessageSendConfig config;
// 设置消息优先级
config.priority = ZIMMessagePriority::LOW;
// 是否强推送给被提醒用户(不管对方是否开启了会话免打扰),默认为 false;
config.isNotifyMentionedUsers = true;
// 以发送单聊信息为例子
ZIMConversationType type = ZIMConversationType::Peer;
zim_->sendMessage(
message, "conv_id", type, config,
std::make_shared<zim::ZIMMessageSendNotification>(
[=](const std::shared_ptr<zim::ZIMMessage> &message) {
if (message) {
// 开发者可以通过该回调,监听消息是否开始准备发送。只有当通过本地基础参数检验的消息才会抛出该回调,否则通过 onMessageSent 回调抛出错误。
}
}),
[=](std::shared_ptr<zim::ZIMMessage> message, zim::ZIMError errorInfo) {
// 开发者可以通过该回调监听消息是否发送成功。
if (errorInfo.code == zim::ZIMErrorCode::ZIM_ERROR_CODE_SUCCESS) {
}
});
1
// 以下为用户在单聊会话中发送 @ 消息(文本消息)的示例代码:
var toConversationID = ''; // 对方 userID
var conversationType = 0; // 会话类型,取值为 单聊:0,房间:1,群组:2
var config = {
priority: 1, // 设置消息优先级,取值为 低:1(默认),中:2,高:3
};
var notification = {
onMessageAttached: function(message) {
}
}
var messageTextObj = {
type: 1,
message: 'xxxx',
isMentionAll: true, // 提醒会话内所有其他用户查看消息
mentionedUserIDs: ["userId1", "userId2"], // 提醒列表中用户查看消息
};
zim.sendMessage(messageTextObj, toConversationID, conversationType, config, notification)
.then(function ({ message }) {
// 发送成功
})
.catch(function (err) {
// 发送失败
});
1
// 以下为用户在单聊会话中发送 @ 消息的示例代码:
try {
// 待提醒的用户列表
List<String> memtionList = ['userID1', 'userID2'];
// message 可以为任何类型消息
// 调用接口提醒列表中用户查看消息
message.mentionedUserIDs(memtionList);
// 提醒会话内所有其他用户查看消息
bool isMentionAll = true;
message.isMentionAll(isMentionAll);
ZIMMessageSendConfig config = ZIMMessageSendConfig();
//设置消息优先级
config.priority = ZIMMessagePriority.low;
// 是否强推送给被提醒用户(不管对方是否开启了会话免打扰),默认为 false;
config.isNotifyMentionedUsers = true;
// 以发送单聊消息为例子
ZIMConversationType type = ZIMConversationType.peer;
ZIMMessageSentResult result = await ZIM.getInstance()!.sendMessage(message, 'conv_id', type, config);
} on PlatformException catch (onError){
onError.code;//根据错误码表处理
onError.message;//错误信息
}
1
接收 @ 消息
接收 @ 消息的回调接口与接收普通消息的回调接口一致,请参考 收发普通消息 - 接收消息 了解具体接口。
收到消息后,开发者可根据业务逻辑实现对应的功能,如高亮等。
- 仅 2.14.0 及以上版本的 ZIM SDK 支持接收并查看 @ 信息中的内容。
- 如果接收端的 SDK 版本介乎 [2.0.0, 2.14.0) 区间,则收到的消息和会话中不会带 @ 信息。
- 如果接收端的 SDK 版本为 1.x.x 版本,则无法收到 @ 信息。
获取 mentionedInfoList
当会话内用户被提醒后,可以被动或主动获取 mentionedInfoList 。
mentionedInfoList,包含 @ 消息的对应消息 ID,发送者 userID,以及 @ 消息的类型 ZIMMessageMentionedType ,开发者可用于实现标记会话等多样业务逻辑。
被动获取
在用户被提醒时,会收到 conversationChanged 回调,即可获取当前 ZIMConversation 的最新 mentionedInfoList 。
@Override
public void onConversationChanged(
ZIM zim, ArrayList<ZIMConversationChangeInfo> conversationChangeInfoList) {
// conversationChangeInfoList 可拿到收到提醒的会话里面的 mentionInfoList
}
1
- (void)zim:(ZIM *)zim
conversationChanged:(NSArray<ZIMConversationChangeInfo *> *)conversationChangeInfoList {
// conversationChangeInfoList 可拿到收到提醒的会话里面的 mentionInfoList
}
1
void onConversationChanged(
ZIM * /*zim*/,
const std::vector<ZIMConversationChangeInfo> & /*conversationChangeInfoList*/) {
// conversationChangeInfoList 可拿到收到提醒的会话里面的 mentionInfoList
}
1
zim.on('conversationChanged', function (zim, { info }) {
console.log(info.mentionInfoList);
});
1
ZIMEventHandler.onConversationChanged = (ZIM zim, List<ZIMConversationChangeInfo> conversationChangeInfoList){
// conversationChangeInfoList 可拿到收到提醒的会话里面的 mentionInfoList
};
1
主动获取
如用 queryConversationList 或者 queryConversation 主动拉取会话,也可获取会话里面的 mentionedInfoList ,可参考以下示例代码:
ArrayList<ZIMMessageMentionedInfo> mentionedInfoList = conversation.mentionedInfoList;
1
NSArray<ZIMMessageMentionedInfo *> * mentionedInfoList = conversation.mentionedInfoList;
1
std::vector<ZIMMessageMentionedInfo> mentionedInfoList = conversation.mentionedInfoList;
1
var mentionedInfoList = conversaion.mentionedInfoList;
1
List<ZIMMessageMentionedInfo> mentionedInfoList = conversation.mentionedInfoList;
1
清除会话的 mentionedInfoList
接收 @ 消息后,用户需要清除会话的 mentionedInfoList ,才能不再被提醒。
清除会话的 mentionedInfoList 接口与清除会话消息未读数接口相同:
获取被提醒用户列表
会话内所有用户都可以调用 mentionedUserIDs 参数获取具体的被提醒用户列表。
ArrayList<String> userIds = message.getMentionedUserIDs();
1
NSArray<NSString *> *userIds = message.mentionedUserIDs;
1
std::vector<std::string> userIds = message.mentionedUserIDs;
1
var userIds = message.mentionedUserIDs;
1
List<String> userIds = message.mentionedUserIDs;
1
确认是否为全员提醒
会话内所有用户都可以调用 isMentionAll 参数,确认消息是否为全员提醒消息。
boolean isMentionAll = message.isMentionAll();
1
BOOL isMentionAll = message.isMentionAll;
1
boolean isMentionAll = message.isMentionAll;
1
var isMentionAll = message.isMentionAll;
1
bool isMentionAll = message.isMentionAll;
1
收发全员推送消息
ZIM 支持您通过服务端向 App 所有在线用户发送消息,目标用户通过客户端接收相关消息。
从服务端向所有用户发送消息
请查看服务端 API 文档 全员推送 文档,实现从服务端向所有用户发送消息。
接收服务端发送的全员推送消息
- 仅 2.10.0 及以上版本的 ZIM SDK 支持接收并查看全员推送消息的内容。
- 如果接收端的 SDK 版本介乎 [2.0.0, 2.10.0) 区间,不可以收到服务端发送的全员推送消息,如需获取此条消息,请将 SDK 升级为 2.10.0 或以上版本。
通过 broadcastMessageReceived 回调,即可接收全员推送消息。
示例代码:
// 用户接收全员推送消息
public void onBroadcastMessageReceived(ZIM zim, ZIMMessage message) {
super.onBroadcastMessageReceived(zim, message);
// 接收到全员推送消息
}
1
// 用户接收全员推送消息
- (void)zim:(ZIM *)zim broadcastMessageReceived:(ZIMMessage *)message {
// 接收到全员推送消息
}
1
// 用户接收全员推送消息
virtual void onBroadcastMessageReceived(ZIM * /*zim*/, const std::shared_ptr<ZIMMessage> & /*message*/) {}
1
// 用户接收全员推送消息
zim.on('broadcastMessageReceived', function (zim, { message }) {
console.log(message);
});
1
// 用户接收全员推送消息
ZIMEventHandler.onBroadcastMessageReceived(zim, message){}
1
转发消息
ZIM SDK 支持实现以下两种形式的消息转发:
具体实现流程,请参考 转发消息。
接收 Tips 消息
ZIM SDK 支持用户在会话内的操作转换为 Tips 消息。当相关操作出现后,ZIM SDK 会向会话发送一条 Tips 消息进行通知,详情请参考 接收 Tips 消息。
监听消息状态
在一些弱网场景中,可能存在以下场景,即消息发送成功,但由于某些因素(如网络丢包),导致 ZIM SDK 未收到服务端应答。此时,ZIM SDK 会因应答超时而认为消息发送失败,但实际上消息发送成功,导致消息状态混乱。为解决该问题,明确消息最终状态, 2.6.0 或以上版本 SDK 支持开发者监听 messageSentStatusChanged 回调,接收消息的状态变化。消息的状态有三种,即 Sending、Success 和 Failed。根据消息状态的变化,开发者可判断消息发送是否成功,并在业务上做相应处理。
// 监听消息状态
zim.setEventHandler(new ZIMEventHandler() {
@Override
public void onMessageSentStatusChanged(
ZIM zim, ArrayList<ZIMMessageSentStatusChangeInfo> messageSentStatusChangeInfoList) {
// 开发者可在这里监听消息状态改变时的回调。
}
});
1
// 监听消息状态
- (void)zim:(ZIM *)zim messageSentStatusChanged:
(NSArray<ZIMMessageSentStatusChangeInfo *> *)messageSentStatusChangeInfoList {
// 开发者可在这里监听消息状态的改变
}
1
// 监听消息状态
void onMessageSentStatusChanged(zim::ZIM *zim, const std::vector<ZIMMessageSentStatusChangeInfo> &messageSentStatusChangeInfoList{
// 开发者可以在这里监听消息状态变更的回调。
}
1
// 监听消息状态
zim.on('messageSentStatusChanged', function (zim, { infos }) {
infos.forEach( function (info) {
console.warn(info.message, info.status);
});
});
1
//监听消息状态
ZIMEventHandler.onMessageSentStatusChanged = (
ZIM zim, List<ZIMMessageSentStatusChangeInfo> messageSentStatusChangedInfoList){
for(ZIMMessageSentStatusChangeInfo info in messageSentStatusChangedInfoList){
log(info.status.toString());
log(info.message!.messageID.toString());
}
};
1