跳到主要内容
版本:5.X

发送消息

本文介绍了如何从客户端发送消息,适用于单聊、群聊、聊天室。

请注意,客户端 SDK 发送消息存在频率限制,每秒最多只能发送 5 条消息。

发送消息

sendMessage 是发送消息的基础接口,可用来发送 IMLib 中的内置类型消息或自定义消息。针对不同的特定消息类型,IMLib 还提供了多个便于调用的语法糖方法。

以调用 sendMessage 往群聊中发送 @张三的文本消息为例。

  1. 定义目标群聊会话,并实例化待发送消息。因为发送的是群聊 @ 消息,所以需要添加 mentionedInfo

    // 定义消息投送目标会话, 这里定义一个群组类型会话
    const conversation = { conversationType: RongIMLib.ConversationType.GROUP, targetId: '<目标 Id>' }
    // 实例化待发送消息,RongIMLib.TextMessage 为内置文本型消息
    const message = new RongIMLib.TextMessage({
    // 文本内容
    content: '文本内容',
    // (可选)消息中附加信息,透传到对端
    extra: '消息中附加信息',
    // 群组消息中,如果需要发送 @ 消息,可添加 mentionedInfo 字段
    mentionedInfo: {
    // @ 类型:全部、个人
    type: RongIMLib.MentionedType.SINGAL,
    // @ 用户列表
    userIdList: [zhangsan],
    // @ 内容
    mentionedContent: ''
    }
    })
  2. 构造发送选项 ISendMessageOptions,用于定义发送行为中的一些可选配置。因为发送的是群聊 @ 消息,必须将 options 中的 isMentioned 设置为 true

    // 配置属性
    const options = {
    // 如果需要发送 @ 消息,isMentioned 需设置为 true
    isMentioned: true,
    // 消息发送前的回调,可以使用此回调返回的 message 用于列表渲染
    onSendBefore: (message) => {
    console.log('消息发送前的回调', message)
    }
    }
  3. 发送消息。如果消息发送成功,可以根据返回结果中的 messageId 字段将列表中的该消息状态改为发送成功。

    // 发送消息
    RongIMLib.sendMessage(conversation, message, options).then(res => {
    if (res.code === RongIMLib.ErrorCode.SUCCESS) {
    // 消息发送成功,可以根据返回结果中的 messageId 字段将列表中的该消息状态改为发送成功。
    console.log('消息发送成功', res.data)
    } else {
    console.log('消息发送失败', res.code, res.msg)
    }
    })
  4. 如果消息发送失败,可以根据返回结果中的 messageId 字段将列表中的该消息状态改为发送失败,并重发消息。

    客户端遇到消息发送失败时,可能有以下情况

    1. 消息未送达融云服务器,或送达融云服务端后返回发送失败的情况(其他人也没有收到)。
    2. 某些极端情况下(例如弱网环境),消息可能已成功送达收件方。但发送端未能及时收到融云服务端回执,超时后认为发送失败。此时客户端重发消息后会导致对方重复收到消息。关于该问题的详细解释可参考 FAQ。
  5. 重新发送消息。重发消息需与原始消息保持一致。

提示

SDK 从 5.5.1 版本开始,支持重发消息时在 options 中传入原消息的 messageId。融云服务端不会去除重复消息,应用层可通过该 ID 自行判断消息是否属于重复消息,并进行相应处理。该 ID 可以从 onSendBefore 回调返回的 message 对象或返回结果中获取。

    // 定义消息投送目标会话, 这里定义一个群组类型会话
const conversation = { conversationType: RongIMLib.ConversationType.GROUP, targetId: '<目标 Id>' }
// 实例化待发送消息,RongIMLib.TextMessage 为内置文本型消息
const message = new RongIMLib.TextMessage({ content: '文本内容' })
// 配置属性
const options = {
// 重发消息的 messageId, 可以从 onSendBefore 回调返回的 message 对象中 或 返回结果中获取
messageId: 0
}

