Message overview
Understand the Message model, message types, and message lifecycle in the OpenIM Flutter SDK.
The OpenIM Flutter SDK organizes messaging capabilities around the Message model. Create ordinary messages or media messages backed by local paths or bytes using the corresponding factory method, then deliver them with Send a message. When media files have already been uploaded by your application server and a URL is available, construct the message using the corresponding URL-based creation method and deliver it with Send a message without OSS. Both delivery paths support one-to-one and group chats. Real-time updates, recalls, deletions, read receipts, upload progress, and conversation shifts synchronize to application state via their respective listeners.
The Flutter Message model does not include a conversationID field. The conversationID used for history retrieval, search, and conversation management is derived from the active conversation context. When a global listener receives a cross-conversation message, determine the target from sessionType, groupID, sendID, recvID, and the current user ID, then obtain the conversation ID using the conversation ID helper.
Message interfaces typically manage the following key identifiers:
| Identifier | Purpose |
|---|---|
clientMsgID | Stable client-side message ID used for deduplication, state updates, queries, and pagination cursors. Never use an empty value as a merge key. |
conversationID | Unique ID of the conversation record used to load history, clear unread counts, and search. Obtained from the conversation context, not a field on Message. |
recvID | Recipient user ID for one-to-one messages. Omitted when sending group messages. |
groupID | Target group ID for group messages. Omitted when sending one-to-one messages. |
Message types
Construct each type of content with its dedicated factory method before sending. The sending layer provides a unified interface: pass the resulting Message instance to either Send a message or Send a message without OSS.
Message type comparison
| Content type | Recommended guide | Content element |
|---|---|---|
| Plain text | Create a text message | textElem |
| @ mention | Create an @ mention message | atTextElem |
| Image | Create an image message, Create an image message from full path, Create an image message by URL | pictureElem |
| Audio | Create an audio message, Create an audio message from full path, Create an audio message by URL | soundElem |
| Video | Create a video message, Create a video message from full path, Create a video message by URL | videoElem |
| File | Create a file message, Create a file message from full path, Create a file message by URL | fileElem |
| Custom | Create a custom message | customElem |
| Quotes, merges, locations, cards, and faces | Create a quote message, Create a merged message, Create a location message, Create a card message, Create a face message | quoteElem, mergeElem, locationElem, cardElem, faceElem |
Media messages created from local paths or bytes are typically uploaded by the SDK and dispatched with Send a message. When media files have already been uploaded by external services and URLs are available, create the message using URL-based factory methods and invoke Send a message without OSS to bypass SDK upload pipelines.
Attach business metadata intended for all recipients to message content or server-side extension fields. Store client-specific UI states intended only for the local device in localEx.
Common Message fields
| Field | Description |
|---|---|
clientMsgID | Stable client-side identifier used for delivery status tracking, queries, and event reconciliation. |
serverMsgID | Unique server-assigned message identifier confirmed after receipt. |
sendID / recvID / groupID | Sender user ID, recipient user ID in direct chats, and destination group ID in group chats. |
sessionType | Conversation type: single or group chat; used to determine conversation routing. |
contentType | Content type identifier, evaluated against integer constants in MessageType. |
status | Message delivery status. |
sendTime / createTime | Server timestamp when sent and local timestamp when created. |
isRead | Read receipt state for the message. |
textElem, pictureElem, soundElem, videoElem, fileElem | Payload objects for standard media content types. |
atTextElem, quoteElem, mergeElem, customElem | Payload objects for mentions, quotes, merged chats, and custom data. |
offlinePush | Push notification configuration for the message. |
ex / localEx | Server-synchronized extension and device-local extension. |
In the Dart SDK model, clientMsgID, sendID, recvID, groupID, and sessionType are nullable. Verify required fields before indexing records; do not use bang operators (!) on untrusted message payloads.
Message lifecycle and conversation routing
- Initialize a local
Messageinstance using dedicated factory methods. Constructing a message does not invoke network requests or trigger new-message callbacks. - Call Send a message for standard delivery, or call Send a message without OSS for pre-uploaded media.
- Upon
Futureresolution, update the sender UI using the returnedMessageobject. Other participants receive the message via their message listeners. - Historical loading, local search, and ID queries return local database snapshots without triggering new-message callbacks.
When a message is sent or received within an active conversation with a known conversationID, merge the record directly into that conversation. For global receive events lacking context, resolve sourceID: for group conversations, use groupID; for direct conversations, compare sendID with the current user ID to select the counterparty ID from recvID or sendID. Then provide sourceID and sessionType to the conversation ID helper.
Skip messages with incomplete routing identifiers. Never substitute list indices, display names, or array lengths for stable conversation and message keys.
Navigation by task
Send messages
Construct a message object, then dispatch it to a user or group. Set userID for direct messages or groupID for group messages, leaving the alternative target empty.
When uploading media through the SDK, use path-based or byte-based creation methods alongside Send a message. When media is pre-uploaded, use URL-based creation methods with Send a message without OSS. Both flows return the updated Message through a Future, which must be merged by clientMsgID.
For parameter descriptions and delivery boundaries, see Send a message.
Receive messages
Handle standard real-time messages, offline synchronized messages, and online-only messages through onRecvNewMessage, onRecvOfflineNewMessage, and onRecvOnlineOnlyMessage. Global listeners must resolve the message's conversation first, then merge items idempotently using conversationID:clientMsgID. Online-only messages are not persisted to local database storage.
For callback parameters and error handling, see Receive messages.
Retrieve messages
Retrieve historical messages in paginated batches by conversationID. Omit startMsg on the initial request, then pass the boundary message as the cursor for subsequent pages. Historical results and real-time listeners may deliver identical records; deduplicate using clientMsgID.
See Load older messages to paginate message history, and Locate messages by ID to fetch specific records.
Search messages
Search locally synchronized messages using keywords and filter parameters. When searching within a group, supply the group's conversationID rather than its groupID. The keywordListMatchType and senderUserIDList fields are currently reserved and do not filter local search results.
See Search messages for complete usage.
Manage messages
Manage existing messages by forwarding, merging, deleting, revoking, modifying, pinning, or inserting local placeholders, or send typing indicators. Revoke, delete, and modify events should update matching records by conversationID:clientMsgID. Replace pinned message lists by conversationID, then deduplicate by clientMsgID.
See Create a forward message, Create a merger message, Delete saved messages, Revoke a message, Modify a message, Pin or unpin a message, Insert a local single-chat message, Clear all local messages, and Update typing status.
Mark messages as read
Clear conversation unread counts using the mark-as-read API. The Flutter SDK receives single-chat read receipts, but does not provide group-member read receipt reporting, group read/unread queries, or group receipt listeners. A conversation's unread counter does not reflect which group members have read a message.
For single-chat read receipt flows, see Mark conversation as read.
Mention other users
Create group @ messages using Create an @ mention message, then send them to the group via Send a message. Target users using their stable userID. Recipients parse mentions from atTextElem and render mention notifications using the conversation's groupAtType.
Retrieve unread counts
Conversation lists, total unread counts, and mention alerts are managed through conversation APIs and OnConversationListener. Merge changes by conversationID and update global badges from the total unread counter. Message screens should not register redundant conversation listeners.
See Get total unread message count.
Custom messages and extension data
Attach metadata intended for other participants to custom message payloads or server-side extension fields before transmission. Store data that only affects the current device in localEx. Setting a local extension replaces the entire string without merging prior values and does not generate shared message events.
See Create a custom message and Set message local extension.
Speech recognition and audio transcription
Audio transcription accepts audio file paths accessible by the local device and returns transcribed text. Checking transcription capabilities returns a Future<void> without returning format, sample rate, duration, or file size attributes.
Transcribed text can be stored in the voice message's soundElem.text field using local update APIs, but changes persist only on the local device without synchronizing to other members or emitting shared message events. See Transcribe audio.
Event ownership
Message-related events are distributed across specific capability guides for listening and state synchronization:
- New message and offline synchronization: Receive messages
- Deletion: Delete saved messages
- Revocation: Revoke a message
- Modification: Modify a message
- Pinning: Pin or unpin a message
- Single-chat read receipts: Mark conversation as read
- Typing indicators: Update typing status
- Conversation list changes: Retrieve conversation list
Creating messages and querying local data returns objects or snapshots directly via Future and does not trigger shared events. For state-changing APIs, handle Future resolution, event updates, and queries as distinct lifecycle stages.
The Flutter Enterprise SDK provides message modification, conversation message pinning, and audio transcription. The Flutter SDK does not provide an API for creating targeted group messages.
Was this page helpful?