Send and receive messages
This document is for applications developed on iOS, Android, macOS, Windows, and Web.
ZEGOCLOUD's In-app conversation (the ZIM SDK) provides the capability of message management, allowing you to send and receive one-to-one, group, in-room messages, query message history, delete messages, and more. With the message management feature, you can meet different requirements of various scenarios such as social entertainment, online shopping, online education, interactive live streaming, and more.
This document describes how to send and receive messages with the ZIM SDK.
Message types
Message Type | Description | Feature and Scenario |
---|
ZIMCommandMessage(2) | The signaling message whose content can be customized. A signaling message cannot exceed 5 KB in size, and up to 10 signaling messages can be sent per second per client. | Signaling messages, unable to be stored, are applicable to signaling transmission (for example, co-hosting, virtual gifting, and course materials sending) in scenarios with a higher concurrency, such as chat rooms and online classrooms. API: sendMessage |
ZIMBarrageMessage(20) | On-screen comments in a chat room. An on-screen comment cannot exceed 5 KB in size, and there is no number limit on comments that can be sent per second per client. | On-screen comments, unable to be stored are usually unreliable messages that are sent at a high frequency and can be discarded. A high concurrency is supported, but reliability cannot be guaranteed. API: sendMessage |
ZIMTextMessage(1) | The text message. A text message cannot exceed 32 KB in size, and up to 10 text messages can be sent per second per client. | Text messages are reliable, in order, and able to be stored as historical messages. (For the storage duration, please refer to Pricing - Plan Fee - Plan Differences). It is applicable to one-to-one chats, group chats, and on-screen comments in chat rooms. After a room is disbanded, messages in it are not stored.
- Images, files, audio, video: Typically used for sending rich media messages.
- Custom message: Typically used for sending messages such as polls, chain messages, video cards, etc.
- Multi-item Message: Typically used for sending a message including images and text.
API: sendMessage、replyMessage |
ZIMMultipleMessage(10) | Multi-item message, a message that can include multiple texts, up to 10 images, 1 file, 1 audio, 1 video, and 1 custom message. - The total number of items should not exceed 20.
- The size and format restrictions for images, audio, files, and videos are the same as those for the corresponding rich media message types.
|
ZIMImageMessage(11) | Image message. Applicable formats includes JPG, PNG, BMP, TIFF, GIF, and WebP. The maximum size is 10 MB. Up to 10 image messages can be sent per second per client. |
ZIMFileMessage(12) | File Message. A file message contains a file of any format and cannot exceed 100 MB in size. Up to 10 file messages can be sent per second per client. |
ZIMAudioMessage(13) | Audio message. An audio message contains an MP3 or M4A audio of up to 300 seconds and cannot exceed 6 MB in size. Up to 10 audio messages can be sent per second per client. |
ZIMVideoMessage(14) | A video message contains an MP4 or MOV video and cannot exceed 100 MB in size. Up to 10 video messages can be sent per second per client.To retrieve the width and height of the first video frame after a video is successfully sent, the video must be encoded in H.264 or H.265. |
ZIMCombineMessage(100) | For combined messages, there is no limit on message size, and the sending frequency of a single client is limited to 10 times/second. |
ZIMCustomMessage(200) | You can customize the message type and parse the message without using the ZIM SDK. |
Send/Receive regular messages
Regular messages refer to the messages of the following message types: ZIMTextMessage and ZIMBarrageMessage.
- To receive event callbacks (receive messages, get connection status, and receive a notification when Token is about to expire, etc.), you can set up the setEventHandler method and listen for related events.
- When receiving messages, you need to determine the message is a Text message ZIMTextMessage or a Command message ZIMCommandMessage because these two message types are based on the basic message class ZIMMessage. You need to convert the basic message class to a concrete message type and then retrieve the message content from the
message
field.
- When a message is received, it can be sorted using the message's
orderKey
. The larger the orderKey
, the newer the message. And the number of unread messages will be updated automatically upon receiving.
Send messages
The following process shows how Client A sends messages to Client B:
- Client A and Client B create their own ZIM SDK instances, and set up an event handler setEventHandler to listen for the callback on the result of message sending onPeerMessageReceived.
- Client A and Client B log in to the ZIM SDK.
- Client A calls the sendMessage method, and set the
converversationType
to ZIMConversationTypePeer
to send a one-to-one message to Client B.
- Client B listens for the onPeerMessageReceived callback to receive Client A's messages.
You can't send messages to yourself by calling the sendMessage method (when toConversationID = your ID). If you did so, the error code 6000001 will return.
// Send a text message to a one-to-one conversation
String toConversationID = "xxxx1";
ZIMTextMessage zimMessage = new ZIMTextMessage();
zimMessage.message = "Message content";
ZIMMessageSendConfig config = new ZIMMessageSendConfig();
// Set the message priority.
config.priority = ZIMMessagePriority.LOW;
// Set up the configurations of the offline notifications.
// Offline push configuration of room messages is not supported. If you need to send room offline messages, please contact ZEGOCLOUD technical support team to activate relevant permissions.
ZIMPushConfig pushConfig = new ZIMPushConfig();
pushConfig.title = "Offline notification title";
pushConfig.content= "Offline notification content";
pushConfig.extendedData = "Extension info of the offline notification";
config.pushConfig = pushConfig;
ZIMConversationType type = ZIMConversationType.Peer;
zim.sendMessage(zimMessage, toConversationID, type, config, new ZIMMessageSentFullCallback() {
@Override
public void onMessageAttached(ZIMMessage zimMessage) {
// You can use this callback to monitor whether the message is ready to be sent. This callback will be thrown only if the message passes the local basic parameter verification, otherwise an error will be thrown through the onMessageSent callback.
}
@Override
public void onMessageSent(ZIMMessage zimMessage, ZIMError error) {
// You can use this callback to monitor whether the message is ready to be sent. This callback will be thrown only if the message passes the local basic parameter verification, otherwise an error will be thrown through the onMessageSent callback.
}
});
1
// Send a text message to a one-to-one conversation
NSString *toConversationID = @"xxxx1";
ZIMTextMessage *textMessage = [[ZIMTextMessage alloc] init];
textMessage.message = @"Message content";
ZIMMessageSendConfig *config = [[ZIMMessageSendConfig alloc] init];
// Set the message priority.
config.priority = ZIMMessagePriorityLow;
// Set up the configurations of the offline notifications. To use this, enable this feature first.
// Offline push configuration of room messages is not supported. If you need to send room offline messages, please contact ZEGOCLOUD technical support team to activate relevant permissions.
ZIMPushConfig *pushConfig = [[ZIMPushConfig alloc] init];
pushConfig.title = @"Offline notification title";
pushConfig.content= @"Offline notification content";
pushConfig.extendedData = @"Extension info of the offline notification";
config.pushConfig = pushConfig
ZIMMessageSendNotification *notification = [[ZIMMessageSendNotification alloc] init];
notification.onMessageAttached = ^(ZIMMessage * _Nonnull message) {
// The callback on the message not sent yet. Before the message is sent, you can get a temporary ZIMMessage message for you to implement your business logic as needed.
};
ZIMConversationType type = ZIMConversationTypePeer;
[self.zim sendMessage:textMessage toConversationID:toConversationID conversationType:type config:config notification:notification callback:^((ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo)) {
// You can listen for this callback for the message sending results.
}];
1
// Send a text message to a one-to-one conversation
zim::ZIMMessage* message = nullptr;
zim::ZIMTextMessage text_message;
text_message.message = "message";
zim::ZIMMessageSendConfig config;
// Set the message priority.
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
// Send a text message to a one-to-one conversation
var toConversationID = ''; // The userID of the message receiver
var conversationType = 0; // Applicable value: 0 (one-to-one), 1 (room), 2 (group).
var config = {
// Set the message priority.
// The applicable value is 1 (low, default), 2 (middle), 3 (high).
priority: 1,
};
var notification = {
onMessageAttached: function(message) {
//
}
}
var messageTextObj = {
type: 1,
message: 'xxxx'
};
zim.sendMessage(messageTextObj, toConversationID, conversationType, config, notification)
.then(function ({ message }) {
// Sent successfully
})
.catch(function (err) {
// failed to send
});
1
// Send a text message to a one-to-one conversation
ZIMTextMessage textMessage = ZIMTextMessage(message: "message");
ZIMMessageSendConfig sendConfig = ZIMMessageSendConfig();
// Set the message priority.
sendConfig.priority = ZIMMessagePriority.low;
ZIMPushConfig pushConfig = ZIMPushConfig();
pushConfig.title = "Offline notification title";
pushConfig.content = "Offline notification content";
pushConfig.extendedData = "Extension info of the offline notificatio";
sendConfig.pushConfig = pushConfig;
ZIMMessageSendNotification notification = ZIMMessageSendNotification(onMessageAttached: (message){
// Callback before sending: You can obtain a temporary object here, which is the same object as the zimMessage object created by you. You can utilize this feature to implement business logic, such as displaying the UI in advance.
});
ZIMConversationType type = ZIMConversationType.peer;
ZIM.getInstance()!.sendMessage(textMessage, toConversationID, type, sendConfig).then((value) => {
// Sent successfully
}).catchError((onError){
// Failed to send
});
1
Receive messages
- To send a message, call the sendMessage method and pass the appropriate conversationType based on the conversation type.
- To receive a message:
zim.setEventHandler(new ZIMEventHandler() {
@Override
public void onPeerMessageReceived(ZIM zim, ArrayList<ZIMMessage> messageList, ZIMMessageReceivedInfo info, String fromUserID) {
// Callback for receiving one-to-one messages.
for (ZIMMessage zimMessage : messageList) {
if (zimMessage instanceof ZIMTextMessage) {
ZIMTextMessage zimTextMessage = (ZIMTextMessage) zimMessage;
Log.e(TAG, "The text message you received:"+ zimTextMessage.message);
} else if (zimMessage instanceof ZIMCommandMessage) {
ZIMCommandMessage zimCommandMessage = (ZIMCommandMessage) zimMessage;
Log.e(TAG, "The signaling message you received:"+ zimCommandMessage.message);
}
}
}
@Override
public void onGroupMessageReceived(ZIM zim, ArrayList<ZIMMessage> messageList, ZIMMessageReceivedInfo info, String fromGroupID) {
// Callback for receiving group messages.
for (ZIMMessage zimMessage : messageList) {
if (zimMessage instanceof ZIMTextMessage) {
ZIMTextMessage zimTextMessage = (ZIMTextMessage) zimMessage;
Log.e(TAG, "The text message you received:"+ zimTextMessage.message);
} else if (zimMessage instanceof ZIMCommandMessage) {
ZIMCommandMessage zimCommandMessage = (ZIMCommandMessage) zimMessage;
Log.e(TAG, "The signaling message you received:"+ zimCommandMessage.message);
}
}
}
@Override
public void onRoomMessageReceived(ZIM zim, ArrayList<ZIMMessage> messageList, ZIMMessageReceivedInfo info, String fromRoomID) {
// Callback for receiving in-room messages.
for (ZIMMessage zimMessage : messageList) {
if (zimMessage instanceof ZIMTextMessage) {
ZIMTextMessage zimTextMessage = (ZIMTextMessage) zimMessage;
Log.e(TAG, "The text message you received:"+ zimTextMessage.message);
} else if (zimMessage instanceof ZIMCommandMessage) {
ZIMCommandMessage zimCommandMessage = (ZIMCommandMessage) zimMessage;
Log.e(TAG, "The signaling message you received:"+ zimCommandMessage.message);
}
}
}
});
1
// Set up a ZIMEventHander and listen for related callbacks.
[zim setEventHandler:self];
// Callback for receiving the one-to-one message.
- (void)zim:(ZIM *)zim
peerMessageReceived:(NSArray<ZIMMessage *> *)messageList
info:(ZIMMessageReceivedInfo *)info
fromUserID:(NSString *)fromUserID{
// Implement your event handling logic after receiving the message here.
}
// Callback for receiving the group message.
- (void)zim:(ZIM *)zim
groupMessageReceived:(NSArray<ZIMMessage *> *)messageList
info:(ZIMMessageReceivedInfo *)info
fromGroupID:(NSString *)fromGroupID{
// Implement your event handling logic after receiving the message here.
}
// Callback for receiving the in-room message.
- (void)zim:(ZIM *)zim
roomMessageReceived:(NSArray<ZIMMessage *> *)messageList
info:(ZIMMessageReceivedInfo *)info
fromRoomID:(NSString *)fromRoomID{
// Implement your event handling logic after receiving the message here.
}
1
// Callback for receiving the one-to-one message.
void onPeerMessagedReceived(ZIM *zim*,
const std::vector<std::shared_ptr<ZIMMessage>> & messageList,
const ZIMMessageReceivedInfo & info,
const std::string &fromUserID) {
// Implement your event handling logic after receiving the message here.
}
// Callback for receiving the group message.
void onGroupMessagedReceived(ZIM *zim*,
const std::vector<std::shared_ptr<ZIMMessage>> & messageList,
const ZIMMessageReceivedInfo & info,
const std::string &fromGroupID) {
// Implement your event handling logic after receiving the message here.
}
// Callback for receiving the in-room message.
void onRoomMessagedReceived(ZIM *zim*,
const std::vector<std::shared_ptr<ZIMMessage>> & messageList,
const ZIMMessageReceivedInfo & info,
const std::string &fromRoomID) {
// Implement your event handling logic after receiving the message here.
}
1
// Callback for receiving the one-to-one message.
zim.on('peerMessageReceived', function (zim, { messageList, info, fromConversationID }) {
console.log(messageList, info, fromConversationID);
});
// Callback for receiving the group message.
zim.on('groupMessageReceived', function (zim, { messageList, info, fromConversationID }) {
console.log(messageList, info, fromConversationID);
});
// Callback for receiving the in-room message.
zim.on('roomMessageReceived', function (zim, { messageList, info, fromConversationID }) {
console.log(messageList, info, fromConversationID);
});
1
ZIMEventHandler.onPeerMessageReceived = (zim, messageList, info, fromUserID) {
// Triggered when receiving the one-to-one message.
};
ZIMEventHandler.onGroupMessageReceived = (zim, messageList, info, fromGroupID) {
// Triggered when receiving the group message.
};
ZIMEventHandler.onRoomMessageReceived = (zim, messageList, info, fromGroupID) {
// Triggered when receiving the in-room message.
};
1
Send/Receive rich media content
The ZIM SDK now supports sending and receiving messages of different rich media types, such as images, audio, video, and files. To send and receive rich media content, refer to the following:
- To send rich media content after login, the message type (image, file, audio, or video) first and the conversation type (one-to-one, room, group) should be specified.
- To receive rich media content, the recipient should listen for relevant event callbacks related to the conversation type after logging in. This will enable them to receive message events and download the content locally.
- To send rich media content after login, the message type (image, file, audio, or video) first and the conversation type (one-to-one, room, group) should be specified.
- To receive rich media content, the recipient should listen for relevant event callbacks related to the conversation type after logging in. This will enable them to receive message events.
Send rich media content
To send rich media content after login, call the sendMessage method, and specify the message type (image, file, audio, video), the conversation type (one-to-one, room, group), and message related configurations as needed.
- When sending rich media content, the file path to be sent must be in
UTF-8
encoding format.
- To send rich media content to a room/group, the sender must be in the room/group.
// Send rich media content in one-to-one conversation - Send an image:
ZIMImageMessage message = new ZIMImageMessage("/storage/emulated/0/Android/data/packagename/picture/xxx.jpg");
// If a network URL is entered here, the SDK will pass through the path without ZIM background service processing. If both the network URL and the local path are entered, the SDK will prioritize the network URL that you want to use.
message.setLargeImageDownloadUrl("url");
message.setFileDownloadUrl("url");
message.setThumbnailDownloadUrl("url");
ZIMMessageSendConfig config = new ZIMMessageSendConfig();
// Set message priority.
config.priority = ZIMMessagePriority.LOW;
// Set up the configurations of the offline notifications.
ZIMPushConfig pushConfig = new ZIMPushConfig();
pushConfig.title = "Offline notification title";
pushConfig.content= "Offline notification content";
pushConfig.extendedData = "Extension info of the offline notification";
config.pushConfig = pushConfig;
zim.sendMessage(message, toConversationID, ZIMConversationType.PEER, config, new ZIMMessageSentFullCallback() {
@Override
public void onMessageSent(ZIMMessage message, ZIMError errorInfo) {
// You can use this callback to monitor whether the message is ready to be sent. This callback will be thrown only if the message passes the local basic parameter verification, otherwise an error will be thrown through the onMessageSent callback.。
}
@Override
public void onMessageAttached(ZIMMessage message){
}
@Override
public void onMediaUploadingProgress(ZIMMediaMessage message, long currentFileSize, long totalFileSize, ) {
// You can use this callback to monitor whether the message is sent successfully.
}
});
1
// Send rich media content in one-to-one conversation - Send a file:
ZIMFileMessage message = new ZIMFileMessage("/storage/emulated/0/Android/data/packagename/picture/xxx.zip");
// If a network URL is provided here, the SDK will pass through the path directly without processing it via the ZIM backend services. When both a network URL and a local path are provided, the SDK will prioritize using the network 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
// Send rich media content in one-to-one conversation - Send an audio:
ZIMAudioMessage message = new ZIMAudioMessage("/storage/emulated/0/Android/data/packagename/picture/xxx.mp3", 300); // 300 is only for example, the unit is second.
// If a network URL is provided here, the SDK will pass through the path directly without processing it via the ZIM backend services. When both a network URL and a local path are provided, the SDK will prioritize using the network 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
// Send rich media content in one-to-one conversation - Send a video:
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
// Send rich media content in one-to-one conversation - Send an image:
ZIMImageMessage *imgMsg = [[ZIMImageMessage alloc] init];
// Fill in a UTF-8 local path (the path to the local picture is recommended)
// The following uses a temporary image path as an example:
imgMsg.fileLocalPath = @"/private/var/mobile/Containers/Data/Application/C142EFE6-9DEC-449D-89B7-BF99F2578F98/tmp/D1513E30-2641-440B-B897-48CD43BE1D04.jpeg";
// If a network URL is entered here, the SDK will pass through the path without ZIM background service processing. If both the network URL and the local path are entered, the SDK will prioritize the network URL that you want to use.
imgMsg.fileDownloadUrl = @"";
ZIMMessageSendConfig *sendConfig = [[ZIMMessageSendConfig alloc] init];
sendConfig.priority = 1;
ZIMMessageSendNotification *notification = [[ZIMMessageSendNotification alloc] init];
notification.onMessageAttached = ^(ZIMMessage * _Nonnull message) {
// Implement your event handling logic before the message is sent.
};
notification.onMediaUploadingProgress = ^(ZIMMediaMessage * _Nonnull message, unsigned long long currentFileSize, unsigned long long totalFileSize) {
// You can listen for the callback to know the uploading progress of the rich media message you sent.
};
[[ZIM getInstance] sendMessage:imgMsg toConversationID:@"conversationID" conversationType:ZIMConversationTypePeer config:sendConfig notification:notification callback:^(ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo) {
}];
1
// Send rich media content in one-to-one conversation - Send an audio:
// You need to provide the local path in UTF-8 format (it is recommended to use the path of the app's local audio), audio duration (in seconds).
// Here, a local audio file path is used as an example.
ZIMAudioMessage audioMessage = [[ZIMAudioMessage alloc] initWithFileLocalPath:@"/private/var/mobile/Containers/Shared/AppGroup/D5144D14-3FE8-4C6C-8527-01F368B8E49E/File Provider Storage/IMG_0131.mp3" audioDuration:10];
// If a network URL is entered here, the SDK will pass through the path without ZIM background service processing. If both the network URL and the local path are entered, the SDK will prioritize the network URL that you want to use.
audioMessage.fileDownloadUrl = @"";
ZIMMessageSendConfig *sendConfig = [[ZIMMessageSendConfig alloc] init];
sendConfig.priority = ZIMMessagePriorityHigh;
ZIMMessageSendNotification *notification = [[ZIMMessageSendNotification alloc] init];
notification.onMessageAttached = ^(ZIMMessage * _Nonnull message) {
// Implement your event handling logic before the message is sent.
};
notification.onMediaUploadingProgress = ^(ZIMMediaMessage * _Nonnull message, unsigned long long currentFileSize, unsigned long long totalFileSize) {
// You can listen for the callback to know the uploading progress of the rich media message you sent.
};
[[ZIM getInstance] sendMessage:audioMessage toConversationID:@"conversationID" conversationType:ZIMConversationTypePeer config:sendConfig notification:notification callback:^(ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo) {
}];
1
// Send rich media content in one-to-one conversation - Send an video:
ZIMVideoMessage *videoMessage = [[ZIMVideoMessage alloc] init];
// You need to provide the local path in UTF-8 format.
// Here, a local video file path is used as an example.
videoMessage.fileLocalPath = @"/var/mobile/Containers/Data/Application/C142EFE6-9DEC-449D-89B7-BF99F2578F98/Documents/22-08-31-10:23:49.mp4";
// If a network URL is entered here, the SDK will pass through the path without ZIM background service processing. If both the network URL and the local path are entered, the SDK will prioritize the network URL that you want to use.
videoMessage.fileDownloadUrl = @"";
ZIMMessageSendConfig *sendConfig = [[ZIMMessageSendConfig alloc] init];
sendConfig.priority = ZIMMessagePriorityHigh;
ZIMMessageSendNotification *notification = [[ZIMMessageSendNotification alloc] init];
notification.onMessageAttached = ^(ZIMMessage * _Nonnull message) {
// Implement your event handling logic before the message is sent.
};
notification.onMediaUploadingProgress = ^(ZIMMediaMessage * _Nonnull message, unsigned long long currentFileSize, unsigned long long totalFileSize) {
// You can listen for the callback to know the uploading progress of the rich media message you sent.
};
[[ZIM getInstance] sendMessage:videoMessage toConversationID:@"conversationID" conversationType:ZIMConversationTypePeer config:sendConfig notification:notification callback:^(ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo) {
}];
1
// Send rich media content in one-to-one conversation - Send a file:
ZIMFileMessage *fileMsg = [[ZIMFileMessage alloc] init];
// You need to provide the local path in UTF-8 format.
fileMsg.fileLocalPath = @"/private/var/mobile/Containers/Shared/AppGroup/D5144D14-3FE8-4C6C-8527-01F368B8E49E/File Provider Storage/IMG_0131.HEIC";
// If a network URL is entered here, the SDK will pass through the path without ZIM background service processing. If both the network URL and the local path are entered, the SDK will prioritize the network URL that you want to use.
fileMsg.fileDownloadUrl = @"";
ZIMMessageSendConfig *sendConfig = [[ZIMMessageSendConfig alloc] init];
sendConfig.priority = ZIMMessagePriorityHigh;
ZIMMessageSendNotification *notification = [[ZIMMessageSendNotification alloc] init];
notification.onMessageAttached = ^(ZIMMessage * _Nonnull message) {
// Implement your event handling logic before the message is sent.
};
notification.onMediaUploadingProgress = ^(ZIMMediaMessage * _Nonnull message, unsigned long long currentFileSize, unsigned long long totalFileSize) {
// You can listen for the callback to know the uploading progress of the rich media message you sent.
};
[[ZIM getInstance] sendMessage:fileMsg toConversationID:@"conversationID" conversationType:ZIMConversationTypePeer config:sendConfig notification:notification callback:^(ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo) {
}];
1
// Send rich media content in one-to-one conversation - Send an image:
zim::ZIMMediaMessage *message = nullptr;
auto imageMessage = zim::ZIMImageMessage();
zim::ZIMMessageSendConfig sendConfig;
zim::ZIMPushConfig pushConfig;
// Offline notification title
pushConfig.title = "win_push_title";
// Offline notification content
pushConfig.content = "win_push_content";
// Extension info of the offline notification
pushConfig.extendedData = "win_push_extended_data";
sendConfig.priority = zim::ZIM_MESSAGE_PRIORITY_MEDIUM;
// Assign a value when offline push is required; if not needed, it can be assigned as nullptr.
sendConfig.pushConfig = &pushConfig;
// Provide the local path in UTF-8 format.
imageMessage.fileLocalPath = "D:\\image\\img.jpg";
// If a network URL is provided here, the SDK will pass through the path directly without processing it via the ZIM backend services. When both a network URL and a local path are provided, the SDK will prioritize using the network URL.
imageMessage.fileDownloadUrl = "";
imageMessage.largeImageDownloadUrl = "";
imageMessage.thumbnailDownloadUrl = "";
message = &imageMessage;
auto notification = std::make_shared<zim::ZIMMessageSendNotification>(
[=](const std::shared_ptr<zim::ZIMMessage> &message) {
// Implement your event handling logic before the message is sent.
},
[=](const std::shared_ptr<zim::ZIMMediaMessage> &message,
unsigned long long currentFileSize,
unsigned long long totalFileSize) {
// You can listen for the callback to know the uploading progress of the rich media message you sent.
});
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
// Send rich media content in one-to-one conversation - Send a file:
zim::ZIMMediaMessage *message = nullptr;
auto fileMessage = zim::ZIMFileMessage();
zim::ZIMMessageSendConfig sendConfig;
zim::ZIMPushConfig pushConfig;
// Offline notification title
pushConfig.title = "win_push_title";
// Offline notification content
pushConfig.content = "win_push_content";
// Extension info of the offline notification
pushConfig.extendedData = "win_push_extended_data";
sendConfig.priority = zim::ZIM_MESSAGE_PRIORITY_MEDIUM;
// Assign a value when offline push is required; if not needed, it can be assigned as nullptr.
sendConfig.pushConfig = &pushConfig;
// Provide the local path in UTF-8 format.
fileMessage.fileLocalPath = "D:\\file\\files.zip";
// If a network URL is provided here, the SDK will pass through the path directly without processing it via the ZIM backend services. When both a network URL and a local path are provided, the SDK will prioritize using the network URL.
fileMessage.fileDownloadUrl = "";
message = &fileMessage;
auto notification = std::make_shared<zim::ZIMMessageSendNotification>(
[=](const std::shared_ptr<zim::ZIMMessage> &message) {
// Implement your event handling logic before the message is sent.
},
[=](const std::shared_ptr<zim::ZIMMediaMessage> &message,
unsigned long long currentFileSize,
unsigned long long totalFileSize) {
// You can listen for the callback to know the uploading progress of the rich media message you sent.
});
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
// Send rich media content in one-to-one conversation - Send an audio:
zim::ZIMMediaMessage *message = nullptr;
auto audioMessage = zim::ZIMAudioMessage();
zim::ZIMMessageSendConfig sendConfig;
zim::ZIMPushConfig pushConfig;
// Offline notification title
pushConfig.title = "win_push_title";
// Offline notification content
pushConfig.content = "win_push_content";
// Extension info of the offline notification
pushConfig.extendedData = "win_push_extended_data";
sendConfig.priority = zim::ZIM_MESSAGE_PRIORITY_MEDIUM;
// Assign a value when offline push is required; if not needed, it can be assigned as nullptr.
sendConfig.pushConfig = &pushConfig;
// Provide the local path in UTF-8 format.
audioMessage.fileLocalPath = "D:\\audio\\audio.mp3";
// If a network URL is provided here, the SDK will pass through the path directly without processing it via the ZIM backend services. When both a network URL and a local path are provided, the SDK will prioritize using the network URL.
audioMessage.fileDownloadUrl = "";
// Audio duration in seconds
audioMessage.audioDuration = 15;
message = &audioMessage;
auto notification = std::make_shared<zim::ZIMMessageSendNotification>(
[=](const std::shared_ptr<zim::ZIMMessage> &message) {
// Implement your event handling logic before the message is sent.
},
[=](const std::shared_ptr<zim::ZIMMediaMessage> &message,
unsigned long long currentFileSize,
unsigned long long totalFileSize) {
// You can listen for the callback to know the uploading progress of the rich media message you sent.
});
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
// Send rich media content in one-to-one conversation - Send a video:
zim::ZIMMediaMessage *message = nullptr;
auto videoMessage = zim::ZIMVideoMessage();
zim::ZIMMessageSendConfig sendConfig;
zim::ZIMPushConfig pushConfig;
// Offline notification title
pushConfig.title = "win_push_title";
// Offline notification content
pushConfig.content = "win_push_content";
// Extension info of the offline notification
pushConfig.extendedData = "win_push_extended_data";
sendConfig.priority = zim::ZIM_MESSAGE_PRIORITY_MEDIUM;
// Assign a value when offline push is required; if not needed, it can be assigned as nullptr.
sendConfig.pushConfig = &pushConfig;
// Provide the local path in UTF-8 format.
videoMessage.fileLocalPath = "D:\\file\\video.mp4";
// If a network URL is provided here, the SDK will pass through the path directly without processing it via the ZIM backend services. When both a network URL and a local path are provided, the SDK will prioritize using the network URL.
videoMessage.fileDownloadUrl = "";
videoMessage.videoFirstFrameDownloadUrl = "";
// Video duration in seconds
videoMessage.videoDuration = 100;
message = &videoMessage;
auto notification = std::make_shared<zim::ZIMMessageSendNotification>(
[=](const std::shared_ptr<zim::ZIMMessage> &message) {
// Implement your event handling logic before the message is sent.
},
[=](const std::shared_ptr<zim::ZIMMediaMessage> &message,
unsigned long long currentFileSize,
unsigned long long totalFileSize) {
// You can listen for the callback to know the uploading progress of the rich media message you sent.
});
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
// Send rich media content in one-to-one conversation - Send an image:
ZIMImageMessage imageMessage = ZIMImageMessage('xxx/xxx.jpeg');
ZIMMessageSendConfig sendConfig = ZIMMessageSendConfig();
ZIMMessageSendNotification notification = ZIMMessageSendNotification(onMessageAttached: (message){
// Implement your event handling logic after sending the message here.
},onMediaUploadingProgress: (message,currentFileSize,totalFileSize){
// You can listen for the callback to know the uploading progress of the rich media message you sent.
});
ZIM.getInstance()!.sendMessage(
imageMessage,
'toConversationID',
ZIMConversationType.peer,
sendConfig, notification).then((value) => {
// Sent successfully
}).catchError((onError){
// Failed to send
});
1
// Send rich media content in one-to-one conversation - Send a video:
ZIMVideoMessage videoMessage = ZIMVideoMessage('xxx/xxx.mov');
ZIMMessageSendConfig sendConfig = ZIMMessageSendConfig();
ZIMMessageSendNotification notification = ZIMMessageSendNotification(onMessageAttached: (message){
// Implement your event handling logic after sending the message here.
},onMediaUploadingProgress: (message,currentFileSize,totalFileSize){
// You can listen for the callback to know the uploading progress of the rich media message you sent.
});
ZIM
.getInstance()
!.sendMessage(
videoMessage,
'toConversationID',
ZIMConversationType.peer,
sendConfig, notification)
.then((value) => {
// Sent successfully
})
.catchError((onError) {
// Failed to send
});
1
// Send rich media content in one-to-one conversation - Send an audio:
ZIMAudioMessage audioMessage = ZIMAudioMessage('xxx/xxx.mp3');
ZIMMessageSendConfig sendConfig = ZIMMessageSendConfig();
ZIMMessageSendNotification notification = ZIMMessageSendNotification(onMessageAttached: (message){
// Implement your event handling logic after sending the message here.
},onMediaUploadingProgress: (message,currentFileSize,totalFileSize){
// You can listen for the callback to know the uploading progress of the rich media message you sent.
});
ZIM
.getInstance()
!.sendMessage(
audioMessage,
'toConversationID',
ZIMConversationType.peer,
ZIMMessageSendConfig(), notification)
.then((value) => {
// Sent successfully
})
.catchError((onError) {
// Failed to send
});
1
// Send rich media content in one-to-one conversation - Send a file:
ZIMFileMessage fileMessage = ZIMFileMessage('xxx/xxx.txt');
ZIMMessageSendConfig sendConfig = ZIMMessageSendConfig();
ZIMMessageSendNotification notification = ZIMMessageSendNotification(onMessageAttached: (message){
// Implement your event handling logic after sending the message here.
},onMediaUploadingProgress: (message,currentFileSize,totalFileSize){
// You can listen for the callback to know the uploading progress of the rich media message you sent.
});
ZIM
.getInstance()
!.sendMessage(
fileMessage,
'toConversationID',
ZIMConversationType.peer,
ZIMMessageSendConfig(), notification)
.then((value) => {
// Sent successfully
})
.catchError((onError) {
// Failed to send
});
1
Callback for the sending progress of rich media content
You will be notified of the sending progress of rich media content through the callback 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
Among which:
- message: The content of the message being sent.
- currentFileSiz: The size of the message that has been sent.
- totalFileSize: The overall size of the message sent.
Receive rich media content
To receive the rich media content messages, do the following:
After logging in, users should listen for the following callbacks based on the conversation type (one-to-one, room, group): onPeerMessageReceived, onRoomMessageReceived, onGroupMessageReceived, to receive the events of rich media messages. From the events, the URL of rich media content can be obtained directly.
If you want to download the rich media content locally, call the downloadMediaFile method.
When downloading rich media content, you need to specify the file type of the corresponding media messages first.
- Image messages: You can choose to download the original file, large view, or thumbnail.
- Files/Audio messages: Only original files/audio files can be downloaded.
- Video messages: You can choose to download the original video file and the thumbnail of the first frame of the video.
// Receive rich media content in one-to-one conversation - Receive images:
@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) {
// You can tell by the Type which kind of message you are receiving.
if (message.getType() == ZIMMessageType.IMAGE) {
// Receive the image
ZIMImageMessage imageMessage = (ZIMImageMessage) message;
zim.downloadMediaFile(imageMessage, ZIMMediaFileType.ORIGINAL_FILE, config, new ZIMMediaDownloadedCallback() {
@Override
public void onMediaDownloaded(ZIMMessage message, ZIMError errorInfo) {
// The callback for download completion.
}
@Override
public void onMediaDownloadingProgress(ZIMMessage message, long currentFileSize, long totalFileSize) {
// The download progress
}
});
} else if (message.getType() == ZIMMessageType.VIDEO) {
// Receive the video
ZIMVideoMessage videoMessage = (ZIMVideoMessage) message;
} else if (message.getType() == ZIMMessageType.AUDIO) {
// Receive the audio
ZIMAudioMessage audioMessage = (ZIMAudioMessage) message;
} else if (message.getType() == ZIMMessageType.FILE) {
// Receive the file
ZIMFileMessage fileMessage = (ZIMFileMessage) message;
}
}
}
1
// Receive rich media content in one-to-one conversation - Receive images
- (void)peerMessageReceived:(NSArray<ZIMMessage *> *)messageList
info:(ZIMMessageReceivedInfo *)info
fromUserID:(NSString *)fromUserID{
ZIMMediaDownloadConfig *config = [[ZIMMediaDownloadConfig alloc] init];
for (ZIMMessage *msg in reverseMsgList) {
// You can tell by the Type which kind of message you are receiving.
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
// Receive rich media content in one-to-one conversation
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) {
// You can tell by the Type which kind of message you are receiving.
if (it->getType() == zim::ZIMMessageType::ZIM_MESSAGE_TYPE_IMAGE) {
// Image message type
auto image_message = std::dynamic_pointer_cast<zim::ZIMImageMessage>(it);
// The following demonstrates how to download the original image.
// If you want to get the image of another type, change 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) {
// File message type
auto media_message = std::dynamic_pointer_cast<zim::ZIMFileMessage>(it);
...
} else if (it->getType() == zim::ZIMMessageType::ZIM_MESSAGE_TYPE_AUDIO) {
// Audio message type
auto media_message = std::dynamic_pointer_cast<zim::ZIMAudioMessage>(it);
...
} else if (it->getType() == zim::ZIMMessageType::ZIM_MESSAGE_TYPE_VIDEO) {
// Video message type
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
// Receive rich media content in one-to-one conversation
ZIMEventHandler.onPeerMessageReceived = (zim, messageList, info, fromUserID) {
// Triggered when receiving a message from a one-to-one
for (ZIMMessage message in messageList) {
// You can tell by messgae.type which kind of message you are receiving
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
Callback for the downloading progress of rich media content
You will be notified of the downloading progress of rich media content through the callback 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
Among which:
- message: The message content you are downloading.
- currentFileSize: The size of messages that have been downloaded.
- totalFileSize: The overall size of the download message.
Send/Receive signaling messages
The ZIM SDK now supports you to send and receive signaling messages. To do that, you can call the ZIMCommandMessage to define the message type you want to send, for example, your location information.
This message type does not support offline push and local storage.
The following shows how to send custom messages to a specified user.
Send signaling messages
// Send a signaling message to a user
String userID = "xxxx";
ZIMCommandMessage zimCustomMessage = new ZIMCommandMessage();
zimCustomMessage.message = new byte[]{0x1,0x2,0x1,0x2};
ZIMMessageSendConfig config = new ZIMMessageSendConfig();
// Set message priority.
config.priority = ZIMMessagePriority.LOW;
// Configure for offline notification
// For a room conversation, offline notification is not supported. To use it, contact ZEGOCLOUD Technical Support to enable the feature first.
ZIMPushConfig pushConfig = new ZIMPushConfig();
pushConfig.title = "Offline notification title";
pushConfig.content= "Offline notification content";
pushConfig.extendedData = "Extra information for the offline notification";
config.pushConfig = pushConfig;
// Send a one-to-one message.
ZIMConversationType type = ZIMConversationType.Peer;
// Send a group message.
// ZIMConversationType type = ZIMConversationType.Gourp;
// Send a in-room message.
// ZIMConversationType type = ZIMConversationType.Room;
zim.sendMessage(zimCustomMessage, toConversationID, type, config, new ZIMMessageSentFullCallback() {
@Override
public void onMessageAttached(ZIMMessage zimMessage) {
// You can use this callback to monitor whether the message is ready to be sent. This callback will be thrown only if the message passes the local basic parameter verification, otherwise an error will be thrown through the onMessageSent callback.
}
@Override
public void onMessageSent(ZIMMessage zimMessage, ZIMError error) {
// You can listen for the callback to know whether the message is sent successfully.
}
});
1
// Send signaling messages to a specified user.
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)) {
// You can listen for this callback on the results of the message sending.
}];
1
// Send signaling messages to a specified user.
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;
// Send an one-to-one message
zim::ZIMConversationType type = zim::ZIMConversationType::ZIM_CONVERSATION_TYPE_PEER
// Send a group message
// zim::ZIMConversationType type = zim::ZIMConversationType::ZIM_CONVERSATION_TYPE_GROUP
// Send a room message
// 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; });
// Send a message
zim_->sendMessage(message, "toConversationID", type, config, notification,
[=](const std::shared_ptr<zim::ZIMMessage> &message,
const zim::ZIMError &errorInfo) { int i = 0; });
1
// Send signaling messages to a specified user.
var toConversationID = ''; // The recipient's user ID.
var conversationType = 0; // 0: one-to-one, 1: room, 2: group
var config = {
priority: 1, // 1: low (default), 2: middle, 3: high
};
var notification = {
onMessageAttached: function(message) {
//
}
}
// Here, a JSON string is used as an example, and the string needs to be converted to a Uint8Array.
// When `peerMessageReceived` receives a message with type 2, the Uint8Array needs to be converted back to a JSON string.
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 }) {
// Sent successfully
})
.catch(function (err) {
// Failed to send
});
1
// Send signaling messages to a specified user.
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) => {
// Sent successfully
})
.catchError((onError) {
// Failed to send
});
1
Receive signaling messages
// Receive signaling messages.
zim.setEventHandler(new ZIMEventHandler() {
@Override
public void onPeerMessageReceived(ZIM zim, ArrayList<ZIMMessage> messageList, ZIMMessageReceivedInfo info, String fromUserID) {
// Callback on the command message received.
for (ZIMMessage zimMessage : messageList) {
if (zimMessage instanceof ZIMCommandMessage) {
ZIMCommandMessage zimCommandMessage = (ZIMCommandMessage) zimMessage;
}
}
}
});
1
// Receive signaling messages.
- (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
// Receive signaling messages.
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
// Receive signaling messages.
zim.on('peerMessageReceived', function (zim, { messageList, info, fromConversationID }) {
console.log(messageList, info, fromConversationID);
messageList.forEach(function (msg) {
// Here, take the JSON string as an example, which needs to be converted to Uint8Array.
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
// Receive signaling messages.
ZIMEventHandler.onPeerMessageReceived = (zim, messageList, info, fromUserID) {
// Triggered when receiving a command message
for (ZIMMessage message in messageList) {
switch (message.type) {
case ZIMMessageType.command:
message as ZIMCommandMessage;
break;
default:
}
}
};
1
Send/Receive custom messages
The ZIM SDK supports developers in implementing the sending and receiving of custom message types. Developers can define their own message types using the ZIMCustomMessage object, such as voting, chain, video card, and more. Developers can follow these steps to implement the sending and receiving of custom messages.
- Only ZIM SDK version 2.8.0 and above supports sending custom type messages, receiving and viewing the content of custom type messages.
- If the SDK version of the receiving end is between [2.0.0, 2.8.0), the custom message can be received, but the message type will be displayed as unknown and the information content cannot be obtained. To get this message, please upgrade the SDK to version 2.8.0 or above.
- If the SDK version of the receiving end is version 1.x.x, you cannot receive custom messages or unknown messages.
Send custom messages
The interface used to send custom messages is sendMessage, which is the same as the interface used to send regular messages. Developers can refer to Send & Receive messages - Send messages to learn about this interface Parameter details.
Developers need to define custom type messages through the ZIMCustomMessage object.
// Send a custom message to specified users in a one-to-one conversation
String userID = "xxxx";
// Customize the text content of the message
String message = "";
// Specific custom type
int subType = 100;
// Customize the search field of the message.
String searchedContent = "";
ZIMCustomMessage zimCustomMessage = new ZIMCustomMessage(message,subType);
// Advanced property configuration for sending messages
ZIMMessageSendConfig config = new ZIMMessageSendConfig();
// Set message priority
config.priority = ZIMMessagePriority.LOW;
// Send one-to-one conversation message
ZIMConversationType type = ZIMConversationType.Peer;
zim.sendMessage(zimCustomMessage, userID, type, config, new ZIMMessageSentFullCallback() {
@Override
public void onMessageAttached(ZIMMessage zimMessage) {
// You can use this callback to monitor whether the message is ready to be sent. This callback will be thrown only if the message passes the local basic parameter verification, otherwise an error will be thrown through the onMessageSent callback.
}
@Override
public void onMessageSent(ZIMMessage zimMessage, ZIMError error) {
// You can use this callback to monitor whether the message is sent successfully.
}
});
1
// Send a custom message to a specified user.
NSString *message = @"message";
NSString *toUserID = @"toUserID";
ZIMCustomMessage * customMessage = [[ZIMCustomMessage alloc] init];
customMessage.message = message;
customMessage.subType = 1; // Developer-defined type
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)) {
// Developers can use this callback to monitor whether the message is sent successfully.
}];
1
// Send a custom message to a specified user
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
// Send a custom message to a specified user
// Pass in the userID of the message receiver
var toConversationID = "xxxx";
var conversationType = 0; // 0: One-to-one; 1: Room,2: Group
// Advanced settings
var config = {
priority: 1, // Message priority: 1: Low (default); 2: Medium; 3: High.
};
var notification = {
onMessageAttached: function(message) {
//
}
}
var zimCustomMessage = {
type: 200,
message: 'xxxx', // Text of custom message
subType: 100, // Specific custom message type
searchedContent: 'xxxx'
};
zim.sendMessage(zimCustomMessage, toConversationID, conversationType, config, notification)
.then(function ({ message }) {
// Sent successfully
})
.catch(function (err) {
// Failed to send
});
1
// Send a custom message to a specified user
// Pass in the userID of the message receiver
String userID = "xxxx";
// Message text
String message = "";
// Specific custom message type
int subType = 100;
String searchedContent = "";
ZIMCustomMessage zimCustomMessage = ZIMCustomMessage(message, subType);
// Advanced settings
ZIMMessageSendConfig config = ZIMMessageSendConfig();
// Message Priority
config.priority = ZIMMessagePriority.low;
ZIMConversationType type = ZIMConversationType.Peer;
ZIM.getInstance().sendMessage(zimCustomMessage, userID, type, config, ZIMMessageSendNotification(onMessageAttached: (ZIMMessage message){
// Developers can use this callback to listen for whether the message is ready to be sent. Only messages that pass the local basic parameter check will trigger this callback, otherwise an error will be thrown through the onMessageSent callback.
})).then((value) {
// Successful callback
}).catchError((onError){
// Handle failure
});
1
Receive custom messages
The callback interface for receiving custom messages is the same as the callback interface for receiving regular messages. Please refer to Send & Receive messages - Receive messages for details on the specific interface.
The following is an example code for receiving custom messages in a one-to-one conversation:
// User receives custom message in a one-to-one conversation
zim.setEventHandler(new ZIMEventHandler() {
@Override
public void onPeerMessageReceived(ZIM zim, ArrayList<ZIMMessage> messageList, ZIMMessageReceivedInfo info, String fromUserID) {
// Callback when receiving "one-to-one conversation" message
for (ZIMMessage zimMessage : messageList) {
if (zimMessage instanceof ZIMCustomMessage) {
ZIMCustomMessage zimCustomMessage = (ZIMCustomMessage) zimMessage;
}
}
}
});
1
// Receiving custom messages in a one-to-one conversation
- (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){
// This indicates that a custom message has been received.
}
}
}
1
// Receive Custom Messages in a one-to-one conversation
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
// Receive a custom messages in a one-to-one conversation
zim.on('peerMessageReceived', function (zim, { messageList, info, fromConversationID }) {
console.log(messageList, info, fromConversationID);
messageList.forEach(function (msg) {
// When receiving a custom message
if (msg.type == 200) {
}
})
});
1
// Receive a custom messages in a one-to-one conversation
ZIMEventHandler.onPeerMessageReceived = (zim, messageList, info, fromUserID) {
for (ZIMMessage message in messageList) {
if(message is ZIMCustomMessage){
}
}
};
1
Send/Receive multi-item messages
ZIM SDK supports sending multiple types of content in a single message, such as text, images, and more. This type of message is referred to as a "multi-message. You can define this type of message by using the ZIMCustomMessage object.
- Only ZIM SDK version 2.19.0 and above supports sending multi-item messages, receiving and viewing the content of multi-item messages.
- If the SDK version of the receiving end is between [2.0.0, 2.19.0), the multi-item message can be received, but the message type will be displayed as unknown and the information content cannot be obtained. To get this message, please upgrade the SDK to version 2.19.0 or above.
- If the SDK version of the receiving end is version 1.x.x, you cannot receive multi-item messages or unknown messages.
Send multi-item messages
After the user logs in successfully, they can send 1 message containing various types of content (such as text, images, audio, video, files, and custom messages) using the ZIMMultipleMessage object in one-to-one chats, room chats, or group chats via the sendMessage interface.
You can use the onMultipleMediaUploadingProgress callback to receive notifications about the upload progress of rich media files in the multi-item message. This callback provides the following fields:
- currentFileSize: Total size of the uploaded files, in bytes.
- totalFileSize: Total size of all rich media files in the multi-item message, in bytes.
- messageInfoIndex: The index of the currently uploading file in the ZIMMultipleMessage array.
- currentIndexFileSize: Uploaded size of the currently uploading file, in bytes.
- totalIndexFileSize: Actual size of the currently uploading file, in bytes.
These fields can be used to calculate the overall upload progress and the progress of the current file being uploaded:
- Total upload progress =
currentFileSize / totalFileSize
.
- Current file upload progress =
currentIndexFileSize / totalIndexFileSize
.
// Send a multi-item message in a one-to-one conversation
String userID = "xxxx";
// The item list of multi-item message can contain a maximum of 20 items.
ArrayList<ZIMMessageLiteInfo> messageInfoList = new ArrayList();
// Text
ZIMTextMessageLiteInfo textMsgInfo= new ZIMTextMessageLiteInfo();
textMsgInfo.message = "Message content";
messageInfoList.add(textMsgInfo);
// Custom message: Only 1 allowed.
ZIMCustomMessageLiteInfo customMsgInfo= new ZIMCustomMessageLiteInfo();
customMsgInfo.message = "Message content";
customMsgInfo.searchedContent = "Searched";
customMsgInfo.subType = 100;
messageInfoList.add(customMsgInfo);
// Image: Only 10 allowed.
// Online image
ZIMImageMessageLiteInfo imageMsgInfo= new ZIMImageMessageLiteInfo();
imageMsgInfo.fileDownloadUrl = "https://xxxx.jpeg"; // Original Image
imageMsgInfo.thumbnailDownloadUrl = "https://xxxx-thumbnail.jpeg"; // Thumbnail
imageMsgInfo.largeImageDownloadUrl = "https://xxxx-large.jpeg"; // Large Image
messageInfoList.add(imageMsgInfo);
// Local Image
ZIMImageMessageLiteInfo localImageMsgInfo= new ZIMImageMessageLiteInfo();
localImageMsgInfo.fileLocalPath = "/storage/emulated/0/Android/data/packagename/xxx.jpg"; // Absolute path of the image
messageInfoList.add(localImageMsgInfo);
// File: Only 1 allowed.
ZIMFileMessageLiteInfo localFileMsgInfo= new ZIMFileMessageLiteInfo();
localFileMsgInfo.fileLocalPath = "/storage/emulated/0/Android/data/packagename/xxx.zip"; // Absolute path of the file
messageInfoList.add(localFileMsgInfo);
// Audio: Only 1 allowed.
ZIMAudioMessageLiteInfo localAudioMsgInfo= new ZIMAudioMessageLiteInfo();
localAudioMsgInfo.fileLocalPath = "/storage/emulated/0/Android/data/packagename/xxx.mp3"; // Absolute path of the audio
localAudioMsgInfo.audioDuration = 100; // Required: Audio duration in seconds.
messageInfoList.add(localAudioMsgInfo);
// Video: Only 1 allowed.
ZIMVideoMessageLiteInfo localVideoMsgInfo= new ZIMVideoMessageLiteInfo();
localVideoMsgInfo.fileLocalPath = "/storage/emulated/0/Android/data/packagename/xxx.mp4"; // Absolute path of the video
localVideoMsgInfo.videoDuration = 100; // Required: Video duration in seconds.
messageInfoList.add(localVideoMsgInfo);
ZIMMultipleMessage zimMultipleMessage = new ZIMMultipleMessage();
zimMultipleMessage.setMessageInfoList(messageInfoList);
// Advanced configuration for sending messages.
ZIMMessageSendConfig config = new ZIMMessageSendConfig();
// Message Priority
config.priority = ZIMMessagePriority.LOW;
ZIMConversationType type = ZIMConversationType.Peer;
zim.sendMessage(zimMultipleMessage, userID, type, config, new ZIMMessageSentFullCallback() {
@Override
public void onMessageAttached(ZIMMessage zimMessage) {
// Developers can use this callback to monitor whether a message is ready to be sent. Only messages that pass the local basic parameter validation will trigger this callback; otherwise, an error will be returned through the onMessageSent callback.
}
@Override
public void onMessageSent(ZIMMessage zimMessage, ZIMError error) {
// Developers can use this callback to monitor whether the message was sent successfully.
}
@Override
public void onMultipleMediaUploadingProgress(
ZIMMultipleMessage message,
long currentFileSize, // Total size of uploaded files in bytes (B). For example, if 20,971,520 Byte has been uploaded, this value will be 20,971,520.
long totalFileSize, // Total file size in bytes (B). For example, if the total file size is 104,857,600 Byte, this value will be 104,857,600.
int messageInfoIndex, // The index of the currently uploading file in the messageInfoList array when this callback is received.
long currentIndexFileSize, // The uploaded size of the currently uploading file in bytes (B) when this callback is received.
long totalIndexFileSize, // The size of the currently uploading file when this callback is received.
) {
// You can display the upload progress here on the UI.
// Developers can use this callback to monitor the upload progress of multimedia files.
// Total file upload progress: currentFileSize / totalFileSize.
// In the above example, the total file upload progress is: 20,971,520 / 104,857,600 = 20%.
// When this callback is received, the upload progress of the currently uploading file is: currentIndexFileSize / totalIndexFileSize.
}
});
1
// Send a multi-item message in a one-to-one conversation
NSString *toUserID = @"toUserID";
// The item list of multi-item message can contain a maximum of 20 items.
NSMutableArray<ZIMMessageLiteInfo *> *messageInfoList = [NSMutableArray array];
// Text
ZIMTextMessageLiteInfo *textMsgInfo = [[ZIMTextMessageLiteInfo alloc] init];
textMsgInfo.message = @"Message content";
[messageInfoList addObject:textMsgInfo];
// Custom message: Only 1 allowed.
ZIMCustomMessageLiteInfo *customMsgInfo = [[ZIMCustomMessageLiteInfo alloc] init];
customMsgInfo.message = @"Message content";
customMsgInfo.searchedContent = @"Searched content";
customMsgInfo.subType = 100;
[messageInfoList addObject:customMsgInfo];
// Image: Only 10 allowed.
// Online image
ZIMImageMessageLiteInfo *imageMsgInfo = [[ZIMImageMessageLiteInfo alloc] init];
imageMsgInfo.fileDownloadUrl = @"https://xxxx.jpeg"; // Original Image
imageMsgInfo.thumbnailDownloadUrl = @"https://xxxx-thumbnail.jpeg"; // Thumbnail
imageMsgInfo.largeImageDownloadUrl = @"https://xxxx-large.jpeg"; // Large
[messageInfoList addObject:imageMsgInfo];
// Local
ZIMImageMessageLiteInfo *localImageMsgInfo = [[ZIMImageMessageLiteInfo alloc] init];
localImageMsgInfo.fileLocalPath = @"/private/var/mobile/Containers/Data/Application/xxx.jpg"; // Absolute path of the image
[messageInfoList addObject:localImageMsgInfo];
// File: Only 1 allowed.
ZIMFileMessageLiteInfo *localFileMsgInfo = [[ZIMFileMessageLiteInfo alloc] init];
localFileMsgInfo.fileLocalPath = @"/private/var/mobile/Containers/Data/Application/xxx.zip"; // Absolute path of the file
[messageInfoList addObject:localFileMsgInfo];
// Audio: Only 1 allowed.
ZIMAudioMessageLiteInfo *localAudioMsgInfo = [[ZIMAudioMessageLiteInfo alloc] init];
localAudioMsgInfo.fileLocalPath = @"/private/var/mobile/Containers/Data/Application/xxx.mp3"; // Absolute path of the audio
localAudioMsgInfo.audioDuration = 100; // Required: Audio duration in seconds.
[messageInfoList addObject:localAudioMsgInfo];
// Video: Only 1 allowed.
ZIMVideoMessageLiteInfo *localVideoMsgInfo = [[ZIMVideoMessageLiteInfo alloc] init];
localVideoMsgInfo.fileLocalPath = @"/private/var/mobile/Containers/Data/Application/xxx.mp4"; // Absolute path of the video
localVideoMsgInfo.videoDuration = 100; // Required: Video duration in seconds.
[messageInfoList addObject:localVideoMsgInfo];
ZIMMultipleMessage * multipleMessage = [[ZIMMultipleMessage alloc] init];
multipleMessage.messageInfoList = messageInfoList;
ZIMMessageSendNotification *notification = [[ZIMMessageSendNotification alloc] init];
notification.onMessageAttached = ^(ZIMMessage * _Nonnull message) {
// Developers can use this callback to execute business logic before sending the message.
};
notification.onMultipleMediaUploadingProgress = ^(
ZIMMultipleMessage * _Nonnull message,
unsigned long long currentFileSize, // Total size of uploaded files in bytes (B). For example, if 20,971,520 Byte has been uploaded, this value will be 20,971,520.
unsigned long long totalFileSize, // Total file size in bytes (B). For example, if the total file size is 104,857,600 Byte, this value will be 104,857,600.
unsigned int messageInfoIndex, // The index of the currently uploading file in the messageInfoList array when this callback is received.
unsigned long long currentIndexFileSize, // The uploaded size of the currently uploading file in bytes (B) when this callback is received.
unsigned long long totalIndexFileSize // The size of the currently uploading file when this callback is received.
) {
// Developers can use this callback to monitor the upload progress of multimedia files.
// Total file upload progress: currentFileSize / totalFileSize.
// In the above example, the total file upload progress is: 20,971,520 / 104,857,600 = 20%.
// When this callback is received, the upload progress of the currently uploading file is: 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)) {
// Developers can use this callback to monitor whether the message was sent successfully.
}];
1
// Send a multi-item message in a one-to-one conversation
auto multiMsg = std::make_shared<ZIMMultipleMessage>();
// The item list of multi-item message can contain a maximum of 20 items.
std::vector<ZIMMessageLiteInfo*> messageInfoList;
// Text
auto textMsgInfo = std::make_shared<ZIMTextMessageLiteInfo>();
textMsgInfo->message = "Message Content";
multiMsg->messageInfoList.push_back(textMsgInfo);
// Custom message: Only 1 allowed.
auto customMsgInfo = std::make_shared<ZIMCustomMessageLiteInfo>();
customMsgInfo->message = "Message content";
customMsgInfo->searchedContent = "Searched Content";
customMsgInfo->subType = 100;
multiMsg->messageInfoList.push_back(customMsgInfo);
// Image: Only 10 allowed.
// Online image
auto imageMsgInfo = std::make_shared<ZIMImageMessageLiteInfo>();
imageMsgInfo->fileDownloadUrl = "https://xxxx.jpeg"; // Original Image
imageMsgInfo->thumbnailDownloadUrl = "https://xxxx-thumbnail.jpeg"; // Thumbnail
imageMsgInfo->largeImageDownloadUrl = "https://xxxx-large.jpeg";// Large Image
multiMsg->messageInfoList.push_back(imageMsgInfo);
// Local Image
auto localImageMsgInfo = std::make_shared<ZIMImageMessageLiteInfo>();
localImageMsgInfo->fileLocalPath = "D:\\files\\xxx.jpg"; // Absolute path of the image
multiMsg->messageInfoList.push_back(localImageMsgInfo);
// File: Only 1 allowed.
auto localFileMsgInfo = std::make_shared<ZIMFileMessageLiteInfo>();
localFileMsgInfo->fileLocalPath = "D:\\files\\xxx.zip"; // Absolute path of the file
multiMsg->messageInfoList.push_back(localFileMsgInfo);
// Audio: Only 1 allowed.
auto localAudioMsgInfo = std::make_shared<ZIMAudioMessageLiteInfo>();
localAudioMsgInfo->fileLocalPath = "D:\\files\\xxx.mp3"; // Absolute path of the audio
localAudioMsgInfo->audioDuration = 100; // Required: Audio duration in seconds.
multiMsg->messageInfoList.push_back(localAudioMsgInfo);
// Video: Only 1 allowed.
auto localVideoMsgInfo = std::make_shared<ZIMVideoMessageLiteInfo>();
localVideoMsgInfo->fileLocalPath = "D:\\files\\xxx.mp4"; // Absolute path of the file
localVideoMsgInfo->videoDuration = 100; // Required: Video duration in seconds.
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) {
// Developers can listen to this callback to execute logic before sending the message.
},
[=](const std::shared_ptr<zim::ZIMMultipleMessage> &message,
unsigned long long currentFileSize, // Total size of uploaded files in bytes (B). For example, if 20,971,520 Byte has been uploaded, this value will be 20,971,520.
unsigned long long totalFileSize, // Total file size in bytes (B). For example, if the total file size is 104,857,600 Byte, this value will be 104,857,600.
unsigned int messageInfoIndex, // The index of the currently uploading file in the messageInfoList array when this callback is received.
unsigned long long currentIndexFileSize, // The uploaded size of the currently uploading file in bytes (B) when this callback is received.
unsigned long long totalIndexFileSize // The size of the currently uploading file when this callback is received.
) {
// The upload callback for sending multi-item messages will not be triggered if there are no media items in the multi-item message.
});
zim_->sendMessage(multiMsg, "toConversationID", type, sendConfig, notification,
[=](const std::shared_ptr<zim::ZIMMessage> &message,
const zim::ZIMError &errorInfo) {
// The result callback
});
1
// The method to select a local file
var file = null; // The file object to be uploaded
var input = document.createElement('input');
input.type = 'file';
input.onchange = function() {
file = this.files[0];
}
1
// The method to select a local file
var file = ''; // Absolute path of the file to be uploaded
1
// Send a multi-item message in a one-to-one conversation
// Pass in the userID of the message receiver
var toConversationID = "xxxx";
// Advanced configuration for sending messages.
var conversationType = 0; // 0: One-to-one; 1: Room; 2: Group
var config = {
priority: 1, // Message Priority, 1: low (default), 2: medium, 3: high
};
var notification = {
onMessageAttached: function(message) {
//
},
onMultipleMediaUploadingProgress: function(
message,
currentFileSize, // Total size of uploaded files in bytes (B). For example, if 20,971,520 Byte has been uploaded, this value will be 20,971,520.
totalFileSize, // Total file size in bytes (B). For example, if the total file size is 104,857,600 Byte, this value will be 104,857,600.
messageInfoIndex, // The index of the currently uploading file in the messageInfoList array when this callback is received.
currentIndexFileSize, // The uploaded size of the currently uploading file in bytes (B) when this callback is received.
totalIndexFileSize // The size of the currently uploading file when this callback is received.
) {
// You can display the upload progress here on the UI.
// Developers can use this callback to monitor the upload progress of multimedia files.
// Total file upload progress: currentFileSize / totalFileSize.
// In the above example, the total file upload progress is: 20,971,520 / 104,857,600 = 20%.
// When this callback is received, the upload progress of the currently uploading file is: currentIndexFileSize / totalIndexFileSize.
}
};
var zimMultipleMessage = {
type: 10,
// The item list of multi-item message can contain a maximum of 20 items.
messageInfoList: [
// Text
{
type: 1,
message: 'xxxx',
},
// Custom message
{
type: 200,
message: 'xxxx',
subType: 100,
searchedContent: 'xxxx'
},
// Image: Only 10 allowed.
// Online image
{
type: 11,
fileDownloadUrl: 'https://xxxx.jpeg', // Original Image
thumbnailDownloadUrl: 'https://xxxx-thumbnail.jpeg', // Thumbnail
largeImageDownloadUrl: 'https://xxxx-large.jpeg', // Large Image
},
// Local Image
{
type: 11,
fileLocalPath: file, // File to be uploaded
},
// File: Only 1 allowed.
{
type: 12,
fileLocalPath: file, // File to be uploaded
},
// Audio: Only 1 allowed.
{
type: 13,
fileLocalPath: file, // File to be uploaded
audioDuration: 100, // Required: Audio duration in seconds.
},
// Video: Only 1 allowed.
{
type: 14,
fileLocalPath: file, // File to be uploaded
videoDuration: 100, // Required: Video duration in seconds.
}
]
};
zim.sendMessage(zimMultipleMessage, toConversationID, conversationType, config, notification)
.then(function ({ message }) {
// Sent successfully
})
.catch(function (err) {
// Failed to send
});
1
// Send a multi-item message in a one-to-one conversation
String userID = "xxxx";
// The item list of multi-item message can contain a maximum of 20 items.
List<ZIMMessageLiteInfo> messageInfoList = [];
// Text
ZIMTextMessageLiteInfo textMsgInfo = ZIMTextMessageLiteInfo();
textMsgInfo.message = "Message content";
messageInfoList.add(textMsgInfo);
// Custom message: Only 1 allowed.
ZIMCustomMessageLiteInfo customMsgInfo = ZIMCustomMessageLiteInfo();
customMsgInfo.message = "Message content";
customMsgInfo.searchedContent = "S er che d";
customMsgInfo.subType = 100;
messageInfoList.add(customMsgInfo);
// Image: Only 10 allowed.
// Online
ZIMImageMessageLiteInfo imageMsgInfo = ZIMImageMessageLiteInfo();
imageMsgInfo.fileDownloadUrl = "https://xxxx.jpeg"; // Original Image
imageMsgInfo.thumbnailDownloadUrl = "https://xxxx-thumbnail.jpeg"; // Thumbnail
imageMsgInfo.largeImageDownloadUrl = "https://xxxx-large.jpeg"; // Large Image
messageInfoList.add(imageMsgInfo);
// Local Image
ZIMImageMessageLiteInfo localImageMsgInfo = ZIMImageMessageLiteInfo();
localImageMsgInfo.fileLocalPath = "/path/xxx.jpg"; // Absolute path of the image
messageInfoList.add(localImageMsgInfo);
// File: Only 1 allowed.
ZIMImageMessageLiteInfo localFileMsgInfo = ZIMFileMessageLiteInfo();
localFileMsgInfo.fileLocalPath = "/path/xxx.zip"; // Absolute path of the file
messageInfoList.add(localFileMsgInfo);
// Audio: Only 1 allowed.
ZIMAudioMessageLiteInfo localAudioMsgInfo = ZIMAudioMessageLiteInfo();
localAudioMsgInfo.fileLocalPath = "/path/xxx.mp3"; //Absolute path of the audio
localAudioMsgInfo.audioDuration = 100; // Required: Playback duration in seconds.
messageInfoList.add(localAudioMsgInfo);
// Video: Only 1 allowed.
ZIMVideoMessageLiteInfo localVideoMsgInfo = ZIMVideoMessageLiteInfo();
localVideoMsgInfo.fileLocalPath = "/path/xxx.mp4"; // Absolute path of the video
localVideoMsgInfo.videoDuration = 100; // Required: Playback duration in seconds.
messageInfoList.add(localVideoMsgInfo);
ZIMMultipleMessage zimMultipleMessage = ZIMMultipleMessage(messageInfos);
zimMultipleMessage.messageInfoList = messageInfoList;
ZIMMessageSendNotification notification = ZIMMessageSendNotification(
onMessageAttached: (message){
// Developers can use this callback to execute business logic before sending the message.
},
onMultipleMediaUploadingProgress: (
message,
currentFileSize, // Total size of uploaded files in bytes (B). For example, if 20,971,520 Byte has been uploaded, this value will be 20,971,520.
totalFileSize, // Total file size in bytes (B). For example, if the total file size is 104,857,600 Byte, this value will be 104,857,600.
messageInfoIndex, // The index of the currently uploading file in the messageInfoList array when this callback is received.
currentIndexFileSize, // The uploaded size of the currently uploading file in bytes (B) when this callback is received.
totalIndexFileSize // The size of the currently uploading file when this callback is received.
){
// Developers can use this callback to monitor the upload progress of multimedia files.
// Total file upload progress: currentFileSize / totalFileSize.
// In the above example, the total file upload progress is: 20,971,520 / 104,857,600 = 20%.
// When this callback is received, the upload progress of the currently uploading file is: currentIndexFileSize / totalIndexFileSize.
}
);
// Advanced configuration for sending messages.
ZIMMessageSendConfig config = ZIMMessageSendConfig();
// Message Priority
config.priority = ZIMMessagePriority.low;
ZIMConversationType type = ZIMConversationType.Peer;
ZIM.getInstance().sendMessage(zimMultipleMessage, userID, type, config, notification).then((value) {
// Sent successfully
}).catchError((onError){
// Failed to send
});
1
Receive multi-item messages
接收组合消息的回调接口与接收普通消息的回调接口一致,请参考 收发普通消息 - 接收消息 了解具体接口。
The callback interface for receiving multi-item messages is the same as the callback interface for receiving regular messages. Please refer to Send & Receive messages - Receive messages for details on the specific interface.
The following is an example code for receiving multi-item messages in a one-to-one conversation:
// // User receives multi-item message in a one-to-one conversation
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) {
// This indicates that a multi-item message has been received.
ZIMMultipleMessage zimMultipleMessage = (ZIMMultipleMessage) zimMessage;
}
}
}
});
1
// // User receives multi-item message in a one-to-one conversation
- (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){
// This indicates that a multi-item message has been received.
}
}
}
1
// // User receives multi-item message in a one-to-one conversation
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
// // User receives multi-item message in a one-to-one conversation
zim.on('peerMessageReceived', function (zim, { messageList, info, fromConversationID }) {
console.log(messageList, fromConversationID);
messageList.forEach(function (msg) {
// This indicates that a multi-item message has been received.
if (msg.type == 10) {
msg.messageInfoList.forEach(function (info) {
// Display UI based on the message type.
console.log('The item type:' + info.type);
}
}
})
});
1
// // User receives multi-item message in a one-to-one conversation
ZIMEventHandler.onPeerMessageReceived = (zim, messageList, info, fromUserID) {
for (ZIMMessage message in messageList) {
if(message is ZIMMultipleMessage){
}
}
};
1
Send/Receive @ messages
An "@" message refers to a message that contains the content of "@ + user". When a user is mentioned with an "@" message, they receive a strong notification.
The "@" message is not a message type itself. A message can be both a text message or another type of message, and it can also be an "@" message.
Send @ messages
When calling sendMessage to send a message, you can use the following methods (can be used simultaneously) to mark a message as an "@" message:
- mentionedUserIDs: Notifies specific users (including users outside of the conversation) to view the message. The length of the userID list passed in should be up to 50. If you need to increase this limit, please contact the ZEGOCLOUD technical support team.
- isMentionAll: Notifies all other users within the conversation to view the message.
Only ZIM SDK version 2.14.0 and above supports sending messages with @ information.
// The following is a sample code for a user to send an @ message in a single conversation:
// Create a list of users to be mentioned
ArrayList<String> mentionArrayList = new ArrayList<>();
// Add a user (the user does not need to be in the current conversation)
mentionArrayList.add("userId1");
mentionArrayList.add("userId2");
// message can be any type of message
// Call the interface to remind users in the list to view messages
message.setMentionedUserIDs(mentionArrayList);
// Remind all other users in the conversation to view the message
boolean isMentionAll = true;
message.setIsMentionAll(isMentionAll);
ZIMMessageSendConfig config = new ZIMMessageSendConfig();
// Set message priority
config.priority = ZIMMessagePriority.LOW;
// Whether to forcefully push the notification to the alerted user (regardless of whether the other party has enabled Do Not Disturb mode), the default is fasle;
config.isNotifyMentionedUsers = true;
// Take sending a one-to-one conversation message as an example
ZIMConversationType type = ZIMConversationType.Peer;
zim.sendMessage(message, "conv_id", type, config, new ZIMMessageSentFullCallback() {
@Override
public void onMessageAttached(ZIMMessage zimMessage) {
// You can use this callback to monitor whether the message is ready to be sent. This callback will be thrown only if the message passes the local basic parameter verification, otherwise an error will be thrown through the onMessageSent callback.
}
@Override
public void onMessageSent(ZIMMessage zimMessage, ZIMError error) {
// Developers can use this callback to monitor whether the message is sent successfully.
}
}];
1
// The following is a sample code for a user to send an @ message in a single conversation:
// Create a list of users to be mentioned
NSMutableArray<NSString *> *mentionArrayList = [[NSMutableArray alloc] init];
// Add a user (the user does not need to be in the current conversation)
[mentionArrayList addObject:@"userId1"];
[mentionArrayList addObject:@"userId2"];
// message can be any type of message
// Call the interface to remind users in the list to view messages
[message mentionedUserIDs:mentionArrayList];
// Remind all other users in the conversation to view the message
BOOL isMentionAll = YES;
[message isMentionAll:isMentionAll];
ZIMMessageSendConfig *config = [[ZIMMessageSendConfig alloc] init];
// Whether to forcefully push the notification to the alerted user (regardless of whether the other party has enabled Do Not Disturb mode), the default is NO;
config.isNotifyMentionedUsers = YES;
// Take sending one-to-one conversation messages as an example
ZIMConversationType type = ZIMConversationTypePeer;
[zim sendMessage:message convId:@"conv_id" type:type config:config callback:^(ZIMMessage *zimMessage, ZIMError *error) {
if (error) {
// Developers can use this callback to monitor whether the message is sent successfully.
}
}];
1
// Create a list of users to be mentioned
std::vector<std::string> mentionArrayList;
// Add a user (the user does not need to be in the current conversation)
nimentionArrayList.push_back("userId1");
mentionArrayList.push_back("userId2");
// message can be of any type
message->mentionedUserIDs = mentionArrayList;
// Remind all other users in the conversation to read the message.
bool isMentionAll = true;
message->isMentionAll = true;
ZIMMessageSendConfig config;
// Set the message priority
config.priority = ZIMMessagePriority::LOW;
// Whether to forcefully push the notification to the alerted user (regardless of whether the other party has enabled Do Not Disturb mode), the default is false;
config.isNotifyMentionedUsers = true;
// Taking sending a one-to-one message as an example.
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) {
// Developers can use this callback to monitor whether a message is preparing to be sent. Only messages that pass the local basic parameter validation will trigger this callback; otherwise, an error will be returned through the onMessageSent callback.
}
}),
[=](std::shared_ptr<zim::ZIMMessage> message, zim::ZIMError errorInfo) {
// Developers can use this callback to monitor whether the message was sent successfully.
if (errorInfo.code == zim::ZIMErrorCode::ZIM_ERROR_CODE_SUCCESS) {
}
});
1
// Below is an example code for a user sending an @ message (text message) in a one-to-one conversation:
var toConversationID = ''; // the userID of message receiver
var conversationType = 0; // Conversation type, with values: One-to-one: 0, Room: 1, Group: 2.
var config = {
priority: 1, // Set message priority, with values: Low: 1 (default), Medium: 2, High: 3.
};
var notification = {
onMessageAttached: function(message) {
//
}
}
var messageTextObj = {
type: 1,
message: 'xxxx',
isMentionAll: true, // Remind all other users in the conversation to check the message.
mentionedUserIDs: ["userId1", "userId2"], // Remind users in the list to check the message.
};
zim.sendMessage(messageTextObj, toConversationID, conversationType, config, notification)
.then(function ({ message }) {
// Sent successfully
})
.catch(function (err) {
// Failed to send
});
1
// Below is an example code for a user sending an @ message in a one-to-one conversation:
try {
// The list of users to be mentioned
List<String> memtionList = ['userID1', 'userID2'];
// The message can be of any type.
// Call the API to remind users in the list to check the message.
message.mentionedUserIDs(memtionList);
// Remind all other users in the conversation to check the message.
bool isMentionAll = true;
message.isMentionAll(isMentionAll);
ZIMMessageSendConfig config = ZIMMessageSendConfig();
//Set message priority.
config.priority = ZIMMessagePriority.low;
// Whether to forcefully push the notification to the alerted user (regardless of whether the other party has enabled Do Not Disturb mode), the default is fasle;
config.isNotifyMentionedUsers = true;
// Taking sending a one-to-one message as an example.
ZIMConversationType type = ZIMConversationType.peer;
ZIMMessageSentResult result = await ZIM.getInstance()!.sendMessage(message, 'conv_id', type, config);
} on PlatformException catch (onError){
onError.code;// Handle error based on the error code docs.
onError.message;// Error message
}
1
Receive @ messages
The callback interface for receiving @ messages is the same as the callback interface for receiving regular messages. Please refer to Send & Receive messages - Receive messages for details on the specific interface.
After receiving a message, developers can implement corresponding functionalities based on their business logic, such as highlighting, etc.
- Only ZIM SDK versions 2.14.0 and above support receiving and viewing the content of @ messages.
- If the SDK version on the receiving end is between [2.0.0, 2.14.0), the received messages and conversations will not contain @ information.
- If the SDK version on the receiving end is version 1.x.x, @ messages cannot be received.
Receive mentionedInfoList
After users within a conversation are mentioned, developers can passively or actively retrieve mentionedInfoList.
mentionedInfoList contains the corresponding message ID, sender userID, and the type of ZIMMessageMentionedType.Developers can use this information to implement various business logics, such as marking conversations.
Passive retrieval
When a user is mentioned, the onConversationChanged will be received, allowing you to retrieve the latest mentionedInfoListfor the current ZIMConversation.
@Override
public void onConversationChanged(
ZIM zim, ArrayList<ZIMConversationChangeInfo> conversationChangeInfoList) {
// conversationChangeInfoList
// You can get the mentionInfoList in the conversation that received the reminder
}
1
- (void)zim:(ZIM *)zim
conversationChanged:(NSArray<ZIMConversationChangeInfo *> *)conversationChangeInfoList {
// Retrieve mentionInfoList from the conversationChangeInfoList of the mentioned conversation
}
1
void onConversationChanged(
ZIM * /*zim*/,
const std::vector<ZIMConversationChangeInfo> & /*conversationChangeInfoList*/) {
// Retrieve mentionInfoList from the conversationChangeInfoList of the mentioned conversation
}
1
zim.on('conversationChanged', function (zim, { info }) {
console.log(info.mentionInfoList);
});
1
ZIMEventHandler.onConversationChanged = (ZIM zim, List<ZIMConversationChangeInfo> conversationChangeInfoList){
// Retrieve mentionInfoList from the conversationChangeInfoList of the mentioned conversation
};
1
Active retrieval
If you use queryConversationList or queryConversation o actively fetch conversations, you can also retrieve the mentionedInfoList within the conversation. Refer to the following example code:
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
Clearing mentionedInfoList of a conversation
After receiving @ messages, users need to clear the mentionedInfoList of the conversation to stop receiving notifications.
The interface for clearing the mentionedInfoList is the same as clearing the unread message count of a conversation:
Get the list of mentioned users
All users within the conversation can call mentionedUserIDs to obtain the specific list of mentioned users.
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
Confirm whether it is a reminder for all members
All users within the conversation can use the isMentionAll parameter of ZIMMessage to determine whether it is a reminder for all members.
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
Send/Receive broadcast messages
ZIM allows you to send messages to all online users of your app from the server side, and the targeted users will receive the messages through the client side.
Send messages to all users from the server side
Please refer to the server-side API documentation Push message to all user to learn how to send messages to all users from the server side.
Receive broadcast messages sent from the server side
- Only ZIM SDK versions 2.10.0 and above support receiving and viewing the content of broadcast messages sent from the server side.
- If the SDK version on the receiving end is between [2.0.0, 2.10.0), broadcast messages sent from the server side cannot be received. If you need to access this message, please upgrade the SDK to version 2.10.0 or above.
Through the onBroadcastMessageReceived callback, you can receive push messages from all members.
Sample code:
// User receives broadcast messages
public void onBroadcastMessageReceived(ZIM zim, ZIMMessage message) {
super.onBroadcastMessageReceived(zim, message);
// Receive broadcast messages from all members
}
1
// User receives broadcast messages
- (void)zim:(ZIM *)zim broadcastMessageReceived:(ZIMMessage *)message {
// Receive broadcast messages from all members
}
1
// User receives broadcast messages
virtual void onBroadcastMessageReceived(ZIM * /*zim*/, const std::shared_ptr<ZIMMessage> & /*message*/) {}
1
// User receives broadcast messages
zim.on('broadcastMessageReceived', function (zim, { message }) {
console.log(message);
});
1
// User receives broadcast messages
ZIMEventHandler.onBroadcastMessageReceived(zim, message){}
1
Forward message
The ZIM SDK supports forwarding messages in one of the following ways:
- Combining messages and forwarding the combined message.
- Forwarding messages one by one.
For more information, see Forward messages.
Receive Tips message
ZIM SDK supports converting user operations within a conversation into Tips messages. When a related operation occurs, ZIM SDK will send a Tips message to the session to notify. For details, please refer to Receive tip messages.
Listen for the message status
On a weak network condition, this may happen: the ZIM SDK doesn't receive the response from the server for some reason (e.g., packet loss), while the message is successfully sent. In this case, the ZIM SDK considers the message sending failed due to the reply timeout, but the message is actually sent successfully, which results in message status confusion.
To solve this and Clarify the message status, the SDK 2.6.0 or later now allows you to listen for the onMessageSentStatusChanged callback to receive the changes of the message status.
And we now have three different message statuses: Sending, Success, and Failed.
You can know whether your message is sent successfully by the status, and implement your event handling logic as needed.
// Listen for the message status
zim.setEventHandler(new ZIMEventHandler() {
@Override
public void onMessageSentStatusChanged(
ZIM zim, ArrayList<ZIMMessageSentStatusChangeInfo> messageSentStatusChangeInfoList) {
// You can listen for the callback on the changes of message status here.
}
});
1
// Listen for the message status.
- (void)zim:(ZIM *)zim messageSentStatusChanged:
(NSArray<ZIMMessageSentStatusChangeInfo *> *)messageSentStatusChangeInfoList {
// You can listen for the callback on the changes of message status here.
}
1
// Listen for the message status.
void onMessageSentStatusChanged(zim::ZIM *zim, const std::vector<ZIMMessageSentStatusChangeInfo> &messageSentStatusChangeInfoList{
// You can listen for the callback on the changes of message status here.
}
1
// Listen for the message status.
zim.on('messageSentStatusChanged', function (zim, { infos }) {
infos.forEach( function (info) {
console.warn(info.message, info.status);
});
});
1
// Listen for the message status.
ZIMEventHandler.onMessageSentStatusChanged = (
ZIM zim, List<ZIMMessageSentStatusChangeInfo> messageSentStatusChangedInfoList){
for(ZIMMessageSentStatusChangeInfo info in messageSentStatusChangedInfoList){
log(info.status.toString());
log(info.message!.messageID.toString());
}
};
1