RongIMLib.sendMessage(conversation, message, options).then(res => {
if (res.code === RongIMLib.ErrorCode.SUCCESS) {
// 消息发送成功,可以根据返回结果中的 messageId 字段将列表中的该消息状态改为发送成功。
console.log('消息发送成功', res.data)
} else {
// 消息发送失败,可以根据返回结果中的 messageId 字段将列表中的该消息状态改为发送失败。
console.log('消息发送失败', res.code, res.msg)
}
})

sendMessage 接口说明

sendMessage 方法接收 conversationmessageoptions 三个参数。

  • conversation 定义目标会话。详见 IConversationOption

    参数类型说明
    conversationTypeConversationType会话类型
    targetIdstring接收方 Id
  • message 是待发送的消息内容,支持 IMLib 内置消息(例如 RongIMLib.TextMessage)实例,或者通过 RongIMLib.registerMessageType() 实现的自定义消息实例。

  • options 定义发送行为中的一些可选配置,如是否可拓展,推送等。参见 ISendMessageOptions

    参数类型说明
    isStatusMessageboolean已废弃)是否为状态消息(可选项)
    disableNotificationboolean是否发送静默消息(可选项)
    pushContentstringPush 信息(可选项)
    pushDatastringPush 通知携带的附加信息(可选项)
    isMentionedboolean是否为 @ 消息。仅在 conversationType 取值为群组或超级群类型时有效(可选项)
    mentionedType1|2已废弃) @ 消息类型,1: @ 所有人 2: @ 指定用户(可选项) 已废弃
    mentionedUserIdListstring[]已废弃)被 @ 的用户 Id 列表(可选项)
    directionalUserIdListstring[]用于发送定向消息,仅在 conversationType 取值为群组或超级群类型时有效。注意,如果 SDK 版本 < 5.9.4,仅群组支持定向消息。(可选项)
    isVoipPushboolean当对方为 iOS 设备且未在线时,其将收到 Voip Push. 此配置对 Android 无影响(可选项)
    canIncludeExpansionboolean是否允许消息被拓展
    expansion[key: string]: string消息拓展内容数据(可选项)
    isFilerWhiteBlacklistboolean黑/白名单(可选项)
    pushConfigIPushConfig移动端推送配置(可选项)(与 Android、iOS 端的 MessagePushConfig 作用相似)
    onSendBeforeFunction消息发送前的回调,支持版本:5.4.0
    messageIdnumber重发消息时,传要重发消息的 messageId,重发消息的所有参数需与原始消息一致,支持版本:5.5.1
    • IPushConfig 参数说明

      参数类型说明
      pushTitlestring推送标题,在没有设置的情况下:单聊通知标题显示为发送者名称,群聊通知标题显示为群名称;自定义消息,默认不显示标题;
      pushContentstring推送内容
      pushDatastring远程推送附加信息
      iOSConfigIiOSPushConfig(可选项)
      androidConfigIAndroidPushConfig(可选项)
      disablePushTitleboolean是否显示推送标题. 仅针对 iOS 平台有效
      forceShowDetailContentboolean是否强制推送
      templateIdstring推送模板id

内置消息类型

IMLib 提供了预定义的文本、语音、图片、Gif、文件等消息类型。

文本消息

ITextMessageBody 参数说明

Key类型必填说明
contentstring文本内容

代码示例

new RongIMLib.TextMessage({ content: '' })

图片消息

IImageMessageBody 参数说明

Key类型必填说明
contentstring图片缩略图,应为 Base64 字符串。自行生成缩略图(建议最长边不超过 240 像素),进行 Base64 编码后放入 content 中。Base64 字符串长度建议为 5k,最大不超过 10k。注意,部分工具图片转 Base64 输出结果会携带 Data URI 前缀。例如:data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAZABkAAD。请丢弃其中 Data URI 前缀,仅保留数据部分,例如:/9j/4AAQSkZJRgABAgAAZABkAAD
imageUristring图片的远程访问地址

