跳到主要内容

发送消息

本文主要描述了如何使用 IMLib SDK 向单聊会话、群聊会话、聊天室会话中发送消息。

消息内容类型简介

IMLib SDK 定义的 Message 对象的 content 属性中可包含两大类消息内容:普通消息内容和媒体消息内容。普通消息内容父类是 MessageContent,媒体消息内容父类是 MediaMessageContent。发送媒体消息和普通消息本质的区别为是否有上传数据过程。

功能消息内容的类型父类描述
文本消息TextMessageMessageContent文本消息的内容。
图片消息ImageMessageMediaMessageContent图片消息的内容,支持发送原图。
文件消息FileMessageMediaMessageContent文件消息的内容。
语音消息HQVoiceMessageMediaMessageContent高清语音消息的内容。
提及他人(@ 消息)不适用不适用@消息并非预定义的消息类型。详见如何发送 @ 消息

以上为 IMLib SDK 内置的部分消息内容类型。您还可以创建自定义的消息内容类型,并使用 sendMessage 方法或sendMediaMessage 方法发送。详见自定义消息类型

重要

  • 发送普通消息使用 sendMessage 方法,发送媒体消息使用 sendMediaMessage 方法。
  • 客户端 SDK 发送消息存在频率限制,每秒最多只能发送 5 条消息。

本文使用 IMLib SDK 核心类 IMEngine 的发送消息方法。

普通消息

普通消息指文本消息等不涉及媒体文件上传的消息。普通消息的消息内容为 MessageContent 的子类的消息,例如文本消息内容(TextMessage),或自定义类型的普通消息内容。

构造普通消息

在发送前,需要先构造 Message 对象。conversationType 字段为会话类型。targetId 表示会话的目标 ID。以下示例中构造了一条包含文本消息内容(TextMessage)的消息对象。

    let conId = new ConversationIdentifier();
conId.conversationType = ConversationType.Private;
conId.targetId = "会话 id";

let textMsg = new TextMessage();
textMsg.content = "文本消息的内容";


let msg = new Message(conId, textMsg);

发送普通消息

如果 Message 对象包含普通消息内容,使用 IMLib SDK 核心类 IMEnginesendMessage 方法发送消息。


let option: ISendMsgOption = {};

IMEngine.getInstance()
.sendMessage(msg, option, (msg: Message) => {
// 消息入库
})
.then(result => {
if (EngineError.Success !== result.code) {
// 发送消息失败
return;
}
if (!result.data) {
// 消息数据为空
return;
}
let msg = result.data as Message;
})

sendMessage方法使用消息推送属性配置 PushConfig,其中包含了 pushContentpushData。详见远程推送通知

关于是否需要配置输入参数或 MessagepushConfig 属性中 pushContent,请参考以下内容:

参数类型说明
messageMessage要发送的消息体。必填属性包括会话类型(conversationType),会话 ID(targetId),消息内容(content)。详见[消息介绍] 中对 Message 的结构说明。
optionISendMsgOption发送消息配置,目前为空

通过 IMEnginesendMessage 方法的,融云服务器始终会通知您的消息是否已发送成功。当因任何问题导致发送失败时,可通过回调方法返回异常。

提示

媒体消息

媒体消息的发送参考: 发送媒体消息

如何发送 @ 消息

@消息在融云即时通讯服务中不属于一种预定义的消息类型(详见服务端文档 [消息类型概述])。融云通过在消息中携带 MentionedInfo 数据,帮助 App 实现提及他人(@)功能。

消息的 MessageContent 中的 [MentionedInfo] 字段存储了携带所 @ 人员的信息。无论是 SDK 内置消息类型,或者您自定义的消息类型,都直接或间接继承了 MessageContent 类。

融云支持在向群组超级群中发消息时,在消息内容中添加 MentionedInfo。消息发送前,您可以构造 MentionedInfo,并设置到消息的 MessageContent 中。

// @ 所有人
let textMsg = new TextMessage();
textMsg.content = "from 鸿蒙 ";
textMsg.extra = "TestExtra";

// 消息 @ 所有人
let mentionedInfo = new MentionedInfo();

// @ 类型为 @ 所有人
mentionedInfo.type = MentionedType.ALL;

// 把 @ 信息塞给消息体
textMsg.mentionedInfo = mentionedInfo;
// @ 部分用户
let textMsg = new TextMessage();
textMsg.content = "from 鸿蒙 ";
textMsg.extra = "TestExtra";

// 消息的 @ 信息
let mentionedInfo = new MentionedInfo();

// @ 类型为 @ 部分用户
mentionedInfo.type = MentionedType.PART;

