Messaging
Update time: 2024/03/07 11:09:07
The SDK for Flutter can send and receive multiple types of messages, helping you implement messaging for diverse use cases. The SDK provides the MessageBuilder
class and the MessageService
class that create messages of different types, send and receive messages, and listen for messaging events. The structure of a message defined in the SDK is NIMMessage
(does not support inheritance and extension). Different message types are defined in NIMMessageType
. The sendMessage
method is used to send different types of messages. Messages sent using this method for P2P chats or group chats are identified by the NIMSessionType
parameter.
This document introduces how a message works in different sessions, prerequisites and how to create and send a message.
- Messaging in chat rooms and Qchat channels must be configured separately. For specific workflows to implement messaging, see Messaging in chat room and Messaging in Qchat.
- The sequence diagrams in this document may display abnormally due to network problems. To fix the displayed problem, refresh the current page.
How it works
After your app integrates the NIM SDK and completes the SDK initialization, the message sending and receiving process is shown in the diagram below (except for local tip messages and notification messages).
The process in the figure above contains the following 3 steps:
- Integrate accounts and login.
- Register IM accounts with user account of your app, Register IM accounts (accid).
- CommsEase IM server returns the token to the app server.
- A client logs in to the app server.
- App server returns the token to the client.
- The client logs in to IM server using the token.
- User A sends a message to IM server.
- IM server forwards messages to other users:
- For messages in P2P chats, IM server delivers the message to User B.
- For messages in group chats, IM server delivers the message to all users in the group.
The above figure only uses static token login as an example to show the message sending and receiving process. IM also supports login authentication using dynamic tokens and webhooks. For more information, see Login authentication.
Prerequisites
Before sending messages, make sure:
- SDK is initialized.
- You have created IM accounts
- You have created a group for messaging in group chats.
- You have understood the [limits] of each message type (https://doc.yunxin.163.com/messaging/docs/Tg1MjcyMjg?platform=flutter#message-types).
API rate limit
The method of sending a message (sendMessage
) can be called up to 300 times per minute by default.
Messaging
Send text messages.
sequenceDiagram
%%{init:
{
"theme": "default",
"themeVariables": {
"mainBkg" : "#9DC3E6",
"actorBkg" : "#337EFF",
"labelBoxBorderColor" : "#7FBC00",
"labelBoxBkgColor" : "#7FBC00",
"fontFamily": "Inter",
"fontSize": "10px"
}
}
}%%
participant Sender
participant NIM
participant Receiver
note over NIM: Initialization of SDK by both participants
Sender ->> NIM: Listen for message status change <br>(onMessageStatus)
Sender ->> NIM: Log in
Receiver ->> NIM: Listen for message status change & message reception <br>(onMessageStatus & onMessage)
Receiver ->> NIM: Log in
Sender ->> NIM: Create text message <br>(createTextMessage)
Sender ->> NIM: Send message <br>(sendMessage)
NIM -->> Receiver: NIMMessage
Procedure
-
The sender has registered the
onAudioRecordStatus
event stream to track changes of the message status.NimCore.instance.messageService.onMessageStatus.listen((NIMMessage message) { // 1. Determine whether it is your message based on the sessionId // 2. Change the message status in memory // 3. Refresh the interface });
-
The recipient has registered the
onMessage
andonAudioRecordStatus
event streams to track changes of the message receiving and message status.NimCore.instance.messageService.onMessage.listen((List<NIMMessage> list) { // Handle new messages. For the convenience of uploading and processing, the SDK ensures that the messages parameter come from the same chat object. });
-
The sender creates a message by calling the
createTextMessage
method.You can specify a text message of a P2P chat or group chat by setting the
sessionType
parameter. Make sure a group chat exists if you set the message for the group chat.Parameter Type Description sessionId
String The ID of a session. The sessionType
is used to determine the session type.- If the session is a P2P chat, the
sessionId
is the user’s IM account (accid
) - If the session is a group chat,
sessionId
is the group ID
sessionType
NIMSessionType
The session type. text
String The body of a text message. - If the session is a P2P chat, the
-
The sender sends the message by calling the
sendMessage
method.You can specify whether the message is stored on the server, added to the roaming messages or counted as unread messages by configuring
NIMCustomMessageConfig
. For specific configuration examples, see Message Configuration.
Sample code for creating and sending a text message:
// Test account String account = 'testAccount'; // P2P chat NIMSessionType sessionType = NIMSessionType.p2p; String text = 'this is an example'; // Create and send a text message. Future<NIMResult<NIMMessage>> result = MessageBuilder.createTextMessage( sessionId: account, sessionType: sessionType, text: text) .then((value) => value.isSuccess ? NimCore.instance.messageService .sendMessage(message: value.data!, resend: false) : Future.value(value));
-
The recipient receives the text message returned by the
onMessage
callback.
Send and receive multimedia messages.
Multimedia messages include image, audio, video, and file messages.
NIM SDK allows users to make high-definition voice recordings and playbacks for processing audio messages. For more information, see Audio message processing.
API sequence diagram
sequenceDiagram
%%{init:
{
"theme": "default",
"themeVariables": {
"mainBkg" : "#9DC3E6",
"actorBkg" : "#337EFF",
"labelBoxBorderColor" : "#7FBC00",
"labelBoxBkgColor" : "#7FBC00",
"fontFamily": "Inter",
"fontSize": "10px"
}
}
}%%
participant Sender
participant NIM
participant Receiver
note over NIM: Initialization of SDK by Both Parties
Sender ->> NIM: Listen for message status change<br>Listen for attachment upload/download progress<br>(onMessageStatus & onAttachmentProgress)
Sender ->> NIM: Log in
Receiver ->> NIM: Listen for message status change<br>Listen for message reception<br>Listen for attachment upload/download Progress<br>(onMessageStatus & onMessage & onAttachmentProgress)
Receiver ->> NIM: Log in
Sender ->> NIM: Create multimedia messages<br>(createAudio/Image/Video/FileMessage)
Sender ->> NIM: Send created message
Sender ->> NIM: Optional: cancel attachment upload<br>(cancelUploadAttachment)
NIM -->> Receiver: NIMMessage
Receiver ->> NIM: Optional: Manually download attachment<br>(downloadAttachment)
Procedure
-
The sender registers the following event flow.
- Register the
onMessageStatus
event stream to track the changes of the message statusNIMMessageStatus
and attachment status [NIMMessageAttachmentStatus
](https://doc.yunxin.163 .com/docs/interface/NIM_SDK/Latest/Flutter/nim_core/NIMMessageAttachmentStatus.html). - Resiter the
onAttachmentProgress
event stream to track the progress of uploading or downloading message attachment. Note: The event flow is not supported for web apps.
onMessageStatusNimCore.instance.messageService.onMessageStatus.listen((NIMMessage message) { // 1. Determine whether it is your message based on the sessionId // 2. Change the message status in memory // 3. Refresh the interface });
NIMMessageAttachmentStatusNimCore.instance.messageService.onAttachmentProgress.listen((NIMAttachmentProgress process) { // TODO updates the UI based on the attachment download/upload progress });
- Register the
-
Recipient registers the following event streams.
onMessage
used to track message receiving.onAttachmentProgress
used to track the transfer progress of uploading or downloading message attachments.
onMessageNimCore.instance.messageService.onMessage.listen((List<NIMMessage> list) { // Handle new messages. For the convenience of uploading and processing, the SDK ensures that the messages parameter come from the same chat object. });
onAttachmentProgressNimCore.instance.messageService.onAttachmentProgress.listen((NIMAttachmentProgress process) { // TODO updates the UI based on the attachment download/upload progress });
-
The sender create a multimedia message.
TypeMethodResources storage Image message createImageMessage
You can specify the expiration time of multimedia resources (image, audio, video, or file) for multimedia messages stored on the Netease Object Storage (Netease Object Storage, NOS) service. For more information, see [Multimedia Resource Storage](https://doc.yunxin.163.com/TM5MzM5Njk/docs/jIzNjg1MDU?platform =flutter). Audio message createAudioMesssage
Video message createVideoMessage
File message createFileMessage
The previous methods contain the following parameters:
Parameter Type Description sessionId
String The ID of a session. The sessionType
is used to determine the session type.- If the session is a P2P chat, the
sessionId
is the user’s IM account (accid
) - If the session is a group chat,
sessionId
is the group ID
sessionType
NIMSessionType
The session type. filePath
String The file path of a multimedia resource. An empty string can be used for web apps. - If the session is a P2P chat, the
-
The sender sends the message by calling the
sendMessage
method.- You can specify whether the message is stored on the server, added to the roaming messages or counted as unread messages by configuring
NIMCustomMessageConfig
. For specific configuration examples, see Message Configuration. - If you send an image message, video message or file message you can call
cancelUploadAttachment
method to cancel the upload of an attachment (image, video or file). If the resource is already uploaded, the operation fails. If uploading the resources is canceled, the delivery of the message with the attachment will fail. The message state becomesNIMMessageStatus.fail
, and the attachmentNIMMessageAttachmentStatus.cancel
. - If the same multimedia message needs to be sent multiple times, control the sequence and the rate to avoid delivery failures.
** Sample code for creating and sending a multimedia message:
Image message// Test account String account = 'testAccount'; // P2P chat NIMSessionType sessionType = NIMSessionType.p2p; // Keep the image in the corresponding directory File file = new File('filePath'); // Display the image name String displayName = 'this is a file'; // Base64 is required for web apps. Other platforms can ignore it. String base64 = 'this is base64'; // Send the image message. Future<NIMResult<NIMMessage>> result = MessageBuilder.createImageMessage( sessionId: account, sessionType: sessionType, filePath: file.path, fileSize: file.lengthSync(), displayName: displayName, base64: base64, nosScene: NIMNosScene.defaultIm) .then((value) => value.isSuccess ? NimCore.instance.messageService .sendMessage(message: value.data!, resend: false) : Future.value(value));
Audio message// Test account String account = 'testAccount'; // P2P chat NIMSessionType sessionType = NIMSessionType.p2p; // Keep the audio file in the corresponding directory File file = new File('filePath'); // Display the audio name String displayName = 'this is a file'; // Base64 is required for web apps. Other platforms can ignore it. String base64 = 'this is base64'; // Send the audio message Future<NIMResult<NIMMessage>> result = MessageBuilder.createAudioMessage( sessionId: account, sessionType: sessionType, filePath: file.path, fileSize: file.lengthSync(), base64: base64, duration: 2000, displayName: displayName, nosScene: NIMNosScene.defaultIm) .then((value) => value.isSuccess ? NimCore.instance.messageService .sendMessage(message: value.data!, resend: false) : Future.value(value));
Video message// Test account String account = 'testAccount'; // P2P chat NIMSessionType sessionType = NIMSessionType.p2p; // Keep the video file in the corresponding directory File file = new File('filePath'); // Display the video name String displayName = 'this is a file'; // Base64 is required for web apps. Other platforms can ignore it. String base64 = 'this is base64'; // Send the message Future<NIMResult<NIMMessage>> result = MessageBuilder.createVideoMessage( sessionId: account, sessionType: sessionType, filePath: file.path, fileSize: file.lengthSync(), base64: base64, duration: 2000, width: 1080, height: 720, displayName: displayName, nosScene: NIMNosScene.defaultIm) .then((value) => value.isSuccess ? NimCore.instance.messageService .sendMessage(message: value.data!, resend: false) : Future.value(value));
File message// Test account String account = 'testAccount'; // P2P chat NIMSessionType sessionType = NIMSessionType.p2p; // Keep the file in the corresponding directory File file = new File('filePath'); // Display the file name String displayName = 'this is a file'; // Base64 is required for web apps. Other platforms can ignore it. String base64 = 'this is base64'; // Send the message Future<NIMResult<NIMMessage>> result = MessageBuilder.createFileMessage( sessionId: account, sessionType: sessionType, filePath: file.path, fileSize: file.lengthSync(), base64: base64, displayName: displayName, nosScene: NIMNosScene.defaultIm) .then((value) => value.isSuccess ? NimCore.instance.messageService .sendMessage(message: value.data!, resend: false) : Future.value(value));
- You can specify whether the message is stored on the server, added to the roaming messages or counted as unread messages by configuring
-
The recipient receives the multimedia message returned by the callback of the
onMessage
event stream.Multimedia resources are automatically downloaded by default. For the default download strategies of different types of messages, see the table below:
Type Download strategy Imageor video message The SDK automatically downloads thumbnail and cover image when receiving a message. Audio message The SDK automatically downloads the source audio when receiving a message. File message The SDK DOES NOT download the source file by default. -
To download the source file of a file message, call the
downloadAttachment
method to download the file manually. If the resources of multimedia messages fail to be downloaded automatically, this method can also be called to manually download the resources.Paraters of the downloadAttachment method
ParameterTypeDescription message
NIMMessage
The message that hold the attachment. thumb
bool Whether only thumbnails are downloaded. If the value is set to true, only the thumbnail will be downloaded. The parameter is valid only for image and video message. The parameter is not supported on Windows and macOS. -
If you want to choose the proper time to download the resources, set the initialization configuration parameter
NIMSDKOptions.enablePreloadMessageAttachment
tofalse
, disable the default resource download strategy, and calldownloadAttachment
method.
An example of manually downloading multimedia resources is as follows:
NimCore.instance.messageService.downloadAttachment(message, true);
-
-
The recipient can get the message attachment using
NIMMessageAttachment
after the attachment is downloaded. The base class of multimedia attachmentNIMFileAttachment
is inherited fromNIMMessageAttachment
. Its subclasses include:NIMVideoAttachment
: the attachment of a video message.NIMImageAttachment
: the attachment of an image message.NIMAudioAttachment
: the attachment of an audio message.
Some parameters of multimedia attachments
Parameter Type Description path String Optional, The path of a local file. If the file does not exit, null is returned.
The file path of an audio message can be obtained after the attachment is downloaded.
The file path of an image or video message is obtained after the file is manually downloaded. When receiving an image or video message, the SDK only automatically downloads the thumbnail of the file by default.path String Optional, The path of a local thumbnail. If the thumbnail does not exit, null is returned.
If the thumbnail download is complete, the thumbnail file path is obtained. The parameter is not supported on Windows and macOS)thumbUrl String Optional. The URL of a thumbnail. The parameter is not supported on Windows and macOS. size int Optional, the size of a file in bytes. md5 String Optional. The MD5 value of a file. url String Optional, the download URL of a file on the server. If the file is not uploaded, null is returned. extension String Optional, the file extension. expire int Optional, the expiration time of a file. is not supported for Windows and macOS. nosScene NIMNosScene NOS token used for uploading files. The default value is [NIMNosScenes.defaultIm] displayName String Optional, the display name of a file. The display name can be different from the file name and used for display on UI. base64 String Optional. The parameter is used to specify the information about a file to be delivered. The parameter is required for sending files for web apps. NIMFileAttachment
holds the attachment of a message.
Send and receive a location message
The process of sending and receiveing location messages is similar to that of text messages. Only the method of constructing a location message is different. This section only shows relevant examples. For the specific implementation process, see [Send and receive text messages] (https://doc.yunxin.163.com/docs/TM5MzM5Njk/jk0NDM1NjA?platformId=60002#Send and receive text messages).
-
Create a location message by calling the
createLocationMessage
method.Parameter Type Description sessionId
String The chat ID. If it is a P2P chat, use a user account ( accid
). For group chats, use a group ID.sessionType
NIMSessionType The session type, NIMSessionType.p2p
represents the P2P chat andNIMSessionType.team
is the group chat.latitude
double latitude longitude
double longitude address
String The description of a location. You can specify whether the message is stored on the server, added to the roaming messages or counted as unread messages by configuring
NIMCustomMessageConfig
. For specific configuration examples, see Message Configuration. -
Send the location message by calling the
sendMessage
method.Sample code for creating and sending a location message:
// Test account String account = 'testAccount'; // P2P chat NIMSessionType sessionType = NIMSessionType.p2p; // Display the file name String address = 'this is a address'; // Send the message Future<NIMResult<NIMMessage>> result = MessageBuilder.createLocationMessage( sessionId: account, sessionType: sessionType, latitude: 30.3, longitude: 120.2, address: address) .then((value) => value.isSuccess ? NimCore.instance.messageService .sendMessage(message: value.data!, resend: false) : Future.value(value));
Send an alert message
Alert messages are used for reminders in the session. The message type is NIMMessageType.tip
. Alert messages are different from custom messages. Alert messages cannot hold attachments by calling thesetAttachment
method. If you must add an attachment, use a custom message.. Tip messages can serve as in-session notification reminders, such the welcome message that appears when joining a session, or the prompt after hitting a sensitive word during the session. You can use custom message for these scenarios but the implementation is complicated.
This section takes the scenario of "You have recalled a message and the reminder appears in the group (the message is only visible to the sender and not sent to the server)" as an example to introduce the process of sending and receiving tip messages.
API sequence diagram
sequenceDiagram
%%{init:
{
"theme": "default",
"themeVariables": {
"mainBkg" : "#9DC3E6",
"actorBkg" : "#337EFF",
"labelBoxBorderColor" : "#7FBC00",
"labelBoxBkgColor" : "#7FBC00",
"fontFamily": "Inter",
"fontSize": "10px"
}
}
}%%
participant Participant_A
participant NIM
participant Other participants
note over NIM: SDK Initialization
Participant_A ->> NIM: Listen for nessage status change <br> receive system notifications <br>(onMessageStatus & onReceiveSystemMsg)
Participant_A ->> NIM: Log in
Other participants ->> NIM: Log in
note over Participant_A: Join group
Participant_A ->> NIM: Create tip message <br>(createTipMessage)
note right of Participant_A: Set the tip message to be excluded from unread count
Participant_A ->> NIM: Store tip message to local database <br>(saveMessageToLocalEx)
Procedure
-
Before logging in to the IM server, User A registers the
onMessageStatus
andonReceiveSystemMsg
event streams to monitor the changes of the message statusNIMMessageStatus
and receiving system notifications. In this scenario, listen to the the notification for unsending messages.onMessageStatusNimCore.instance.messageService.onMessageStatus.listen((NIMMessage message) { // 1. Determine whether it is your message based on the sessionId // 2. Change the message status in memory // 3. Refresh the interface });
onReceiveSystemMsgNimCore.instance.systemMessageService.onReceiveSystemMsg. NimCore.instance.systemMessageService.onReceiveSystemMsg.listen((SystemMessage event) { });
-
User A creates an advanced group by calling the
createTeam
method. For the sample code, see Create a group. -
Other users join the advanced group created by User A. For the method to join an advanced group, see Join a group.
-
User A creates an alert message by calling the
createTipMessage
method with theenableUnreadCount
parameter set tofalse
. In this case, alert messages are not counted as unread.The methods contain the following parameters:
Parameter Type Description sessionId
String The ID of a session. The sessionType
is used to determine the session type.- If the session is a P2P chat, the
sessionId
is the user’s IM account (accid
) - If the session is a group chat,
sessionId
is the group ID
sessionType
NIMSessionType
The session type. - If the session is a P2P chat, the
-
User A stores alert messages in the local database by calling the
saveMessageToLocalEx
method without sending alert messages to the server.The sample code for Step 4 to 5:
//Create an alert message.
var tipMessageBuild = await MessageBuilder.createTipMessage(sessionId: sessionId, sessionType: sessionType,content: "content");
var message = tipMessageBuild.data!;
message.config = NIMCustomMessageConfig(enableUnreadCount:false);
// Save the alert message.
NimCore.instance.messageService.saveMessageToLocalEx(message: message, time: time).then((value) {
if(value.isSuccess){
// TODO success
}
});
Receive notification messages
For events in some specific scenarios, CommsEase server presets some notification messages and sends them to the SDK when the event occurs. A notification is a specific message. You must parse the data of a notification message to obtain the content of a notification. For example, notifications for group events. If new members join a group, the members in the group will receive this type of notifications. For the difference between notification messages and system notifications, see [Notification Messages and System Notifications] (https://doc.yunxin.163.com/messaging/docs/Tg1MjcyMjg?platform=flutter#Notification Messages and System Notifications)
- The notification message is an in-session message and its corresponding construct is
NIMMessage
. The message type isNIMMessageType.notification
. Notification messages are used for notifications for events in groups and chat rooms.
To parse the notifications, see [Group notification messages](https://doc.yunxin.163.com/messaging/docs/jE1NjkyNzA?platform=flutter#group notifications).
- Notification messages can be filtered. For more information, see Notification Message Filtering.
Send and receive custom messages
In addition to built-in types of messages, the NIM SDK also supports custom messages. The SDK does not define and parse the specific content of a custom message. You must handle parsing of custom messages.. The SDK will store custom messages in the message database, and display custom message in the message history the same as built-in messages.
Custom messages are displayed in the form of attachments. In the NIMMessage
class, custom messages are parsed as the NIMCustomMessageAttachment
object.
FAQ
How can I get the message body
Register the onMessageStatus
event stream that tracks the changes of message status. The method can track the NIMMessage
object returned when the message status changes.
You can get the message body using the following attributes of the NIMMessage
object.
messageDirection
: message direction (sending or receiving a message)sessionId
: the chat target, a user account (accid
) for P2P chats, and group ID (teamId
) for groups chats.content
: The content of a message.messageAttachment
: The attachment of a message.status
: the message status, sending or receiving a message.timestamp
: The time when a message was sent in milliseconds.
How can I set the extension field of a message
You can set the extension field of messages in P2P chats or group chats for server side and client side. The server-side extension field can only be set before the message is sent, and it will be synchronized to other devices.
- For extension fields, wrap them in JSON format and pass in a non-formatted JSON string with a maximum length of 1024 bytes.
Method to set the extension field:
-
For messages in P2P chats and group chats, set the extension field of a message when creating the
IMMessage
object using thelocalExtension
parameter. -
Update the local extension field of a message by calling the
updateMessage
method.After setting the local extension field of a message, call the
updateIMMessage
method to update the field. Otherwise, the extension field will not take effect.
For messages in P2P chats and group chats, set the extension field of a message on the server when creating the NIMMessage
object using the remoteExtension
method.