代码示例

new RongIMLib.ImageMessage({
content: '', // 图片缩略图,应为 Base64 字符串,且不可超过 80KB
imageUri: '' // 图片的远程访问地址
})

文件消息

IFileMessageBody 参数说明

Key类型必填说明
namestring文件名称
sizenumber图片尺寸,单位 Byte
typestring文件类型
fileUrlstring文件远程下载地址

代码示例

new RongIMLib.FileMessage({
name: '',
size: 1000,
type: '',
fileUrl: ''
})

高清语音

IHQVoiceMessageBody 参数说明

Key类型必填说明
remoteUrlstring远程媒体资源地址
durationnumber语音时长,单位 s。请务必保证待发送的语音时长保持在 60s 以内
typestring编码类型,默认 aac。如果您的业务同时使用了 Android/iOS 端的 IMKit SDK,请使用默认的 aac 格式,因为 IMKit 的音频录制、播放只实现了对 aac 格式的支持,默认无法播放其他格式。如果您的 Android/iOS App 会自行处理音频录制、播放,可以按需选用格式。

代码示例

new RongIMLib.HQVoiceMessage({
remoteUrl: '<aac 文件地址>',
duration: 60,
})

短视频消息

ISightMessageBody 参数说明

Key类型必填说明
sightUrlstring远程视频资源地址。如果您的业务同时使用了 Android/iOS 端的 IMKit SDK,必须使用 H.264 + AAC 编码的文件,因为 IMKit 的短视频录制、播放只实现了该编码组合的支持。
contentstring小视频首帧缩略图的 Base64 字符串。自行生成缩略图(建议最长边不超过 240 像素),进行 Base64 编码后放入 content 中。Base64 字符串长度建议为 5k,最大不超过 10k。注意,部分工具图片转 Base64 输出结果会携带 Data URI 前缀。例如:data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAZABkAAD。请丢弃其中 Data URI 前缀,仅保留数据部分,例如:/9j/4AAQSkZJRgABAgAAZABkAAD
durationnumber视频时长。请注意服务端的默认视频时长上限为 2 分钟。如需调整上限,请联系商务。
sizenumber视频大小,单位 Byte
namenumber视频名称

代码示例

new RongIMLib.SightMessage({
sightUrl: "<视频资源的远程地址>",
content: "<缩略图base64>"
duration: 10,
size: 100,
name: "视频名称"
})

GIF 消息

IGIFMessageBody 参数说明

Key类型必填说明
gifDataSizenumberGIF 图片文件大小,单位 Byte
remoteUrlstringGIF 图片的远程存储地址
widthnumber图片宽度
heightnumber图片高度

代码示例

new RongIMLib.GIFMessage({
gifDataSize: 30,
remoteUrl: '<图片地址>',
width: 300,
height: 200
})

引用消息

IReferenceMessageBody 参数说明

参数类型必填说明
referMsgUserIdstring被引用消息的发送用户 Id
referMsgany引用消息对象
contentstring输入的文本消息内容
objNamestring引用的消息类型

代码示例

new RongIMLib.ReferenceMessage({
referMsgUserId: '<引用消息的用户ID>',
referMsg: {
content: '引用消息文本'
},
referMsgUid: '引用消息的 messageUId',
content: '发送的消息内容',
objName: RongIMLib.MessageType.TEXT
})

位置消息

ILocationMessageBody 参数说明

参数类型必填说明
longitudenumber经度
latitudenumber维度
poistring位置信息
contentstring位置缩略图,图片需要是不带前缀的 Base64 字符串

代码示例

new RongIMLib.LocationMessage({
latitude: '<位置的经度>',
longitude: '<位置的纬度>',
poi: '位置信息',
content: '<base64>'
})

富文本消息

IRichContentMessageBody 参数说明

参数类型必填说明
titlestring标题
contentstring简介内容
imageUristring展示的图片地址
urlstring文章链接地址

代码示例