// 保存 @ 的用户 id 列表
let userIdList = new Array<string>();
userIdList.push("TestUserId");
mentionedInfo.userIdList = userIdList;

// 把 @ 信息塞给消息体
textMsg.mentionedInfo = mentionedInfo;

MentionedInfo 参数:

参数类型说明
typeMentionedType(必填)指定 MentionedInfo 的类型。MentionedType.ALL 表示需要提及(@)所有人。MentionedType.PART 表示需要 @ 部分人,被提及的人员需要在 userIdList 中指定。
userIdListList<String>被提及(@)用户的 ID 集合。当 typeMentionedType.PART 时必填
mentionedContentString触发离线消息推送时,通知栏显示的内容。如果是 null,则显示默认提示内容(“有人 @ 你”)。@消息携带的 mentionedContent 优先级最高,会覆盖所有默认或自定义的 pushContent 数据。

以下示例展示了发送一条提及部分用户的文本消息,该消息发往一个群聊会话。

let conId = new ConversationIdentifier();
conId.conversationType = ConversationType.Group;
conId.targetId = "TestTargetId"; // 按需填写实际的会话 id


let textMsg = new TextMessage();
textMsg.content = "from 鸿蒙 ";
textMsg.extra = "TestExtra";

// 消息 @ 所有人
let mentionedInfo = new MentionedInfo();

// @ 类型为 @ 所有人
mentionedInfo.type = MentionedType.ALL;

// 把 @ 信息塞给消息体
textMsg.mentionedInfo = mentionedInfo;

let msg = new Message(conId, textMsg);

let option: ISendMsgOption = {};

IMEngine.getInstance()
.sendMessage(msg, option, (msg: Message) => {
// 消息入库
})
.then(result => {
if (EngineError.Success !== result.code) {
// 发送消息失败
return;
}
if (!result.data) {
// 消息数据为空
return;
}
let msg = result.data as Message;
})

IMLib SDK 接收消息后,您需要处理 @ 消息中的数据。您可以在获取 Message(消息对象)后,通过以下方法获取到消息对象携带的 MentionedInfo 对象。

let mentionedInfo = msg.content.mentionedInfo;

远程推送通知

提示

聊天室会话不支持离线消息机制,因此也不支持离线消息转推送。

如果您的应用已经在融云配置鸿蒙推送,在消息接收方离线时,融云服务端会根据消息类型、接收方支持的推送通道、接收方的免打扰设置等,决定是否触发远程推送。

远程推送通知一般会展现在系统的通知栏。融云内置的消息类型默认会在通知栏展现通知标题和通知内容。关于各类型消息的默认推送通知内容,详见用户内容类消息格式

如果您需要个性化的离线推送通知,可以通过以下方式,修改或指定远程推送的通知标题、通知内容其他属性。

  • sendMessagesendMediaMessage 方法,请使用 Message 的推送属性(pushConfig)方法进行配置。

配置消息推送属性

在发送消息时,您可以通过设置消息的 PushConfig 对象,对单条消息的推送行为进行个性化配置。例如:

  • 自定义推送标题、推送通知内容

pushConfig 中的配置具有更高优先级。发送消息时,如已配置 pushConfig,则优先使用 pushConfig 中的配置。

// 创建会话标识
let conId = new ConversationIdentifier();
conId.conversationType = ConversationType.Private;
conId.targetId = "TestTargetId"; // 按需填写实际的会话 id

// 创建文本消息
let textMsg = new TextMessage();
textMsg.content = "from 鸿蒙 ";
textMsg.extra = "TestExtra";

let option: ISendMsgOption = {};

// 创建消息体
let msg = new Message(conId, textMsg);

// 按需创建推送配置
let pushConfig = new PushConfig();
pushConfig.pushTitle = "TestPushTitle";
pushConfig.pushContent = "TestPushContent";
pushConfig.pushData = "TestPushData";
msg.pushConfig = pushConfig;

// 请根据消息类型调用对应的发送方法

pushConfig 属性说明如下:

