消息
im.messages 提供消息列表、发送队列、撤回、本人删除、表情回应、置顶、已读回执和本地搜索。消息的服务端字段、限制与内容格式见消息格式。
打开消息列表
val list = im.messages.open(conversationKey)
try {
list.setViewing(atBottom = true, visible = true)
list.snapshot.collect { state ->
println(state.items.size)
println(state.error?.code)
}
} finally {
list.setViewing(visible = false)
list.close()
}快照包含 items、gaps、hasOlder、hasNewer、loading、pinned、error。loadOlder()、loadNewer() 加载历史或更新消息;jumpTo(seq) 定位;只对 kind 为 skipped 的空洞调用 loadGap(gap)。rejoin 空洞反映重新入群边界,不能作为任意历史访问入口。
页面滚动或可见性变化时调用 setViewing;只有启用 autoMarkRead 后才按可见状态自动推进已读,否则调用 list.markRead()。完整生命周期示例见界面与生命周期。
发送内容
import com.deeprespond.im.*
val message = im.messages.send(
SendTarget.User("bob"),
OutgoingContent.Text("你好"),
SendOptions(waitUntilSent = true),
)SendTarget 可选 User(username)、Group(groupId)、Conversation(conversationKey)。
| 内容 | 构造方式 |
|---|---|
| 文本 | OutgoingContent.Text(text) |
| 图片 | OutgoingContent.Image(file, original = false) |
| 语音 | OutgoingContent.Voice(file, duration) |
| 视频 | OutgoingContent.Video(file) |
| 文件 | OutgoingContent.File(file, name?) |
| 自定义 | OutgoingContent.Custom(body),接受 JsonObject 或 Map |
| 位置 | OutgoingContent.Location(latitude, longitude, name?, address?) |
| 已上传附件 | OutgoingContent.Uploaded(type, body) |
| 转发 | OutgoingContent.Forward(message) |
附件使用 DRFile,URI、录音和预处理见文件。
im.messages.send(
SendTarget.Group(groupId),
OutgoingContent.Custom(mapOf("card" to "order", "order_id" to "order-1")),
SendOptions(mentionUsernames = listOf("bob"), needReceipt = true),
)发送选项与队列
| SendOptions 字段 | 默认值 | 用途 |
|---|---|---|
ext | null | JsonObject 扩展字段 |
mentionUsernames、mentionAll | null、false | @成员、@全体 |
replyToSeq | null | 引用同一会话中的序号 |
needReceipt | false | 申请群已读回执 |
excludeFromUnread | false | 不计入未读,是否允许由策略决定 |
pushDisabled | null | 本条是否关闭推送 |
waitUntilSent | false | 等服务端确认后才返回 |
默认 send 在消息写入队列后返回,本地状态为 queued、uploading、sending、sent 或 failed。待发消息的 messageId、seq、conversationId 可能为 null,使用 clientMsgId 标识本地消息;上传进度和错误位于 message.local。
进入队列后,调用方协程取消只是不再等待,消息仍按队列规则处理。用 discard(clientMsgId) 删除等待或失败的本地消息并取消上传;resend(clientMsgId) 重新发送。网络恢复后 SDK 自动处理队列,不要为同一条待发消息反复调用 send。
撤回、删除、回应与置顶
if (im.messages.canRecall(message)) {
val id = message.conversationId
val seq = message.seq
if (id != null && seq != null) im.messages.recall(id, seq)
}
im.messages.react(conversationId, seq, "like")
im.messages.unreact(conversationId, seq, "like")
im.messages.setPinned(conversationId, seq, true)撤回与置顶仍以服务端权限和时限为准。deleteForMe(conversationId, seqs) 仅本人删除,每次最多 100 条;reactionUsers 查询表情参与者。当前公开客户端接口没有 edit 方法,不应照搬 REST 的编辑接口名。
查询与回执
lookup(conversationId, seqs)返回 items 与 missing。searchLocal(keyword, conversationId?, limit = 50)只检索已保存的文本消息,不等于服务端全量搜索。receipts(conversationId, seqs)查询群已读人数;getReceipt读取最近内存缓存。receiptUsers(..., ReceiptStatus.READ / UNREAD)分页查询成员,权限取决于应用策略。
只发给在线设备
sendOnline(target, body, ext?) 只发送 custom 内容,不进队列、不保存离线消息、不自动重试。连接暂停时以 network_error/paused 失败;用 MessageOnline 事件接收。适用于临时协作信号,不作为可靠通知通道。
全部方法和参数见MessagesModule。