new RongIMLib.RichContentMessage({
title: '标题',
content: '内容简介',
imageUri: '<图片地址>',
url: '<文章链接地址>'
})

小灰条消息

提示

从 5.8.1 开始支持

IInformationNotificationMessageBody 参数说明

参数类型必填说明
messagestring提示条消息内容
extrastring提示条附加信息

代码示例

new RongIMLib.InformationNotificationMessage({
message: '提示条消息内容',
extra: '提示条附加信息',
})

命令消息

提示

从 5.8.1 开始支持

ICommandMessageBody 参数说明

参数类型必填说明
namestring命令名称
datastring命令内容

代码示例

new RongIMLib.CommandMessage({
name: '命令名称',
data: '命令内容',
})

群组通知消息

提示

从 5.8.1 开始支持

IGroupNotificationMessageBody 参数说明

参数类型必填说明
operatorUserIdstring操作人用户 ID
operationstring群组中各种通知的操作名称
datastring操作数据
messagestring消息内容
extrastring扩展信息

代码示例

new RongIMLib.GroupNotificationMessage({
operatorUserId: '操作人用户 ID',
operation: '群组中各种通知的操作名称',
data: '操作数据',
message: '消息内容'
})

Emoji 消息

Web 端发送 Emoji 消息时,直接以文本消息类型(TextMessage)发送即可。

  • 融云提供 Emoji 插件,内置了 128 个 Emoji 表情的图片。可用于消息输入框的表情选项,也可自行扩展配置。
  • 发消息时,必须直接发送 Emoji 原生字符。如:😀 ,转换方法:symbolToEmoji
  • Web SDK 接收消息时,接收到的 Emoji 为 Unicode 编码格式,例如:ef600。转换后才能正确显示为原生 Emoji。

代码示例

// 定义消息投送目标会话
const conversation = { conversationType: RongIMLib.ConversationType.PRIVATE, targetId: '<目标 Id>' }
// 实例化待发送消息,RongIMLib.TextMessage 为内置文本型消息
const message = new RongIMLib.TextMessage({ content: '😀' })
// 发送
RongIMLib.sendMessage(conversation, message).then(res => {})

Emoji 插件

  • 插件兼容性

    ChromeFirefoxSafariIEEdgeiPhoneAndroid
    30+30+10+7+✔️iOS 8.0+ 的Safari浏览器以及微信浏览器4.4+系统的Chrome浏览器以及微信浏览器
  • 引入 Emoji 插件

    <!-- 非压缩版 -->
    <script src="https://cdn.ronghub.com/RongEmoji-2.2.10.js"></script>
    <!-- 压缩版 -->
    <script src="https://cdn.ronghub.com/RongEmoji-2.2.10.min.js"></script>