/**
* 推送配置
* @version 1.0.0
*/
class PushConfig {
/**
* ```
* 通知栏是否屏蔽通知标题(true: 不显示通知标题;false: 显示通知标题)
* 默认情况下融云单聊消息通知标题为用户名、群聊消息为群名称,设置后不会再显示通知标题。
* 此属性只针目标用户为 iOS 平台时有效,Android 第三方推送平台的通知标题为必填项,所以暂不支持
* ```
* @version 1.1.0
*/
disablePushTitle : boolean;
/**
* 推送标题
*
* 如果没有设置,会使用下面的默认标题显示规则:
*
* 内置消息:单聊通知标题显示为发送者名称,群聊通知标题显示为群名称。
*
* 自定义消息:默认不显示标题。
*/
pushTitle: string = "";
/**
* 推送内容
*/
pushContent: string = "";
/**
* 远程推送附加信息
*/
pushData: string = "";

/**
* 是否强制显示通知详情。推送越权设置,当目标用户设置推送不显示消息详情时,可通过此功能,强制设置该条消息显示推送详情。
* @version 1.1.0
*/
forceShowDetailContent : boolean;

/**
* iOS 推送配置
* @version 1.1.0
*/
iosConfig: IosConfig;

/**
* Android 推送配置
* @version 1.1.0
*/
androidConfig: AndroidConfig;

/**
* HarmonyOS 推送配置
* @version 1.1.0
*/
harmonyConfig: HarmonyConfig;
}

IosConfig 属性说明如下:

/**
* iOS 推送配置
* @version 1.1.0
*/
class IosConfig {
/**
* iOS 平台通知栏分组 ID
*
* 相同的 thread-id 推送分为一组
*
* iOS10 开始支持
*/
threadId: string = "";
/**
* iOS 标识推送的类型
*
* 如果不设置后台默认取消息类型字符串,如 RC:TxtMsg
*/
category: string = "";
/**
* iOS 平台通知覆盖 ID
*
* apnsCollapseId 相同时,新收到的通知会覆盖老的通知,最大 64 字节
*
* iOS10 开始支持
*/
apnsCollapseId: string = "";
/**
* iOS 富文本推送内容
*/
richMediaUri: string = "";
/**
* iOS 推送级别. 默认值 "active"
* ```
* 可选值为:"passive" 、 "active" 、"time-sensitive" 、 "critical"
* "passive" 被动通知:即并不需要及时关注的通知,类似餐馆推荐通知
* "active" 主动通知(默认的):默认的通知,即人们可能想知道的,类似最喜欢的体育比赛的最新比分
* "time-sensitive" 时效性通知:需要人们立刻注意的通知,类似账户安全问题或快递动态
* "critical" 重要通知:关于个人健康或直接影响到设备拥有者的公共安全事件且需要立刻关注的,这类通知很少,一般是来自公共政府机构或健康 App。
* ```
*/
interruptionLevel: string = "active";
}

AndroidConfig 属性说明如下:

/**
* Android 推送配置
* @version 1.1.0
*/
class AndroidConfig {
/**
* Android 平台 Push 唯一标识
*
* 目前支持小米、华为推送平台,默认开发者不需要进行设置,当消息产生推送时,消息的 messageUId 作为 notificationId 使用。
*/
notificationId: string = "";


// 小米配置*************************************************

/**
* 小米的渠道 ID
*
* 该条消息针对小米使用的推送渠道,如开发者集成了小米推送,需要指定 channelId 时,可向 Android 端研发人员获取,channelId 由开发者自行创建。
*/
miChannelId: string = "";


// 华为配置*************************************************

/**
* 华为的渠道 ID
*
* 该条消息针对华为使用的推送渠道,如开发者集成了华为推送,需要指定 channelId 时,可向 Android 端研发人员获取,channelId 由开发者自行创建。
*/
hwChannelId: string = "";
/**
* 华为推送消息级别
*
* 消息级别包括 "NORMAL", "LOW"
*/
hwImportance: string = "";
/**
* 华为通知栏消息右侧大图标 URL
*/
hwImageUrl: string = "";
/**
* 华为推送消息分类:
* ```
* - 社交通讯:即时通讯[IM],音频、视频通话[VOIP]
* - 服务提醒:订阅[SUBSCRIPTION],出行[TRAVEL],健康[HEALTH],工作事项提醒[WORK],帐号动态[ACCOUNT],订单&物流[EXPRESS],财务[FINANCE],系统提示[SYSTEM_REMINDER],邮件[MAIL]
* - 资讯营销类:内容资讯/新闻/财经动态/生活资讯/社交动态/调研/其他[MARKETING]
* - 营销活动:产品促销/功能推荐/运营活动/MARKETING
* 更多信息请参考华为消息分类标准文档: https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/message-classification-0000001149358835
*```
* 默认值为 null,如果为 null,则以服务配置为准
*/
hwCategory: string = "";


// 荣耀配置*************************************************
/**
* 荣耀推送消息级别
*
* 消息级别包括 "NORMAL", "LOW"
*/
honorImportance: string = "";
/**
* 荣耀通知栏消息右侧大图标 URL
*/
honorImageUrl: string = "";


// OPPO 配置*************************************************
/**
* OPPO 的渠道 ID
*
* 该条消息针对 OPPO 使用的推送渠道,如开发者集成了 OPPO 推送,需要指定 channelId 时,可向 Android 端研发人员获取,channelId 由开发者自行创建。
*/
oppoChannelId: string = "";


// VIVO 配置*************************************************

/**
* VIVO 推送消息分类
*```
* 系统消息分类
* 即时消息[IM],账号与资产[ACCOUNT],日程待办[TODO],设备信息[DEVICE_REMINDER],订单与物流[ORDER],订阅提醒[SUBSCRIPTION]
* 运营消息分类
* 新闻[NEWS],内容推荐[CONTENT],运营活动[MARKETING],社交动态[SOCIAL]
* 更多信息请参考 VIVO 消息分类标准文档: https://dev.vivo.com.cn/documentCenter/doc/359
*```
* 默认值为 null,如果为 null,则以服务配置为准
*/
vivoCategory: string = "";
/**
* VIVO 推送通道类型
*
* 开发者集成了 VIVO 推送,需要指定推送类型时,可进行设置。
*
* 目前可选值 "0"(运营消息) 和 "1"(系统消息)
*/
vivoType: string = "";


// FCM 配置*************************************************

/**
* FCM 通知的频道 ID
*
* 该应用程序必须使用此频道 ID 创建一个频道,然后才能收到带有该频道 ID 的任何通知。如果您未在请求中发送此频道 ID,或者如果应用尚未创建提供的频道 ID,则 FCM 使用应用清单中指定的频道 ID。
*/
fcmChannelId: string = "";
/**
* FCM 通知类型推送时所使用的分组 id
*/
fcmCollapseKey: string = "";
/**
* FCM 通知类型的推送所使用的通知图片 URL
*/
fcmImageUrl: string = "";
}