危险
  1. 使用 import * as RongIMLib from '@rongcloud/imlib-next' 方式引入 SDK 时表情插件调用需要使用 window 前缀。例如:window.RongIMLib.RongIMEmoji.init()
  2. RongEmoji 插件仅支持 cdn 引入方式,暂不支持 npm 引入
  • Emoji 初始化(默认参数)

    RongIMLib.RongIMEmoji.init();
  • Emoji 初始化(自定义表情配置)

    config 参数说明:

    参数类型必填说明最低版本
    sizeNumber表情大小, 默认 24, 建议 18 - 582.2.6
    urlStringEmoji 背景图片 url2.2.6
    langStringEmoji 对应名称语言, 默认 zh2.2.6
    extensionObject扩展表情2.2.6
    // 表情信息可参考 http://unicode.org/emoji/charts/full-emoji-list.html
    var config = {
    size: 25,
    url: '//f2e.cn.ronghub.com/sdk/emoji-48.png',
    lang: 'en',
    extension: {
    dataSource: {
    u1F914: { // 自定义 u1F914 对应的表情
    en: 'thinking face', // 英文名称
    zh: '思考', // 中文名称
    tag: '🤔', // 原生 Emoji
    position: '0 0' // 所在背景图位置坐标
    }
    },
    url: '//cdn.ronghub.com/thinking-face.png' // 新增 Emoji 背景图 url
    }
    };
    RongIMLib.RongIMEmoji.init(config);
  • 获取列表

    var list = RongIMLib.RongIMEmoji.list;
    /*list => [{
    unicode: 'u1F600',
    emoji: '😀',
    node: span,
    symbol: '[笑嘻嘻]'
    }]
    */
  • Emoji 转文字

    在不支持原生 Emoji 渲染时,可显示对应名称,适用于消息输入。

    var message = '😀😁测试 Emoji';
    // 将 message 中的原生 Emoji 转化为对应名称
    RongIMLib.RongIMEmoji.emojiToSymbol(message);
    // => '[笑嘻嘻][露齿而笑]测试 Emoji'
  • 文字转 Emoji

    发送消息时,消息体里必须使用原生 Emoji 字符。

    var message = '[笑嘻嘻][露齿而笑]测试 Emoji';
    // 将 message 中的 Emoji 对应名称转化为原生 Emoji
    RongIMLib.RongIMEmoji.symbolToEmoji(message);
    // => '😀😁测试 Emoji'
  • Emoji 转 HTML

    Web SDK 接收消息后,消息体内的原生 Emoji 字符会被解码为对应 Unicode 码,需调用转化方法才能正确显示。

    var message = '\uf600测试 Emoji';
    // 将 message 中的原生 Emoji (包含 Unicode ) 转化为 HTML
    RongIMLib.RongIMEmoji.emojiToHTML(message);
    // => "<span class='rong-emoji-content' name='[笑嘻嘻]'>😀</span>测试 Emoji"
  • 文字 转 HTML

    var message = '[露齿而笑]测试 Emoji';
    // 将 message 中的 Emoji 对应名称转化为 HTML
    RongIMLib.RongIMEmoji.symbolToHTML(message);
    // => "<span class='rong-emoji-content' name='[露齿而笑]'>😁</span>测试 Emoji"

拓展属性

所有消息均支持 userextra 两种拓展属性,便于业务层基于自身需求透传业务数据信息。

  • user: 用于在消息中携带用户数据,目前仅支持 user.iduser.nameuser.portraitUriuser.extra 四个属性定义。
  • extra: 字符串类型数据,融云不解析,由业务层自行定义序列化与反序列化逻辑。

代码示例

new RongIMLib.TextMessage({
content: '',
extra: '',
user: {
id: '',
name: '',
portraitUri: '',
extra: ''
}
})

语法糖

发送 FileMessageImageMessageHQVoiceMessageSightMessageGIFMessage 五种消息时,在构建消息实例过程中均需要一个远程资源地,这意味着业务层需要将待发送的本地资源先行上传,再构建消息实例,过程较为复杂。

为此,IMLib 实现了相应的语法糖方法以封装本地资源的上传过程、以及消息构建过程,便于业务层更易于集成。

发送文件消息

参数说明

参数类型必填说明
conversationIConversationOption会话
msgBodyISendFileMessageOptions要发送的消息内容
hooksIUploadHooks上传过程中的回调钩子
sendOptionsIUploadMessageOption消息配置

代码示例

const conversation = {
conversationType: RongIMLib.ConversationType.PRIVATE,
targetId: ''
}
const msgBody = {
file, // 待上传文件
user: { id: '', name: '', portraitUri: '', extra: '' }, // 消息中携带的用户信息,非必填
extra: '' // 消息中携带的透传信息,非必填
}
const hooks = {
onProgress (progress) {}, // 上传进度监听,可选
onComplete (fileInfo) { // 上传完成时的回调钩子,可选
console.log(fileInfo.url) // 文件存储地址
// 如果需要构建自定义消息,return new ABCMesssage('')
// ABCMesssage 定义通过自定义消息实现 `const ABCMesssage = RongIMLib.registerMessageType(...)`
// 无 return 返回值的情况下,SDK 默认发送 FileMessage
}
}
const options = {
contentDisposition: 'attachment' // 文件链接在浏览器中展示形式(仅 aws、stc 上传有效) 'inline': 在浏览器中预览, 'attachment': 直接下载。如果不传,html 类型文件会预览,其他类型为直接下载
// ... 其他配置项,可选
},

RongIMLib.sendFileMessage(
conversation,
msgBody,
hooks,
options
).then(({ code, data: message }) => {
if (code === 0) {
// 发送成功
}
})

发送图片消息

参数说明

参数类型必填说明
conversationIConversationOption会话
msgBodyISendImageMessageOptions要发送的消息内容
hooksIUploadHooks上传过程中的回调钩子
sendOptionsIImageMessageOption消息配置

代码示例

const conversation = {
conversationType: RongIMLib.ConversationType.PRIVATE,
targetId: ''
}
const msgBody = {
file, // 待上传文件
user: { id: '', name: '', portraitUri: '', extra: '' }, // 消息中携带的用户信息,非必填
extra: '' // 消息中携带的透传信息,非必填
}
const hooks = {
onProgress (progress) {}, // 上传进度监听,可选
onComplete (fileInfo) { // 上传完成时的回调钩子,可选
console.log(fileInfo.url) // 文件存储地址
// 如果需要构建自定义消息,return new ABCMesssage('')
// ABCMesssage 定义通过自定义消息实现 `const ABCMesssage = RongIMLib.registerMessageType(...)`
// 无 return 返回值的情况下,SDK 默认发送 FileMessage
}
}
const options = {
contentDisposition: 'inline' // 'inline' | 'attachment' , 使用 aws 上传时返回链接在浏览器中的展示形式
// ... 其他配置项,可选
},

RongIMLib.sendImageMessage(
conversation,
msgBody,
hooks,
options
).then(({ code, data: message }) => {
if (code === 0) {
// 发送成功
}
})

发送高清语音消息

提示

如果您的业务同时使用了 Android/iOS 端的 IMKit SDK,请使用默认的 aac 格式,因为 IMKit 的音频录制、播放只实现了对 aac 格式的支持,默认无法播放其他格式。如果您的 Android/iOS App 会自行处理音频录制、播放,可以按需选用格式。

参数说明

参数类型必填说明
conversationIConversationOption会话
msgBodyISendHQVoiceMessageOptions要发送的消息内容
hooksIUploadHooks上传过程中的回调钩子
sendOptionsIUploadMessageOption消息配置

代码示例

const conversation = {
conversationType: RongIMLib.ConversationType.PRIVATE,
targetId: ''
}
const msgBody = {
file, // 待上传文件
user: { id: '', name: '', portraitUri: '', extra: '' }, // 消息中携带的用户信息,非必填
extra: '' // 消息中携带的透传信息,非必填
}
const hooks = {
onProgress (progress) {}, // 上传进度监听,可选
onComplete (fileInfo) { // 上传完成时的回调钩子,可选
console.log(fileInfo.url) // 文件存储地址
// 如果需要构建自定义消息,return new ABCMesssage('')
// ABCMesssage 定义通过自定义消息实现 `const ABCMesssage = RongIMLib.registerMessageType(...)`
// 无 return 返回值的情况下,SDK 默认发送 FileMessage
}
}
const options = {
contentDisposition: 'attachment' // 文件链接在浏览器中展示形式(仅 aws、stc 上传有效) 'inline': 在浏览器中预览, 'attachment': 直接下载。如果不传,html 类型文件会预览,其他类型为直接下载
// ... 其他配置项,可选
},

RongIMLib.sendHQVoiceMessage(
conversation,
msgBody,
hooks,
options
).then(({ code, data: message }) => {
if (code === 0) {
// 发送成功
}
})

发送短视频消息

提示

如果您的业务同时使用了 Android/iOS 端的 IMKit SDK,必须使用 H.264 + AAC 编码的文件,因为 IMKit 的短视频录制、播放只实现了该编码组合的支持。