HarmonyConfig 属性说明如下:

/**
* HarmonyOS 推送配置
* @version 1.1.0
*/
class HarmonyConfig {
/**
* HarmonyOS 通知栏消息右侧大图标 URL
* 通知栏右侧图片,格式支持 png、jpg,图片长*宽 < 25000 像素,图片不满足要求的情况下,终端不能显示通知消息。
*/
imageUrl: string = "";
/**
* HarmonyOS 推送消息分类:
* 社交通讯:消息自分类标识,默认为空。category 取值必须为大写字母
* 默认值为 null,如果为 null,则以服务配置为准
* 更多信息请参考鸿蒙通知消息分类标准文档: https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/message-classification-0000001149358835
*/
category: string = "";
}

自定义消息如何支持远程推送

融云为内置的消息类型默认支提供了远程通知标题和通知内容(详见用户内容类消息格式)。不过,如果您发送的是自定义类型的消息,则需要您自行提供 pushContent 字段,否则用户无法收到离线推送通知。具体如下:

  • 如果消息类型为自定义消息类型,且需要支持离线推送通知,则必须向融云提供 PushConfig.pushContent 字段,否则用户无法收到离线推送通知。
  • 如果消息类型为自定义消息类型,但不需要支持远程推送通知(例如通过自定义消息类型实现的 App 业务层操作指令),可将 PushConfig.pushContent 字段留空。
提示

如果要自定义消息启用离线推送通知能力,请务必发送消息的入参或消息推送属性向融云提供 PushConfig.pushContent 字段内容,否则接收方用户无法收到离线推送通知。

为消息禁用推送通知

鸿蒙暂不支持禁用消息推送

如何透传自定义数据

如果应用需要将自定义数据透传到对端,可通过以下方式实现:

  • 消息内容 MessageContent 的附加信息字段,该字段会随即时消息一并发送到对端。接收方在线接收消息后,可从消息内容中获取该字段。请区别于 Message.extraMessage.extra 为本地操作的字段,不会被发往服务端。

如何处理消息发送失败

对于客户端本地会存储的消息类型(参见[消息类型概述]),如果触发消息入库回调,表示此时该消息已存入本地数据库,并已进入本地消息列表。

  • 如果入库失败,您可以检查参数是否合法,设备存储是否可正常写入。
  • 如果入库成功,但消息发送失败,App 可以在 UI 临时展示这条发送失败的消息,并缓存失败的 Message 实例,在合适的时机重新调用 sendMessage / sendMediaMessage 发送。请注意,如果不复用该消息实例,而是重发相同内容的新消息,本地消息列表中会存储内容重复的两条消息。

对于客户端本地不存储的消息,如果发送失败,App 可缓存消息实例再重试发送,或直接新建消息实例进行发送。

如何实现转发、群发消息

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

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

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