参数说明

参数类型必填说明
conversationIConversationOption会话
msgBodyISendSightMessageOptions要发送的消息内容
hooksIUploadHooks上传过程中的回调钩子
sendOptionsIUploadMessageOption消息配置

代码示例

const conversation = {
conversationType: RongIMLib.ConversationType.PRIVATE,
targetId: ''
}
const msgBody = {
file, // 待上传文件
user: { id: '', name: '', portraitUri: '', extra: '' }, // 消息中携带的用户信息,非必填
extra: '', // 消息中携带的透传信息,非必填
duration: 10, // 时长
thumbnail: '' // 缩略图
}
const hooks = {
onProgress (progress) {}, // 上传进度监听,可选
onComplete (fileInfo) { // 上传完成时的回调钩子,可选
console.log(fileInfo.url) // 文件存储地址
// 如果需要构建自定义消息,return new ABCMesssage('')
// ABCMesssage 定义通过自定义消息实现 `const ABCMesssage = RongIMLib.registerMessageType(...)`
// 无 return 返回值的情况下,SDK 默认发送 FileMessage
}
}
const options = {
contentDisposition: 'attachment' // 文件链接在浏览器中展示形式(仅 aws、stc 上传有效) 'inline': 在浏览器中预览, 'attachment': 直接下载。如果不传,html 类型文件会预览,其他类型为直接下载
// ... 其他配置项,可选
},

RongIMLib.sendSightMessage(
conversation,
msgBody,
hooks,
options
).then(({ code, data: message }) => {
if (code === 0) {
// 发送成功
}
})

发送输入状态

当需要同步输入状态到指定会话,可以通过调用 sendTypingStatusMessage 方法实现。

代码示例

RongIMLib.sendTypingStatusMessage({
conversationType: RongIMLib.ConversationType.PRIVATE,
targetId: '<targetId>'
}, RongIMLib.MessageType.TEXT)

为什么发送失败后重发消息可能导致消息重复

发送端处于弱网情况下可能出现该问题。

问题场景

A 向 B 发送消息后,消息成功到达服务端,并成功下发到接收者 B。但 A 由于网络等原因可能未收到服务端返回的 ack,导致 A 认为没有发送成功。此时如果 A 重发消息,此时 B 就会收到与之前重复的消息。

解决方案

融云服务端不处理消息重复。从 SDK 5.5.1 版本开始,支持在重发消息携带原消息的 messageId。应用层可在消息重复时自行处理。

发送消息后和接收消息时,消息中会携带 messageId 字段,这个字段是由客户端生成的消息 ID。从 Web 端重发消息时,在 options 参数中传入发送失败消息的 messageId。应用层在展示消息前,可根据 senderUserIdmessageId 滤除重复消息后再进行展示。

遗留问题

  1. 撤回重发的消息时,会出现只能撤回一条,另一条还存在的问题。
  2. 收到的消息重复时,即时页面上通过过滤方式使消息显示一条,但未读数依然会显示 2 个。

如何实现转发、群发消息

转发消息:IMLib SDK 未提供转发消息接口。App 实现转发消息效果时,可调用发送消息接口发送。

群发消息:群发消息是指向多个用户发送消息。更准确地说,是向多个 Target ID?发送消息,一个 Target ID 可能代表一个用户,一个群组,或一个聊天室。客户端 SDK 未提供直接实现群发消息效果的 API。您可以考虑以下实现方式:

  • App 循环调用客户端的发送消息 API。请注意,客户端 SDK 限制发送消息的频率上限为每秒 5 条。
  • App 在业务服务端接入即时通讯服务端 API(IM Server API),由 App 业务服务端群发消息。IM Server API 的 发送单聊消息 接口支持单次向多个用户发送单聊消息。您也可以通过 发送群聊消息发送聊天室消息接口实现单次向多个群组或多个聊天室发送消息。