Staticget初始化 SDK
整个 App 生命周期内,原则上 SDK 只能初始化一次
SDK 允许调用该方法重复初始化 SDK,但是我们不建议这么做
因为 SDK 重复初始化之后,之前的连接、监听等均会失效,需要将初始化后的操作重新做一遍,如重新连接,并重新设置各种监听
// 在 UIAbility 中获取 context
let context = this.context
let initOption = new InitOption();
let appKey = "从融云后台获取的 appKey";
IMEngine.getInstance().init(context, appKey, initOption);
上下文,为空则初始化失败
融云 appKey,为空则初始化失败
初始化配置,见 InitOption
获取本地时间与服务器时间的时间差。 通过当前本地时间减去此接口返回的时间,即当前服务器时间。
IMEngine.getInstance().getDeltaTime().then(result => {
  if (EngineError.Success === result.code) {
    let deltaTime = result.data as number
  }
});
本地时间与服务器时间的时间差。
上设置断线重连时是否踢出重连设备。
用户没有开通多设备登录功能的前提下,同一个账号在一台新设备上登录的时候,会把这个账号在之前登录的设备上踢出。
由于 SDK 有断线重连功能,存在下面情况: 用户在 A 设备登录,A 设备网络不稳定,没有连接成功,SDK 启动重连机制。 用户此时又在 B 设备登录,B 设备连接成功。 A
设备网络稳定之后,用户在 A 设备连接成功,B 设备被踢出。 这个接口就是为这种情况加的。
let kickEnable = true;
IMEngine.getInstance().setReconnectKickEnable(kickEnable);
设置为 true 时,SDK 重连的时候发现此时已有别的设备连接成功,踢出当前重连设备,不再强行踢出别的设备
设置鸿蒙推送 token
1. SDK 初始化之前设置:SDK 会将推送 token 缓存,连接成功后上报
2. SDK 初始化之后连接之前设置:连接成功后 SDK 自动上报
3. SDK 连接成功后设置:SDK 立即上报
import { pushService } from '@kit.PushKit';
pushService.getToken((error: BusinessError, token: string) => {
 if (token) {
   IMEngine.getInstance().setPushToken(token);
 }
});
推送 token
设置数据库状态监听
数据库打开的时机:参考 DatabaseStatusListener.onDatabaseStatusChange()
IMEngine.getInstance().setDatabaseStatusListener((status: DatabaseStatus) => {
 hilog.info(0x0000, 'IM-App', 'setDatabaseStatusListener onChanged status:%{public}d', status);
});
监听
增加数据库状态监听
数据库打开的时机:参考 DatabaseStatusListener.onDatabaseStatusChange()
let dbListener: DatabaseStatusListener = {
 onDatabaseStatusChange: (status: DatabaseStatus): void => {
   // status 为具体的数据库状态
 }
}
IMEngine.getInstance().addDatabaseStatusListener(dbListener);
监听
监听
设置控制台日志级别
例如:填入 LogLevel.None ,SDK 将不再控制台输出日志
例如:填入 LogLevel.Warn ,SDK 将会在控制台输出 Warn 和 Error 的日志
IMEngine.getInstance().setLogLevel(LogLevel.Info)
日志级别,用于过滤控制台的日志输出,初始化之后设置
连接 IM
调用该接口,SDK 会在 timeLimit 秒内尝试重连,直到出现下面三种情况之一
第一、连接成功,回调 IConnectResult.code === EngineError.Success
第二、超时,回调 IConnectResult.code === EngineError.ConnectionTimeout,需要手动调用该接口继续连接
第三、出现 SDK 无法处理的错误,回调 IConnectResult.code 为具体的错误码
常见的错误如下:
ClientNotInit :SDK 没有初始化,请先调用 init 接口
NaviRespTokenIncorrect :检查一下 APP 使用的 appKey 和 APP Server 使用的 appKey 是否相同
ConnectTokenIncorrect :检查一下 APP 使用的 appKey 和 APP Server 使用的 appKey 是否相同
ConnectOneTimePasswordUsed :重新请求 Token
ConnectPlatformError :重新请求 Token
ConnectTokenExpired :重新请求 Token
ConnectAppBlockOrDelete : 给用户提示 AppKey 已经封禁或删除
ConnectUserBlocked :给用户提示被封禁
DisconnectUserKicked :给用户提示被提掉线
DisconnectUserBlocked :给用户提示被封禁
ConnectUserDeleteAccount :给用户提示已销号
let token = "IMToken";
let timeout = 5;
IMEngine.getInstance().connect(token, timeout).then(result => {
 if (EngineError.Success === result.code) {
   // 连接成功
   let userId = result.userId;
   return;
 }
 if (EngineError.ConnectTokenExpired === result.code) {
   // Token 过期,从 APP 服务请求新 token,获取到新 token 后重新 connect()
 } else if (EngineError.ConnectionTimeout === result.code) {
   // 连接超时,弹出提示,可以引导用户等待网络正常的时候再次点击进行连接
 } else {
   //其它业务错误码,请根据相应的错误码作出对应处理。
 }
});
从您服务器端获取的 token (用户身份令牌)
超时时间,整型,单位秒,timeout <= 0:不设置超时时长,一直连接直到成功或失败;timeout > 0: 在对应的时间内连接未成功则返回超时错误
连接结果
设置连接状态监听
每个连接状态都有详细的描述和处理意见,参考 ConnectionStatusListener.onConnectionStatusChanged()
IMEngine.getInstance().setConnectionStatusListener((status: ConnectionStatus) => {
 // status 为具体的连接状态
});
监听
增加连接监听。每个连接状态都有详细的描述和处理意见
每个连接状态都有详细的描述和处理意见,参考 ConnectionStatusListener.onConnectionStatusChanged()
 let statusListener: ConnectionStatusListener = {
   onConnectionStatusChanged: (status: ConnectionStatus): void => {
     // status 为具体的连接状态
   }
 }
 IMEngine.getInstance().addConnectionStatusListener(statusListener);
监听
连接监听
获取当前连接状态
 IMEngine.getInstance().getCurrentConnectionStatus().then(result => {
   if (EngineError.Success !== result.code) {
     // 获取当前连接状态失败
     return;
   }
   if (!result.data) {
     // 获取的当前连接状态为空
     return;
   }
   let status = result.data as ConnectionStatus;
 });
连接状态
获取当前用户 ID
 IMEngine.getInstance().getCurrentUserId().then(result => {
   if (EngineError.Success !== result.code) {
     // 获取用户 ID 失败
     return;
   }
   if (!result.data) {
     // 获取的用户 ID 为空
     return;
   }
   let userId = result.data as string;
 });
连接成功后才会有值
设置消息接收监听
 IMEngine.getInstance().setMessageReceivedListener((message: Message, info: ReceivedInfo) => {
   //  针对接收离线消息时,服务端会将 200 条消息打成一个包发到客户端,客户端对这包数据进行解析。该参数表示每个数据包数据逐条上抛后,还剩余的条数
   let left = info.left;
   // 消息是否离线消息
   let isOffline = info.isOffline;
   // 是否在服务端还存在未下发的消息包
   let hasPackage = info.hasPackage;
 });
监听
添加消息接收监听,可以添加多个监听
 let messageReceiveListener: MessageReceivedListener = {
   onMessageReceived: (message: Message, info: ReceivedInfo): void => {
     // 收到了单条消息
   },
   onOfflineMessageSyncCompleted: (): void => {
     // 离线消息已全部拉取完成
   }
 };
 IMEngine.getInstance().addMessageReceivedListener(messageReceiveListener);
监听
监听
设置消息撤回监听,撤回了之后,原始消息会变成 RecallNotificationMessage 消息
IMEngine.getInstance().setMessageRecalledListener((message: Message, recallMessage: RecallNotificationMessage) => {
});
监听
增加消息撤回监听。撤回了之后,原始消息会变成 RecallNotificationMessage 消息
 let recalledListener : MessageRecalledListener = {
   onMessageRecalled: (message: Message, recallMessage: RecallNotificationMessage): void => {
     // 消息撤回
   }
 }
 IMEngine.getInstance().addMessageRecalledListener(recalledListener);
监听
监听
设置消息敏感词拦截监听
 IMEngine.getInstance().setMessageBlockedListener((blockInfo: MessageBlockInfo) => {
 });
监听
增加消息敏感词拦截监听
 let blockedListener : MessageBlockedListener = {
   onMessageBlocked: (blockInfo: MessageBlockInfo): void => {
   }
 }
 IMEngine.getInstance().addMessageBlockedListener(blockedListener);
监听
监听
发送消息
如果遇到 DatabaseNotOpened = 34301 ,原因是在 IM 连接成功前发送了消息
IM 连接成功后 SDK 才会打开对应用户的消息数据库
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "会话 id";
 let textMsg = new TextMessage();
 textMsg.content = "文本消息的内容";
 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;
 })
消息对象
消息发送的配置
消息入库的回调
消息发送结果
发送媒体消息
如果遇到 DatabaseNotOpened = 34301 ,原因是在 IM 连接成功前发送了消息
IM 连接成功后 SDK 才会打开对应用户的消息数据库
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "会话 id";
 let imgMsg = new ImageMessage();
 // 使用沙盒路径创建图片消息。系统路径的图片 SDK 无法访问(例如相册的图片路径 SDK 就无法访问)
 imgMsg.localPath = localPath;
 let msg = new Message(conId, imgMsg);
 let option: ISendMsgOption = {};
 IMEngine.getInstance().sendMediaMessage(msg, option, (msg: Message) => {
   // 消息保存到数据库
 }, (msg: Message, progress: number) => {
   // 媒体上传进度 [1 ~ 100]
 }).then(result => {
   if (EngineError.Success !== result.code) {
     //发送消息失败
     return;
   }
   if (!result.data) {
     // 消息为空
     return;
   }
   let msg = result.data as Message;
 })
消息体
消息发送的配置
消息入库的回调
媒体文件上传进度
媒体消息发送结果
使用自定义上传发送媒体消息
如果遇到 DatabaseNotOpened = 34301 ,原因是在 IM 连接成功前发送了消息
IM 连接成功后 SDK 才会打开对应用户的消息数据库
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "会话 id";
 let imgMsg = new ImageMessage();
 // 使用沙盒路径创建图片消息。系统路径的图片 SDK 无法访问(例如相册的图片路径 SDK 就无法访问)
 imgMsg.localPath = localPath;
 let msg = new Message(conId, imgMsg);
 let option: ISendMsgOption = {};
 IMEngine.getInstance().sendMediaMessageWithUploader(msg, option, (msg: Message) => {
   // 消息保存到数据库
 }, (msg: Message, progress: number) => {
   // 媒体上传进度 [1 ~ 100]
 }, (uploader: MediaMessageTransfer) => {
   // app 需要在该回调里面做上传业务,并把上传进度,上传结果通知 sdk
   // 此处 for 循环模拟上传进度。实际应该是 app 真实的上传进度
   for (let index = 1; index < 101; index++) {
     // 这里的进度取值范围必须是 [1 ~ 100]
     uploader.updateProgress(index);
   }
   // 模拟 app 是否上传媒体成功
   let appUploadSuccess = true;
   if (appUploadSuccess) {
     // app 上传媒体成功了,调用 uploader.success 通知 sdk 上传成功了,sdk 就会将该消息带着远端 url 直接发送出去
     uploader.success("https://exmaple.com/123.jpg");
   }else {
     // 如果 app 上传失败,调用 uploader.error 通知 sdk 上传失败了,sdk 会触发失败回调
     uploader.error();
   }
 }).then(result => {
   if (EngineError.Success !== result.code) {
     //发送消息失败
     return;
   }
   if (!result.data) {
     // 消息为空
     return;
   }
   let msg = result.data as Message;
 })
消息体
消息发送的配置
消息入库的回调
媒体文件上传进度
OptionaluploadCallback: (uploader: MediaMessageTransfer) => void[可选参数]自定义媒体文件上传回调,如果此参数不传则执行SDK默认流程
媒体消息发送结果
取消发送媒体消息下载
 let messageId = 123;
 IMEngine.getInstance().cancelSendMediaMessage(messageId).then(result => {
   if (EngineError.Success === result.code) {
     // 取消发送媒体消息成功
   } else {
     // 取消发送媒体消息成功失败
   }
 });
消息 Id
取消发送媒体消息结果
发送普通定向消息
此方法用于在群组中发送消息给其中的部分用户,其它用户不会收到这条消息。
如果遇到 DatabaseNotOpened = 34301 ,原因是在 IM 连接成功前发送了消息
IM 连接成功后 SDK 才会打开对应用户的消息数据库
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Group;
 conId.targetId = "群组 id";
 let textMsg = new TextMessage();
 textMsg.content = "文本消息的内容";
 let msg = new Message(conId, textMsg);
 let option: ISendMsgOption = {};
 // 填入实际的用户 id
 let userIdArray = ["userId1", "userId2"];
 IMEngine.getInstance().sendDirectionalMessage(msg, option, userIdArray, (msg: Message) => {
     // 消息入库回调
   }).then(result => {
     if (EngineError.Success !== result.code) {
       // 发送消息失败
       return;
     }
     if (!result.data) {
       // 消息数据为空
       return;
     }
     let msg = result.data as Message;
 })
消息对象
消息发送的配置
消息指定接收者
消息入库的回调,
消息发送结果
发送媒体定向消息
此方法用于在群组中发送消息给其中的部分用户,其它用户不会收到这条消息。
如果遇到 DatabaseNotOpened = 34301 ,原因是在 IM 连接成功前发送了消息
IM 连接成功后 SDK 才会打开对应用户的消息数据库
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Group;
 conId.targetId = "群组 id";
 let imgMsg = new ImageMessage();
 // 使用沙盒路径创建图片消息。系统路径的图片 SDK 无法访问(例如相册的图片路径 SDK 就无法访问)
 imgMsg.localPath = localPath;
 let msg = new Message(conId, imgMsg);
 let option: ISendMsgOption = {};
 // 填入实际的用户 id
 let userIdArray = ["userId1", "userId2"];
 IMEngine.getInstance().sendDirectionalMediaMessage(msg, option, userIdArray, (msg: Message) => {
   // 消息保存到数据库
 }, (msg: Message, progress: number) => {
   // 媒体上传进度 [1 ~ 100]
 }).then(result => {
   if (EngineError.Success !== result.code) {
     //发送消息失败
     return;
   }
   if (!result.data) {
     // 消息为空
     return;
   }
   let msg = result.data as Message;
 })
消息体
消息发送的配置
消息指定接收者
消息发送的配置
媒体文件上传进度
媒体消息发送结果
下载媒体消息
 let messageId = 234;
 IMEngine.getInstance().downloadMediaMessage(messageId).then(result => {
   if (EngineError.Success === result.code) {
     // 本地路径
     let localPath = result.data as string;
   }
 });
消息 id,对应的消息必须是 MediaMessageContent 子类
媒体消息下载成功的本地路径,存储路径见 InitOption.mediaSavePath
下载媒体消息,含下载进度
 let messageId = 123;
 IMEngine.getInstance().downloadMediaMessageWithProgress(messageId, (messageId: number, progress: number) => {
   // 下载进度,取值范围 [0 , 100]
 }).then(result => {
   if (EngineError.Success === result.code) {
     // 本地路径
     let localPath = result.data as string;
   }
 });
消息 Id,对应的消息必须是 MediaMessageContent 子类
下载进度监听,取值范围 [0 , 100]
媒体消息下载成功的本地路径,存储路径见 InitOption.mediaSavePath
使用自定义方法下载媒体消息
 let messageId = 234;
 IMEngine.getInstance().downloadMediaMessageWithDownloader(
   messageId,
   (messageId: number, progress: number) => {
      // 下载进度,取值范围 [0 , 100]
   },
   (downloader: MediaMessageTransfer) => {
     downloadImg(imgMsg.getPicFilePath(), new downloadListener() {
       public onSuccess(localPath: string): void {
         downloader.success(localPath);
       }
     }
   }
 ).then(result => {
   if (EngineError.Success === result.code) {
     // 本地路径
     let localPath = result.data as string;
   }
 });
消息 id,对应的消息必须是 MediaMessageContent 子类
OptionaldownloadCallback: (downloader: MediaMessageTransfer) => void[可选参数]自定义媒体文件下载回调,如果此参数不传则执行SDK默认流程
媒体消息下载成功的本地路径,存储路径见 InitOption.mediaSavePath
暂停媒体消息下载
 let messageId = 123;
 IMEngine.getInstance().pauseDownloadMediaMessage(messageId).then(result => {
   if (EngineError.Success === result.code) {
     // 暂停下载成功,此时 downloadMediaMessageWithProgress 会返回 EngineError.RequestPaused
   } else {
     // 暂停下载失败
   }
 });
消息 Id
暂停下载结果
取消下载媒体消息,配合 downloadMediaMessageWithProgress 方法
 let messageId = 123;
 IMEngine.getInstance().cancelDownloadMediaMessage(messageId).then(result => {
   if (EngineError.Success === result.code) {
     // 下载取消成功,此时 downloadMediaMessageWithProgress 会返回 EngineError.RequestCanceled
   } else {
     // 下载取消失败
   }
 });
消息 Id
取消下载结果
下载文件(带下载进度)
如果是下载媒体消息,请调用 downloadMediaMessageWithProgress 方法,下载成功 SDK 会更新媒体消息的本地路径
不是媒体消息的媒体文件需要下载时,才调用 downloadFileWithProgress
会将 file_name 最后一个 . 之前的特殊替换为下划线。如 abc@123.png 会被替换为 abc_123.png。
如果多次请求 file_name 相同,后一次下载会加入序号,如 abc.png,abc(1).png,abc(2).png。
 let remoteUrl = "https://expamle.com/1.jpg";
 let fileName = "1.jpg";
 IMEngine.getInstance().downloadFileWithProgress(remoteUrl, fileName, (uniqueId: number) => {
   // 开始下载,下载唯一标识 uniqueId
 }, (uniqueId: number, progress: number) => {
   // 下载进度
 }).then(result => {
   if (EngineError.Success !== result.code) {
     // 下载失败
     return;
   }
   if (!result.data) {
     // 下载的本地路径为空
     return;
   }
   // 本地路径
   let localPath = result.data as string;
 });
媒体的远端地址
本地文件名
开始下载。uniqueId 下载唯一标识,可以调用 cancelDownloadFile 取消下载
下载进度监听,取值范围 [0 , 100]
媒体文件下载成功的本地路径,存储路径见 InitOption.mediaSavePath
下载媒体文件
// uniqueId 是下载媒体文件任务的标识,可以用来发起下载、暂停下载和取消下载。
// 与 pauseDownloadMediaFile 和 cancelDownloadFile 中的 uniqueId 保持一致。
let uniqueId = "123"
let remoteUrl = "https://expamle.com/1.jpg";
let fileName = "1.jpg";
IMEngine.getInstance().downloadMediaFile(uniqueId, remoteUrl, fileName,
  (uniqueId: string) => {
    // 开始下载,下载唯一标识 uniqueId
  },
  (uniqueId: string, progress: number) => {
    // 下载进度
}).then(result => {
   if (EngineError.Success !== result.code) {
     // 下载失败
     return;
   }
   if (!result.data) {
     // 下载的本地路径为空
     return;
   }
   // 本地路径
   let localPath = result.data as string;
 });
文件唯一标示
文件的远端地址
本地文件名
下载进度监听,取值范围 [0 , 100]
媒体文件下载成功的本地路径,存储路径见 InitOption.mediaSavePath
暂停下载媒体文件
// messageId 与 downloadMediaFile 的第一个参数对应
let messageId = "123";
 IMEngine.getInstance().pauseDownloadMediaFile(messageId).then(result => {
   if (EngineError.Success === result.code) {
     // 暂停下载成功,此时 downloadMediaFile 会返回 EngineError.RequestCanceled
   } else {
     // 暂停下载失败
   }
 });
下载的结果
取消下载文件,配合 downloadFileWithProgress 方法
 // uniqueId 必须是调用 downloadFileWithProgress 时由 SDK 生成的,此处进行了简写
 let uniqueId = "1234";
 IMEngine.getInstance().cancelDownloadFile(uniqueId).then(result => {
   if (EngineError.Success !== result.code) {
     // 取消下载失败
     return;
   }
   // 取消下载成功,此时 downloadFileWithProgress 会返回 EngineError.RequestCanceled
 })
下载唯一标识
下载的结果
撤回消息
 // 必须用发送成功的消息,此处进行了简写
 let message : Message;
 IMEngine.getInstance().recallMessage(message).then(result => {
   if (EngineError.Success !== result.code) {
     // 消息撤回失败
     return;
   }
   if (!result.data) {
     // 撤回小灰条消息为空
     return;
   }
   // 撤回小灰条消息
   let recallNtfMsg = result.data as RecallNotificationMessage;
 })
需要撤回的消息,发送成功的消息才能撤回(必须有有效的 MessageUid)
撤回成功后的小灰条消息
注册自定义消息,初始化之后,连接之前调用
自定义消息 CustomOrderMessage 示例代码见 MessageContent
自定义媒体消息 CustomFileMessage 示例代码见 MediaMessageContent
let clazzList: List<MessageContentConstructor> = new List();
clazzList.add(CustomOrderMessage);
IMEngine.getInstance().registerMessageType(clazzList);
自定义消息数组
获取 SDK 中所有的消息 objectName 和存储标识的映射关系
1. 映射关系集合包含 内置消息 和 自定义消息
2. 必须在所有自定义消息注册完成之后再调用该方法,否则会导致无法正确获取自定义消息的映射关系
3. 不要频繁调用该方法:建议 app 调用该方法之后, app 自行保存整个集合
iOS 通过 RCMessagePersistentCompatible.persistentFlag 获取消息存储标识
Android 通过 getClass().getAnnotation(MessageTag.class) 获取消息存储标识
鸿蒙需要通过本方法获取
1. 发送消息时需要手动构造指定的消息体,可以直接获取到 objectName:例如创建文本消息时一定知道是文本消息的 objectName
2. 接收消息时通过 Message 对象获取:Message.objectName
3. 读取会话时通过 Conversation 对象获取:Conversation.objectName
let hashMap = IMEngine.getInstance().getMessageTypeMap();
映射关系集合。 key :objectName 、 value : MessageFlag
消息批量入库(多用于数据迁移)
conversationType   会话类型
targetId           会话 ID
channelId          所属会话的业务标识,长度限制 20 字符
direction          消息方向
senderId           发送者 ID
receivedStatus     接收状态:direction 为 Receive 且 receivedStatus.isRead 为 false 时,会话未读数累加
sentStatus         发送状态
sentTime           发送时间
content            消息内容
objectName         消息类型,设置 content 的时候 SDK 会自动赋值对应的 objectName
messageUid         服务端生产的消息唯一 ID,如要携带该字段需要保证入库后是唯一的
extra              扩展信息
canIncludeExpansion 是否支持消息扩展
expansion           消息扩展内容
 // 必须是有效的消息集合,此处进行了简写
 let msgList : List<Message> ;
 IMEngine.getInstance().batchInsertMessage(msgList).then(result => {
   if (EngineError.Success !== result.code) {
     // 批量入库失败
     return;
   }
   // 批量入库成功
 });
需要入库的消息,范围 [1 ~ 500],会话类型不支持聊天室和超级群
入库结果
单条消息入库
conversationType   会话类型
targetId           会话 ID
direction          消息方向,默认为发送
senderId           发送者 ID
receivedStatus     接收状态:direction 为 Receive 且 receivedStatus.isRead 为 false 时,会话未读数累加
sentStatus         发送状态,默认为发送失败
sentTime           发送时间
content            消息内容
objectName         消息类型,设置 content 的时候 SDK 会自动赋值对应的 objectName
messageUid         服务端生产的消息唯一 ID,如要携带该字段需要保证入库后是唯一的
extra              扩展信息
canIncludeExpansion 是否支持消息扩展
expansion           消息扩展内容
 // 必须是有效的消息对象,此处进行了简写
 let msg : Message;
 IMEngine.getInstance().insertMessage(msg).then(result => {
   if (EngineError.Success !== result.code) {
     // 入库失败
     return;
   }
   if (!result.data) {
     // 入库的消息体为空
     return;
   }
   // 入库成功的消息,含有效的 messageId
   let dbMsg = result.data as Message;
 });
入库结果
批量获取本地和远端消息,支持单聊、群聊、系统消息。
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 let option: IHistoryMessageOption = {
   sendTime: 0,
   count: 100,
   order: Order.Ascending
 }
 IMEngine.getInstance().getMessages(conId, option).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取历史消息失败
     return;
   }
   if (!result.data) {
     // 获取历史消息为空
     return;
   }
   // 获取到有效的历史消息
   let dbMsg = result.data as HistoryMessageResult;
 })
会话标识
历史消息选项
历史消息数据,详见 HistoryMessageResult
通过 messageId 获取单条消息
 let messageId = 123;
 IMEngine.getInstance().getMessageById(messageId).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取本地消息失败
     return;
   }
   if (!result.data) {
     // 获取本地消息为空
     return;
   }
   // 获取到有效的本地消息
   let dbMsg = result.data as Message;
 })
消息的本地数据库自增 ID
消息数据
通过 messageUid 获取单条消息
 let messageUid = "CH2C-A072-OGM5-E3HL";
 IMEngine.getInstance().getMessageByUid(messageUid).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取本地消息失败
     return;
   }
   if (!result.data) {
     // 获取本地消息为空
     return;
   }
   // 获取到有效的本地消息
   let dbMsg = result.data as Message;
 })
消息发送成功后的服务唯一 ID,固定格式的字符串,例如 : CH2C-A072-OGM5-E3HL
消息数据
获取批量本地消息,基于 messageId 获取
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 let option: IGetLocalMsgByIdOption = {
   messageId: 100,
   beforeCount: 5,
   afterCount: 5
 }
 IMEngine.getInstance().getHistoryMessagesById(conId, option).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取消息失败
     return;
   }
   if (!result.data) {
     // 消息不存在
     return;
   }
   // 消息体集合
   let msgList = result.data as List<Message>;
 });
会话标识
配置
返回本地消息结果
获取批量本地消息,基于 time 获取
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 let option: IGetLocalMsgByTimeOption = {
   time: Date.now(),
   beforeCount: 5,
   afterCount: 5
 };
 IMEngine.getInstance().getHistoryMessagesByTime(conId, option).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取消息失败
     return;
   }
   if (!result.data) {
     // 消息不存在
     return;
   }
   // 消息列表
   let msgList = result.data as List<Message>;
 });
会话标识
配置
返回本地消息结果
获取批量远端消息
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 let option: IGetRemoteMsgOption = {
   time: Date.now(),
   count: 10,
   order: Order.Descending,
   isCheckDup: true
 }
 IMEngine.getInstance().getRemoteHistoryMessages(conId, option).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取聊天室消息失败
     return;
   }
   if (!result.data) {
     // 消息数据为空
     return;
   }
   // 消息列表
   let msgList = result.data as List<Message>;
 });
会话标识
配置
返回远端消息结果
获取本地会话中 @ 自己的未读消息列表
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 let option: ICountOption = {
   count: 10,
   order: Order.Descending
 };
 IMEngine.getInstance().getUnreadMentionedMessages(conId, option).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取消息失败
     return;
   }
   if (!result.data) {
     // 消息不存在
     return;
   }
   // 消息列表
   let msgList = result.data as List<Message>;
 });
会话标识
配置
返回本地消息结果
获取会话里第一条未读消息
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 IMEngine.getInstance().getFirstUnreadMessage(conId).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取消息失败
     return;
   }
   if (!result.data) {
     // 消息不存在
     return;
   }
   let msg = result.data as Message;
 });
会话标识
消息,如果该会话没有未读,返回 null
删除本地会话的指定一批消息
 let idList = new List<number>();
 idList.add(msg.messageId);
 IMEngine.getInstance().deleteHistoryMessagesByIds(idList).then(result => {
   if (EngineError.Success !== result.code) {
     // 删除消息失败
     return;
   }
   // 删除消息成功
 })
消息 ID 列表
删除结果
清空本地会话的消息
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 IMEngine.getInstance().deleteMessages(conId).then(result => {
   if (EngineError.Success !== result.code) {
     // 删除消息失败
     return;
   }
   // 删除消息成功
 });
会话标识
结果
删除本地会话特定时间前的所有消息
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 let sentTime = Date.now();
 IMEngine.getInstance().deleteHistoryMessagesByTime(conId, time).then(result => {
   if (EngineError.Success !== result.code) {
     // 删除消息失败
     return;
   }
   // 删除消息成功
 })
会话标识
毫秒时间戳。清除 <= sentTime 的所有历史消息,若为 0 则代表清除所有消息
结果
删除远端会话特定时间前的消息
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 let sentTime = Date.now();
 IMEngine.getInstance().cleanRemoteHistoryMessagesByTime(conId, time).then(result => {
   if (EngineError.Success !== result.code) {
     // 删除消息失败
     return;
   }
   // 删除消息成功
 });
会话标识
毫秒时间戳。清除 <= sentTime 的所有历史消息,若为 0 则代表清除所有消息
结果
批量删除远端消息,发送成功或者接收到的消息才可以从远端删除
msgList 里面 Message 下列属性是必须的
uid:               服务端生产的消息唯一 id
direction:         消息方向
sentTime:          发送时间,不能小于等于 0
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "会话 ID";
 let msgList = new List<Message>();
 for (let i = 0; i < 10; i++) {
   // msg 必须是发送成功的消息,此处进行简写
   let msg : Message;
   msgList.add(msg);
 }
 // 是否删除本地消息
 let isDeleteLocal = true;
 IMEngine.getInstance().deleteRemoteMessages(conId, msgList, isDeleteLocal).then(result => {
   if (EngineError.Success !== result.code) {
     // 删除远端消息失败
     return;
   }
   // 删除远端消息成功
 })
会话标识
消息列表,长度范围 [1, 100]
是否删除本地消息。只有远端消息被删除成功时设置 true 才会删除本地消息。
设置输入状态的监听
IMEngine.getInstance().setTypingStatusListener((conId: ConversationIdentifier, typingStatusList: List<TypingStatus>) => {
   // conId 具体的会话标识
   // typingStatusList 具体的输入状态
});
监听,conId 会话标识;typingStatusList 输入状态的列表
增加输入状态的监听
 let typingListener: TypingStatusListener = {
   onTypingStatusChange: (conId: ConversationIdentifier, typingStatusList: List<TypingStatus>): void => {
     // conId 具体的会话标识
     // typingStatusList 具体的输入状态
   }
 }
 IMEngine.getInstance().addTypingStatusListener(typingListener);
监听
监听,对方调用 sendTypingStatus() 时本端会出发该监听
发送输入状态,仅支持单聊
常见的使用方式如下:
在聊天页面输入文本时,可以发送 TextMessageObjectName ,对方收到后可以展示"正在输入中"
在录音时,可以发送 HQVoiceMessageObjectName ,对方收到后可以展示"正在说话"
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "会话 ID";
 let objectName = TextMessageObjectName;
 IMEngine.getInstance().sendTypingStatus(conId, objectName).then(result => {
   if (EngineError.Success !== result.code) {
     // 发送失败
     return;
   }
   // 发送成功
 });
会话标识
正在输入的消息 ObjectName
设置输入状态更新时间间隔
控制输入状态发送频率,在规定时间内多次调用发送输入状态方法,最终只会发送一次输入状态
例如输入状态时间间隔为 6000 毫秒,在这段时间多次调用输入状态方法,只会发出一次输入状态,对方也只会收到一次输入状态
 let interval = 5000;
 IMEngine.getInstance().setTypingStatusInterval(interval).then(result => {
   if (EngineError.Success !== result.code) {
     // 设置输入状态间隔失败
     return;
   }
   // 设置成功
 });
时间间隔,单位毫秒,默认为 6000 毫秒。有效值 [1000,60000] 毫秒;超过范围,则设置不成功
修改消息接收状态
目前该方法仅用于设置 isListened 来标记高清语音消息是否已被听过
 let messageId = 123;
 let receivedStatus = new ReceivedStatus();
 receivedStatus.isRead = false;
 receivedStatus.isListened = false;
 IMEngine.getInstance().setMessageReceivedStatus(messageId, receivedStatus).then(result => {
   if (EngineError.Success !== result.code) {
     // 设置接收状态失败
     return;
   }
   // 设置接收状态成功
 })
消息 Id
接收状态
结果
设置本地消息的附加信息
用于扩展消息的使用场景。设置后可以通过 getHistoryMessages 取出带附加信息的消息。
 let messageId = 123;
 let extra = "这是要更新的 extra 字段内容";
 IMEngine.getInstance().setMessageExtra(messageId, extra).then(result => {
   if (EngineError.Success == result.code) {
     // 设置 extra 字段内容成功
   } else {
     // 设置 extra 字段内容失败
   }
 })
消息 Id
返回设置成功或者失败
设置消息扩展监听
 let listener: MessageExpansionListener = {
   onMessageExpansionUpdate: (expansion: Map<string, string>, message: Message): void => {
   },
   onMessageExpansionRemove: (keyArray: string[], message: Message): void => {
   }
 }
 IMEngine.getInstance().setMessageExpansionListener(listener);
监听
增加消息扩展监听
 let listener: MessageExpansionListener = {
   onMessageExpansionUpdate: (expansion: Map<string, string>, message: Message): void => {
   },
   onMessageExpansionRemove: (keyArray: string[], message: Message): void => {
   }
 }
 IMEngine.getInstance().addMessageExpansionListener(listener);
监听
监听
更新消息扩展信息
调用更新扩展的一方必须通过成功回调来处理本端的数据刷新。
仅被动接收扩展变更的用户(包含本用户的其他端)通过监听方法 MessageExpansionListener.onMessageExpansionUpdate 获取通知。
消息扩展信息是以字典形式存在。设置的时候从 expansion 中读取 key,如果原有的扩展信息中 key 不存在则添加新的 KV 对,如果 key 存在则替换成新的 value。
扩展信息字典中的 Key 支持大小写英文字母、数字、部分特殊符号 + = - _ 的组合方式,最大长度 32;Value 最长长度 4096,单次设置扩展数量最大为 20,消息的扩展总数不能超过 300
 // 消息 UId 是固定格式的字符串,例如 : CH2C-A072-OGM5-E3HL
 let msgUid = "消息 UId";
 // 更新的消息扩展数据
 let map = new Map<string,string>();
 map.set("k1","v1");
 map.set("k2","v2");
 IMEngine.getInstance().updateMessageExpansion(map, msgUid).then(result => {
   if (EngineError.Success !== result.code) {
     // 消息扩展更新失败
     return;
   }
   // 消息扩展更新成功
 });
要更新的消息扩展信息键值对
消息 messageUId
结果
删除消息扩展信息中特定的键值对
调用删除扩展的一方必须通过成功回调来处理本端的数据刷新。
仅被动接收扩展变更的用户(包含本用户的其他端)通过监听方法 MessageExpansionListener.onMessageExpansionRemove 获取通知。
 // 消息 UId 是固定格式的字符串,例如 : CH2C-A072-OGM5-E3HL
 let msgUid = "消息 UId";
 // 需要删除的 key 数组
 let keyArray = new Array<string>();
 keyArray.push("k1");
 IMEngine.getInstance().removeMessageExpansion(keyArray, msgUid).then(result => {
   if (EngineError.Success !== result.code) {
     // 删除消息扩展失败
     return;
   }
   // 删除消息扩展成功
 });
消息扩展信息中待删除的 key 的列表
消息 messageUId
结果
增加消息阅后即焚监听,仅支持单聊,仅限阅后即焚消息的接收方调用
 let destructListener: MessageDestructionListener = {
   onMessageDestructing: (message: Message, leftDuration: number): void => {
   },
   onMessageDestructionStop: (message: Message): void => {
   }
 }
 IMEngine.getInstance().addMessageDestructionListener(destructListener);
监听
移除消息阅后即焚监听,仅支持单聊,仅限阅后即焚消息的接收方调用
 IMEngine.getInstance().removeMessageDestructionListener(destructListener);
监听
消息开始阅后即焚倒计时,仅支持单聊,仅限阅后即焚消息的接收方调用
 // 必须使用有效的消息体,此处进行了简写
 let msg: Message;
 IMEngine.getInstance().messageBeginDestruct(msg).then(result => {
   if (EngineError.Success !== result.code) {
     // 失败
     return;
   }
   // 成功
 });
消息体
消息停止阅后即焚倒计时,仅支持单聊,仅限阅后即焚消息的接收方调用
调用之后,该消息终止阅后即焚
阅后即焚倒计时停止,并触发 MessageDestructionListener.onMessageDestructionStop
可以调用 messageBeginDestruct() 重新进行倒计时
 // 必须使用有效的消息体,此处进行了简写
 let msg: Message;
 IMEngine.getInstance().messageStopDestruct(msg).then(result => {
   if (EngineError.Success !== result.code) {
     // 失败
     return;
   }
   // 成功
 });
消息体
设置显示推送详情
通知栏显示的消息推送默认显示的是消息内容,如果消息包含敏感信息,不希望在推送通知栏上显示消息内容,可以调用此方法设置 showStatus 为 false
注意:此功能需要从服务端开启用户设置功能。
 let showStatus = true;
 IMEngine.getInstance().setPushContentShowStatus(showStatus).then(result => {
   if (EngineError.Success !== result.code) {
     // 失败
     return;
   }
   // 成功
 });
是否显示远程推送内容,true 显示,false 不显示
设置的结果
获取是否显示远程推送内容详情设置
 IMEngine.getInstance().getPushContentShowStatus().then(result => {
   if (EngineError.Success !== result.code) {
     // 获取失败
     return;
   }
   if (!result.data) {
     // 数据为空
     return;
   }
   let showStatus = result.data as boolean;
 });
是否显示远程推送内容,true 显示,false 不显示
设置 Web 端在线时,手机端是否接收推送
注意:此功能需要从服务端开启用户设置功能。
 let receiveStatus = true;
 IMEngine.getInstance().setPushReceiveStatus(receiveStatus).then(result => {
   if (EngineError.Success !== result.code) {
     // 失败
     return;
   }
   // 成功
 });
是否接收推送,true 接收,false 不接收
结果
获取是否接收远程推送的设置
前提: 移动端不在线,Web 、MAC/PC 终端在线,移动端是否接收远程推送。
 IMEngine.getInstance().getPushReceiveStatus().then(result => {
   if (EngineError.Success !== result.code) {
     // 获取失败
     return;
   }
   if (!result.data) {
     // 数据为空
     return;
   }
   let receiveStatus = result.data as boolean;
 });
是否接收远程推送,true 接收,false 不接收
设置会话状态(置顶,消息免打扰)变化监听
 IMEngine.getInstance().setConversationStatusListener((items: List<ConversationStatusInfo>) => {
 });
监听
增加会话状态(置顶,消息免打扰)变化监听
 let statusListener : ConversationStatusListener = {
   onConversationStatusChange: (items: List<ConversationStatusInfo>): void => {
   }
 }
 IMEngine.getInstance().addConversationStatusListener(statusListener);
监听
监听
获取单个会话
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 IMEngine.getInstance().getConversation(conId).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取回话失败
     return;
   }
   if (!result.data) {
     // 会话为空
     return;
   }
   let con = result.data as Conversation;
 });
会话标识
会话数据
分页获取本地会话列表
 let conTypeList = new List<ConversationType>();
 conTypeList.add(ConversationType.Private);
 conTypeList.add(ConversationType.Group);
 let option: IGetConversationOption = {
   time: Date.now(),
   count: 10
 }
 IMEngine.getInstance().getConversationListByPage(conTypeList, option).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取会话列表失败
     return;
   }
   if (!result.data) {
     // 会话列表为空
     return;
   }
   let conList = result.data as List<Conversation>;
 });
会话类型列表
配置
本地会话列表数据
分页获取本地置顶会话列表
 let conTypeList = new List<ConversationType>();
 conTypeList.add(ConversationType.Private);
 conTypeList.add(ConversationType.Group);
 let option: IGetConversationOption = {
   time: Date.now(),
   count: 10
 }
 IMEngine.getInstance().getTopConversationListByPage(conTypeList, option).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取会话列表失败
     return;
   }
   if (!result.data) {
     // 会话列表为空
     return;
   }
   let conList = result.data as List<Conversation>;
 });
会话类型列表
配置
本地会话列表数据
分页获取本地免打扰会话列表
 let conTypeList = new List<ConversationType>();
 conTypeList.add(ConversationType.Private);
 conTypeList.add(ConversationType.Group);
 let option: IGetConversationOption = {
   time: Date.now(),
   count: 10
 }
 IMEngine.getInstance().getBlockedConversationListByPage(conTypeList, option).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取会话列表失败
     return;
   }
   if (!result.data) {
     // 会话列表为空
     return;
   }
   let conList = result.data as List<Conversation>;
 });
会话类型列表
配置
本地会话列表数据
获取本地未读会话列表,该接口仅支持单聊、群聊、系统三种会话类型,不支持聊天室、超级群。
 let conTypeList = new List<ConversationType>();
 conTypeList.add(ConversationType.Private);
 conTypeList.add(ConversationType.Group);
 IMEngine.getInstance().getUnreadConversations(conTypeList).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取未读会话列表失败
     return;
   }
   if (!result.data) {
     // 获取未读会话列表为空
     return;
   }
   // 未读会话列表
   let conList = result.data as List<Conversation>;
 });
会话类型数组,长度范围 [1, 100]
会话数组
获取本地会话中 @ 自己的未读会话列表
 let conTypeList = new List<ConversationType>();
 conTypeList.add(ConversationType.Private);
 conTypeList.add(ConversationType.Group);
 let timestamp = 0; // 按需填写实际的 timestamp
 let count = 10; // 按需填写实际需要获取的条数
 let topPriority = false; // 按需填写是否需要置顶优先
 let option: GetConversationsByPageOption = {
   conversationTypes: conTypeList,
   timestamp: timestamp,
   count: count,
   topPriority: topPriority
 }
 IMEngine.getInstance().getUnreadMentionMeConversationList(option).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取未读@会话列表失败
     return;
   }
   if (!result.data) {
     // 获取未读@会话列表为空
     return;
   }
   // 未读@会话列表
   let conList = result.data as List<Conversation>;
 });
配置
会话列表
获取本地包括机器人的会话列表
 let conTypeList = new List<ConversationType>();
 conTypeList.add(ConversationType.Private);
 conTypeList.add(ConversationType.System);
 let timestamp = 0; // 按需填写实际的 timestamp
 let count = 10; // 按需填写实际需要获取的条数
 let topPriority = false; // 按需填写是否需要置顶优先
 let option: GetConversationsByPageOption = {
   conversationTypes: conTypeList,
   timestamp: timestamp,
   count: count,
   topPriority: topPriority
 }
IMEngine.getInstance().getConversationsIncludingRobots(option).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取会话列表失败
     return;
   }
   if (!result.data) {
     // 会话列表为空
     return;
   }
   let conList = result.data as List<Conversation>;
 });
配置
会话列表
删除本地会话同时删除会话中的消息
 let conTypeList = new List<ConversationType>();
 conTypeList.add(ConversationType.Private);
 IMEngine.getInstance().clearConversations(conTypeList).then(result => {
   if (EngineError.Success !== result.code) {
     // 删除会话失败
     return;
   }
 });
会话类型列表
结果
批量删除本地会话,但是不会删除消息
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 let list = new List<ConversationIdentifier>();
 list.add(conId);
 IMEngine.getInstance().removeConversations(conIdList).then(result => {
   if (EngineError.Success !== result.code) {
     // 删除会话失败
     return;
   }
 });
会话标识数组
结果
批量删除远端会话
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 let conIds : Array<ConversationIdentifier> = [];
 conIds.push(conId);
 IMEngine.getInstance().removeRemoteConversations(conIds).then(result => {
   if (EngineError.Success !== result.code) {
     // 删除会话失败
     return;
   }
 });
结果
设置实时会话的已读时间
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 let timestamp = 1234567; // 按需填写实际的 timestamp
 IMEngine.getInstance().setReadTimestamp(conId, timestamp).then(result => {
   if (EngineError.Success !== result.code) {
     // 设置实时会话的已读时间失败
   } else {
     // 设置实时会话的已读时间成功
   }
 });
会话标识
时间戳
结果
批量 设置/取消 会话置顶
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 let list = new List<ConversationIdentifier>();
 list.add(conId);
 let option: ISetConversationTopOption = {
   isTop: true, // 是否置顶
   isNeedCreate: true // 没有会话时是否创建该会话
 }
 IMEngine.getInstance().setConversationsToTop(conIdList, option).then(result => {
   if (EngineError.Success !== result.code) {
     // 设置置顶失败
     return;
   }
 });
会话标识列表
配置
结果
获取会话置顶状态
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 IMEngine.getInstance().getConversationTopStatus(conId).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取置顶状态失败
     return;
   }
   if (!result.data) {
     // 置顶状态为空
     return;
   }
   let isTop = result.data as boolean;
 });
会话标识
是否置顶
批量设置会话免打扰
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 let list = new List<ConversationIdentifier>();
 list.add(conId);
 let level = PushNotificationLevel.Blocked;
 IMEngine.getInstance().setConversationsNotificationLevel(conIdList, level).then(result => {
   if (EngineError.Success !== result.code) {
     // 设置免打扰失败
     return;
   }
 });
会话标识列表
会话免打扰级别
结果
获取单个会话免打扰状态
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 IMEngine.getInstance().getConversationNotificationLevel(conId).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取免打扰状态失败
     return;
   }
   if (!result.data) {
     // 免打扰状态为空
     return;
   }
   let level = result.data as PushNotificationLevel;
 });
会话标识
会话免打扰级别
保存/清空 会话草稿
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 let draft = "draft From 鸿蒙";
 IMEngine.getInstance().saveTextMessageDraft(conId, draft).then(result => {
   if (EngineError.Success !== result.code) {
     // 保存草稿失败
     return;
   }
 });
会话标识
草稿:传入有效值代表保存草稿;传入空字符串代表清空草稿
结果
获取会话草稿
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 IMEngine.getInstance().getTextMessageDraft(conId).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取草稿失败
     return;
   }
   if (!result.data) {
     // 草稿为空
     return;
   }
   let draft = result.data as string;
 })
会话标识
草稿
屏蔽某个时间段的消息提醒
 let option: IQuietHoursOption = {
   startTime: "00:30:00",
   duration: 300,
   level: PushNotificationLevel.Blocked
 }
 IMEngine.getInstance().setNotificationQuietHoursLevel(option).then(result => {
   if (EngineError.Success !== result.code) {
     // 设置免打扰失败
     return;
   }
 })
配置,见 IQuietHoursOption
结果
查询已设置的时间段消息提醒屏蔽
 IMEngine.getInstance().getNotificationQuietHoursLevel().then(result => {
   if (EngineError.Success !== result.code) {
     // 获取免打扰失败
     return;
   }
   if (!result.data) {
     // 免打扰数据为空
     return;
   }
   let info = result.data as IQuietHoursOption;
 })
具体的配置
删除已设置的全局时间段消息提醒屏蔽
 IMEngine.getInstance().removeNotificationQuietHours().then(result => {
   if (EngineError.Success !== result.code) {
     // 移除免打扰失败
     return;
   }
   // 移除免打扰成功
 });
结果
获取本地会话的全部未读数
 IMEngine.getInstance().getTotalUnreadCount().then(result => {
   if (EngineError.Success !== result.code) {
     // 获取未读数失败
     return;
   }
   if (!result.data) {
     // 未读数为 null
     return;
   }
   let unreadCount = result.data as number;
 })
未读数
获取本地批量会话的未读数之和
 let conIdList = new List<ConversationIdentifier>();
 let conId1 = new ConversationIdentifier();
 conId1.conversationType = ConversationType.Private;
 conId1.targetId = "会话 id";
 conIdList.add(conId1)
 let conId2 = new ConversationIdentifier();
 conId2.conversationType = ConversationType.Private;
 conId2.targetId = "会话 id";
 conIdList.add(conId2)
 IMEngine.getInstance().getTotalUnreadCountByIds(conIdList).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取未读数失败
     return;
   }
   if (!result.data) {
     // 未读数为 null
     return;
   }
   let unreadCount = result.data as number;
 })
会话标识数组
未读数
获取单个会话的未读数
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 IMEngine.getInstance().getUnreadCount(conId).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取未读数失败
     return;
   }
   if (!result.data) {
     // 未读数为 null
     return;
   }
   let unreadCount = result.data as number;
 });
会话标识
该会话的未读数
清空单个会话未读数
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 IMEngine.getInstance().clearMessagesUnreadStatus(conId).then(result => {
   if (EngineError.Success !== result.code) {
     // 清空未读数失败
     return;
   }
   / 清空未读数成功
 })
会话标识
结果
清除单个会话的未读数:按照时间戳清除
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 let time = Date.now();
 IMEngine.getInstance().clearMessagesUnreadStatusByTime(conId, time).then(result => {
   if (EngineError.Success !== result.code) {
     // 清空未读数失败
     return;
   }
   // 清空未读数成功
 })
会话标识
时间,清理小于该时间戳的消息未读
结果
会话未读数,是否包含免打扰会话的未读数
 let typeList = new List<ConversationType>();
 typeList.add(ConversationType.Private);
 typeList.add(ConversationType.Group);
 let isContainBlocked = false;
 IMEngine.getInstance().getUnreadCountByTypes(conTypeList, isContainBlocked).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取未读数失败
     return;
   }
   if (!result.data) {
     // 未读数为 null
     return;
   }
   let unreadCount = result.data as number;
 });
会话类型数组
是否包含免打扰;true 代表获取所有会话未读数之和; false 代表获取不包含免打扰会话的正常会话未读数之和
未读数
同步会话已读状态
用于相同账号的多端已读同步
例如用户 A 同时登录鸿蒙和 Android,两端同时收到消息,同时未读数增加
Android 调用该方法将某个会话同步已读之后, 鸿蒙会触发 SyncConversationReadStatusListener
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "会话 Id";
 // 会话中已读的最后一条消息的发送时间戳,此处用了当前时间
 let time = Date.now();
 IMEngine.getInstance().syncConversationReadStatus(conId,time).then(result => {
   if (EngineError.Success !== result.code) {
     // 同步已读失败
     return;
   }
   // 同步已读成功
 });
会话标识
会话中已读的最后一条消息的发送时间戳
结果
设置会话已读状态监听
 let listener : SyncConversationReadStatusListener = {
   onSyncConversationReadStatus: (conId: ConversationIdentifier, timestamp: number): void => {
    // 该会话的 timestamp 之前的消息未读已清空
   }
 }
 IMEngine.getInstance().setSyncConversationReadStatusListener(listener);
监听
增加会话已读状态监听
 let listener : SyncConversationReadStatusListener = {
   onSyncConversationReadStatus: (conId: ConversationIdentifier, timestamp: number): void => {
    // 该会话的 timestamp 之前的消息未读已清空
   }
 }
 IMEngine.getInstance().addSyncConversationReadStatusListener(listener);
监听
增加消息已读回执监听
 let listener: MessageReadReceiptListener = {
   onMessageReadReceiptReceived: (message: Message): void => {
   },
   onMessageReceiptRequest: (conId: ConversationIdentifier, messageUid: string): void => {
   },
   onMessageReceiptResponse: (conId: ConversationIdentifier, messageUid: string, respondUserIdList: Map<string, number>): void => {
   }
 }
 IMEngine.getInstance().addMessageReadReceiptListener(listener);
监听
监听
单聊,发送某个会话中的消息阅读回执,由原始消息的接收方调用
单聊调用该方法后,原始消息发送方会触发 MessageReadReceiptListener.onMessageReadReceiptReceived
原始消息发送方本地对应单聊会话的已读消息 sentStatus 均为 SentStatus.Read
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 let time = Date.now();
 IMEngine.getInstance().sendReadReceiptMessage(conId, time).then(result => {
   if (EngineError.Success !== result.code) {
     // 失败
     return;
   }
   // 成功
 });
会话标识
会话中已读的最后一条消息的发送时间戳, Message.sentTime
群聊,发送某个会话的消息已读请求,由原始消息的发送方调用
群聊调用该方法后,原始消息的接收方会触发 MessageReadReceiptListener.onMessageReceiptRequest
原始消息接收方就知道需要对该消息做已读响应。调用 sendReadReceiptResponse
 // 应该使用发送成功的消息,此处进行了简写
 let msg : Message;
 IMEngine.getInstance().sendReadReceiptRequest(msg).then(result => {
   if (EngineError.Success !== result.code) {
     // 失败
     return;
   }
   // 成功
 });
消息体,messageUid 必须有效
消息已读请求的结果
群聊,发送某个会话已读响应,由原始消息的接收方调用
群聊调用该方法后,原始消息的发送方会触发 MessageReadReceiptListener.onMessageReceiptResponse
原始消息的发送方就知道自己该消息有哪些人已读了
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 // 需要具体的消息,此处进行了简写
 let msgArray = new Array<Message>();
 let msg : Message;
 msgArray.push(msg);
 IMEngine.getInstance().sendReadReceiptResponse(conId, msgArray).then(result => {
   if (EngineError.Success !== result.code) {
     // 失败
     return;
   }
   if (!result.data) {
     // 成功的消息体列表为空
     return;
   }
   // 发送响应成功的消息列表
   let msgList = result.data as List<Message>;
 });
会话标识
消息体数组,消息体必须存在有效的 senderId 和 messageUid
消息已读响应结果,返回的 Message 集合可以通过 Message.readReceiptInfo.hasRespond 确认该消息是否已经发送了响应
增加消息已读V2回执监听
 let listener: MessageReadReceiptV2Listener = {
   onMessageReceiptResponse: (conId: ConversationIdentifier, messageUid: string, readCount: number, totalCount: number): void => {
   }
 }
 IMEngine.getInstance().addMessageReadReceiptV2Listener(listener);
监听
监听
群聊,发送某个会话已读响应,由原始消息的接收方调用
群聊调用该方法后,原始消息的发送方会触发 MessageReadReceiptV2Listener.onMessageReceiptResponse
原始消息的发送方就知道自己该消息有多少人已读了
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Group;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 // 需要具体的消息,此处进行了简写
 let msgArray = new Array<Message>();
 let msg : Message;
 msgArray.push(msg);
 IMEngine.getInstance().sendReadReceiptResponseV2(conId, msgArray).then(result => {
   if (EngineError.Success !== result.code) {
     // 失败
     return;
   }
   if (!result.data) {
     // 成功的消息体列表为空
     return;
   }
   // 发送响应成功的消息列表
   let msgList = result.data as List<Message>;
 });
会话标识
消息体数组,消息体必须存在有效的 senderId 和 messageUid
消息已读响应结果,返回的 Message 集合可以通过 Message.readReceiptInfo.hasRespond 确认该消息是否已经发送了响应
群聊,获取已读人员列表
在服务端配置已读V2后,原始消息的发送方调用该方法后,就知道自己该消息有哪些人已读了
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Group;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 // 需要具体的消息,此处进行了简写
 let msgUid = "123456";  // 按需填写实际的Message Uid
 IMEngine.getInstance().getGroupMessageReaderList(conId, msgUid, (totalCount: number, readerList: Map<string, number>) => {
   // 处理已读人员信息
 }).then(result => {
   if (EngineError.Success !== result.code) {
     // 失败
     return;
   }
   // 成功,获取已读人数
   let readCount = result.data;
 });
会话标识
消息Uid
消息已读人数
增加消息已读V5回执监听
 let listener: MessageReadReceiptV5Listener = {
   onMessageReceiptResponse: (readReceiptNotifyArray: Array<ReadReceiptNotifyV5>): void => {
   }
 }
 IMEngine.getInstance().addMessageReadReceiptV5Listener(listener);
已读 V5 监听器
监听
发送消息已读回执 V5,由原始消息的接收方调用
调用该方法后,原始消息的发送方会触发 MessageReadReceiptV5Listener.onMessageReceiptResponse
原始消息的发送方就知道自己该消息有多少人已读了
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Group;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 // 需要具体的消息,此处进行了简写
 let msgUidArray = new Array<String>();
 let messageUid1 = "MessageUid1"; // 按需填写实际的 MessageUid
 let messageUid2 = "MessageUid2"; // 按需填写实际的 MessageUid
 msgUidArray.push(messageUid1);
 msgUidArray.push(messageUid2);
 IMEngine.getInstance().sendReadReceiptResponseV5(conId, msgUidArray).then(result => {
   if (EngineError.Success !== result.code) {
     // 失败
     return;
   }
   if (!result.data) {
     // 成功的消息体列表为空
     return;
   }
   // 发送响应成功的消息列表
   let msgList = result.data as List<Message>;
 });
会话标识
消息 Uid 数组
消息已读响应结果,成功返回 EngineError.Success,失败返回对应错误码。
批量获取消息已读信息(V5)
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Group;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 // 需要具体的消息,此处进行了简写
 let msgUidArray = new Array<string>();
 let messageUid1 = "MessageUid1"; // 按需填写实际的 MessageUid
 let messageUid2 = "MessageUid2"; // 按需填写实际的 MessageUid
 msgUidArray.push(messageUid1);
 msgUidArray.push(messageUid2);
 IMEngine.getInstance().getMessageReadReceiptInfoV5(conId, msgUidArray).then(result => {
   if (EngineError.Success !== result.code) {
     // 失败
     return;
   }
   if (!result.data) {
     // 成功的消息体列表为空
     return;
   }
   // 发送响应成功的消息列表
   let msgList = result.data as List<ReadReceiptInfoV5>;
 });
会话标识
消息 Uid 数组
消息已读响应结果,返回的 Message 集合
批量获取消息已读回执 V5 信息
消息会话标识
消息已读响应结果,返回的 Message 集合
分页获取消息已读未读信息
在服务端配置已读V5后,原始消息的发送方调用该方法后,就知道自己该消息有哪些人已读了
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Group;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 // 需要具体的消息,此处进行了简写
 let msgUid = "123456";  // 按需填写实际的Message Uid
 let pageToken = "yourPageToken";
 let count = 100;
 let readStatus = ReadStatus.All;
 let order = Order.Descending;
 IMEngine.getInstance().getMessagesReadReceiptUsersByPageV5(
   conId,
   msgUid,
   pageToken,
   count,
   readStatus,
   order,
).then(result => {
   if (EngineError.Success !== result.code) {
     // 失败
     return;
   }
   // 成功,获取已读人数
   let readReceiptUserResult = result.data;
 });
会话标识
消息Uid
消息已读人数
批量获取用户指定群组消息是否已读状态(V5)
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Group;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 // 需要具体的消息,此处进行了简写
 let msgUid = "123456";  // 按需填写实际的Message Uid
 // 需要具体的消息,此处进行了简写
 let userIdArray = new Array<string>();
 let userId1 = "userId1"; // 按需填写实际的 userId
 let userId2 = "userId2"; // 按需填写实际的 userId
 userIdArray.push(userId1);
 userIdArray.push(userId2);
 IMEngine.getInstance().getMessagesReadReceiptByUsersV5(
   conId,
   msgUid,
   userIdArray,
).then(result => {
   if (EngineError.Success !== result.code) {
     // 失败
     return;
   }
   // 成功,获取已读人数
   let readReceiptUserResult = result.data;
 });
会话标识
消息Uid
要查询的用户 userId 列表
根据关键字搜索本地会话。
 let conTypeList = new List<ConversationType>();
 conTypeList.add(ConversationType.Private);
 conTypeList.add(ConversationType.Group);
 let keyword = "需要搜索的关键字";
 let objNameList = new List<string>();
 // 例如文本消息传入文本消息的 objectName: RC:TxtMsg
 objNameList.add(TextMessageObjectName);
 IMEngine.getInstance().searchConversations(conTypeList, keyword, objNameList).then(result => {
   if (EngineError.Success !== result.code) {
     // 搜索会话失败
     return;
   }
   if (!result.data) {
     // 搜索的会话为空
     return;
   }
   // 搜索到的会话列表
   let conList = result.data as List<Conversation>;
 });
搜索的关键字,长度范围 [1, 256]
消息类型数组。用于搜索指定类型的消息;为空代表所有所有类型消息
搜索到的会话列表
根据关键字搜索本地会话。
 let conTypeList = new List<ConversationType>();
 conTypeList.add(ConversationType.Private);
 conTypeList.add(ConversationType.Group);
 let keyword = "关键字";
 IMEngine.getInstance().searchConversationsWithResult(conTypeList, keyword, null).then(result => {
   if (EngineError.Success !== result.code) {
     // 搜索会话失败
     return;
   }
   if (!result.data) {
     // 搜索的会话内容为空
     return;
   }
   // 搜索的结果
   let searchResultList = result.data as List<SearchConversationResult>;
 });
搜索的关键字,长度范围 [1, 256]
消息类型数组。用于搜索指定类型的消息;为空代表所有所有类型消息
搜索到的会话列表
根据关键字搜索指定消息类型的本地消息。
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "会话 ID";
 let keyword = "需要搜索的关键字";
 let objNameList = new List<string>();
 objNameList.add(TextMessageObjectName);
 let startTime = Date.now();
 let count = 10;
 IMEngine.getInstance().searchMessages(conId, keyword, objNameList, startTime, count).then(result => {
   if (EngineError.Success !== result.code) {
     // 搜索消息失败
     return;
   }
   if (!result.data) {
     // 搜索消息为空
     return;
   }
   // 搜索到的消息
   let msgList = result.data as List<Message>;
 });
会话标识
关键字,长度范围 [1, 256]
消息类型数组。用于搜索指定类型的消息;为空代表搜索所有类型消息
查询的起始发送时间,返回小于该时间的消息,毫秒时间戳;如果为 0,则查询全部。当分页时,可以传入上一批消息的最小发送时间,取值范围 [0, INT64_MAX]
消息个数,传 0 时会返回所有搜索到的消息,非 0 时根据 startTime 逐页返回,取值范围 [0, 100]
消息列表
根据关键字和指定时间段搜索指定会话中的消息。
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "会话 ID";
 let keyword = "需要搜索的关键字";
 // 查找当前时间 24 小时内的消息
 let option: ISearchMessageInTimeRangeOption = {
   startTime: Date.now() - 24 * 60 * 60 * 1000,
   endTime: Date.now(),
   offset: 0,
   limit: 10
 }
 IMEngine.getInstance().searchMessagesInTimeRange(conId, keyword, option).then(result => {
   if (EngineError.Success !== result.code) {
     // 搜索消息失败
     return;
   }
   if (!result.data) {
     // 搜素消息为空
     return;
   }
   // 搜索的消息列表
   let msgList = result.data as List<Message>;
 });
会话标识
关键字,长度范围 [1, 256]
在时间区间内搜索消息的参数配置
消息列表
根据用户 id 搜索指定会话中的本地消息。
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "会话 ID";
 let userId = "用户 ID";
 let startTime = Date.now();
 let count = 10;
 IMEngine.getInstance().searchMessagesByUser(conId, userId, startTime, count).then(result => {
   if (EngineError.Success !== result.code) {
     // 搜索消息失败
     return;
   }
   if (!result.data) {
     // 搜素消息为空
     return;
   }
   // 搜索的消息列表
   let msgList = result.data as List<Message>;
 });
会话标识
用户 id
查询的起始发送时间,返回小于该时间的消息,毫秒时间戳;如果为 0,则查询全部。当分页时,可以传入上一批消息的最小发送时间,取值范围 [0, INT64_MAX]
消息个数,传 0 时会返回所有搜索到的消息;非 0 时根据 startTime 逐页返回,取值范围 [0, 100]
消息列表
在指定的一批会话中搜索消息
 let conTypeArray = new Array<ConversationType>();
 conTypeArray.push(ConversationType.Private);
 let targetIdArray: Array<string> | null = null;
 let channelIdArray: Array<string> | null = null;
 let objNameArray: Array<string> | null = null;
 let keyword = "关键字";
 let startTime = Date.now();
 let count = 10;
 let order = Order.Ascending;
 IMEngine.getInstance().searchMessagesByConversations(
   conTypeArray,
   targetIdArray,
   channelIdArray,
   objNameArray,
   keyword,
   startTime,
   count, order
 ).then(result => {
   if (EngineError.Success !== result.code) {
     // 失败
     return;
   }
   if (!result.data) {
     // 数据为空
     return;
   }
   let msgList = result.data as List<Message>;
 })
会话类型数组,非空
会话 Id 数组,为空代表所有会话
频道 Id 数组,为空代表所有频道
消息类型数组。用于搜索指定类型的消息;为空代表搜索所有类型消息
关键字,长度范围 [1, 256]
查询的起始发送时间,返回小于该时间的消息,毫秒时间戳;如果为 0,则查询全部。当分页时,可以传入上一批消息的最小发送时间,取值范围 [0, INT64_MAX]
消息个数,传 0 时会返回所有搜索到的消息;非 0 时根据 startTime 逐页返回,取值范围 [0, 100]
返回排序。Ascending 升序,返回比 startTime 时间戳大的消息。Descending 降序,返回比 startTime 时间戳消的消息
在本地指定会话中搜索多个成员指定的消息类型
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.Private;
 conId.targetId = "TestTargetId"; // 按需填写实际的会话 id
 let userIdArray = ["UserId1","UserId2"];
 let objNameArray: Array<string> | null = null;
 let startTime = Date.now();
 let count = 10;
 let order = Order.Ascending;
 IMEngine.getInstance().searchMessagesByUsers(conId, userIdArray, objNameArray, startTime, count, order).then(result => {
   if (EngineError.Success !== result.code) {
     // 失败
     return;
   }
   if (!result.data) {
     // 数据为空
     return;
   }
   // 搜索到的消息列表
   let msgList = result.data as List<Message>;
 })
会话标识
消息发送者 Id 数组,搜索由这些用户发送的消息
消息类型数组。用于搜索指定类型的消息;为空代表搜索所有类型消息
查询的起始发送时间,返回小于该时间的消息,毫秒时间戳;如果为 0,则查询全部。当分页时,可以传入上一批消息的最小发送时间,取值范围 [0, INT64_MAX]
消息个数;非 0 时根据 startTime 逐页返回,传 0 默认取值为 100,取值范围 [0, 100]
返回排序。Ascending 升序,返回比 startTime 时间戳大的消息。Descending 降序,返回比 startTime 时间戳消的消息
消息列表
获取本地订阅的所有公众号(仅支持私有云)
 IMEngine.getInstance().getPublicServiceList().then(result => {
   if (EngineError.Success !== result.code) {
     // 获取公众号失败
     return;
   }
   if (!result.data) {
     // 公众号为空
     return;
   }
   // 公众号列表
   let list = result.data as List<PublicServiceInfo>;
 });
获取本地订阅的指定公众号
 let conId = new ConversationIdentifier();
 conId.conversationType = ConversationType.AppPublicService;
 conId.targetId = this.targetId;
 IMEngine.getInstance().getPublicService(conId).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取公众号失败
     return;
   }
   if (!result.data) {
     // 公众号为空
     return;
   }
   // 公众号信息
   let info = result.data as PublicServiceInfo;
 });
会话标识,会话类型不管为何值,SDK 均会按照 AppPublicService 处理
设置聊天室状态监听
 let listener: ChatroomStatusListener = {
   onChatroomJoining(roomId: string): void {
   },
   onChatroomJoined(roomId: string, info: ChatroomJoinedInfo): void {
   },
   onChatroomJoinFailed(roomId: string, code: EngineError): void {
   },
   onChatroomQuited(roomId: string): void {
   },
   onChatroomDestroyed(roomId: string, type: ChatroomDestroyType): void {
   },
 }
 IMEngine.getInstance().setChatroomStatusListener(listener);
监听
增加聊天室状态监听
let listener: ChatroomStatusListener = {
 onChatroomJoining(roomId: string): void {
   hilog.info(0x0000, 'IM-App', 'onChatroomJoining roomId:%{public}s', roomId);
 },
 onChatroomJoined(roomId: string, info: ChatroomJoinedInfo): void {
   hilog.info(0x0000, 'IM-App', 'onChatroomJoined roomId:%{public}s info:%{public}s', roomId, JSON.stringify(info));
 },
 onChatroomJoinFailed(roomId: string, code: EngineError): void {
   hilog.info(0x0000, 'IM-App', 'onChatroomJoined roomId:%{public}s code:%{public}d', roomId, code);
 },
 onChatroomQuited(roomId: string): void {
   hilog.info(0x0000, 'IM-App', 'onChatroomQuited roomId:%{public}s', roomId);
 },
 onChatroomDestroyed(roomId: string, type: ChatroomDestroyType): void {
   hilog.info(0x0000, 'IM-App', 'onChatroomDestroyed roomId:%{public}s type:%{public}d', roomId, type);
 },
}
IMEngine.getInstance().addChatroomStatusListener(listener);
监听
监听
加入聊天室,如果聊天室不存在则创建聊天室
 let roomId = "TestChatroomId"; // 按需填写实际的聊天室 id
 let msgCount = 5;
 IMEngine.getInstance().joinChatroom(roomId, msgCount).then(result => {
   if (EngineError.Success !== result.code) {
     // 加入聊天室失败
     return;
   }
   if (!result.data) {
     // 聊天室加入信息失败
     return;
   }
   let joinedInfo = result.data as ChatroomJoinedInfo;
 });
roomId 聊天室 ID
msgCount 消息个数,-1 时不拉取任何消息,0 时拉取 10 条消息,最多只能拉取 50
结果
加入已经存在的聊天室
 let roomId = "TestChatroomId"; // 按需填写实际的聊天室 id
 let msgCount = 5;
 IMEngine.getInstance().joinExistingChatroom(roomId, msgCount).then(result => {
   if (EngineError.Success !== result.code) {
     // 加入聊天室失败
     return;
   }
   if (!result.data) {
     // 聊天室加入信息失败
     return;
   }
   let joinedInfo = result.data as ChatroomJoinedInfo;
 });
聊天室 ID
消息个数,-1 时不拉取任何消息,0 时拉取 10 条消息,最多只能拉取 50
结果
退出聊天室
 let roomId = "TestChatroomId"; // 按需填写实际的聊天室 id
 IMEngine.getInstance().quitChatroom(roomId).then(result => {
   if (EngineError.Success !== result.code) {
     // 退出聊天室失败
     return;
   }
 });
聊天室 ID
结果
获取聊天室信息
 let roomId = "TestChatroomId"; // 按需填写实际的聊天室 id
 let option: ICountOption = {
   count: 10,
   order: Order.Descending
 }
 IMEngine.getInstance().getChatroomInfo(roomId, option).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取聊天室信息失败
     return;
   }
   if (!result.data) {
     // 聊天室信息为空
     return;
   }
   let chatroomInfo = result.data as ChatroomInfo;
 });
聊天室 ID
配置
聊天室信息
设置聊天室自定义属性
entries 最大限制为 10
key : 聊天室属性名称,长度范围 [1~128],支持大小写英文字母、数字、部分特殊符号 + = - _ 的组合方式
value : 聊天室属性对应的值,长度范围 [1~4096]
 let roomId = "聊天室 ID";
 let map = new Map<string, string>();
 map.set("key1","value1");
 map.set("key2","value2");
 let autoDelete = true;
 let overWrite = true;
 IMEngine.getInstance().setChatroomEntries(roomId, map, autoDelete, overWrite).then(result => {
   if (EngineError.Success !== result.code) {
     // 设置 KV 失败
     return;
   }
   if (!result.data) {
     // 所有 KV 都设置成功
     return;
   }
   // 设置失败的 key 和对应的失败错误码,视情况决定是否重新设置失败的 KV
   let errorMap = result.data as Map<string, EngineError>;
 });
聊天室 ID
key-value 字典,长度范围 [1 ~ 10]
用户掉线或退出时,是否自动删除该 Key、Value 值;自动删除时不会发送通知
是否强制覆盖
返回的具体结果,会明确特定 key 的具体错误
删除聊天室自定义属性
 let roomId = "聊天室 ID";
 let list = new List<string>();
 list.add("key1");
 list.add("key2");
 let isForce = true;
 IMEngine.getInstance().deleteChatroomEntries(roomId, list, isForce).then(result => {
   if (EngineError.Success !== result.code) {
     // 删除 KV 失败
     return;
   }
   if (!result.data) {
     // 删除 KV 成功
     return;
   }
   // 删除失败的 K 和对应的错误,视情况决定是否重新删除失败的 KV
   let errorMap = result.data as Map<string,EngineError>;
 });
聊天室 ID
key 数组,长度范围 [1,10]
是否强制删除
返回的具体结果,会明确特定 key 的具体错误
获取本地指定一批聊天室自定义属性
 let roomId = "聊天室 ID";
 let list = new List<string>();
 list.add("key1");
 list.add("key2");
 IMEngine.getInstance().getChatroomEntries(roomId, list).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取 KV 失败
     return;
   }
   if (!result.data) {
     // KV 为空
     return;
   }
   // KV map
   let kvMap = result.data as Map<string,string>;
 });
聊天室 ID
key 数组,长度范围 [1,100]
对应的 kv 信息
获取本地聊天室全部自定义属性
 let roomId = "聊天室 ID";
 IMEngine.getInstance().getAllChatroomEntries(roomId).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取 KV 失败
     return;
   }
   if (!result.data) {
     // KV 为空
     return;
   }
   // KV map
   let kvMap = result.data as Map<string,string>;
 });
聊天室 ID
对应的 kv 信息
设置聊天室 KV 状态变化的监听
 let listener: ChatroomKVStatusListener = {
   onChatroomKVSync: (roomId: string): void => {
   },
   onChatroomKVUpdate: (roomId: string, entries: Map<string, string>): void => {
   },
   onChatroomKVRemove: (roomId: string, entries: Map<string, string>): void => {
   }
 }
 IMEngine.getInstance().setChatroomKVStatusListener(listener);
聊天室 KV 状态变化的监听
增加聊天室 KV 状态变化的监听
 let listener: ChatroomKVStatusListener = {
   onChatroomKVSync: (roomId: string): void => {
   },
   onChatroomKVUpdate: (roomId: string, entries: Map<string, string>): void => {
   },
   onChatroomKVRemove: (roomId: string, entries: Map<string, string>): void => {
   }
 }
 IMEngine.getInstance().addChatroomKVStatusListener(listener);
监听
监听
设置聊天室成员变化监听
 let listener: ChatroomMemberActionListener = {
   onMemberChange: (actionModel: ChatRoomMemberActionModel): void => {
   }
 }
 IMEngine.getInstance().setChatroomMemberListener(listener);
成员变化监听
增加聊天室成员变化监听
 let listener: ChatroomMemberActionListener = {
   onMemberChange: (actionModel: ChatRoomMemberActionModel): void => {
   }
 }
 IMEngine.getInstance().addChatroomMemberListener(listener);
成员变化监听
成员变化监听
设置聊天室事件通知监听器
 let listener: ChatroomNotifyEventListener = {
   onChatroomNotifyMultiLoginSync: (syncEvent: ChatroomSyncEvent): void => {
   },
   onChatroomNotifyBlock: (blockEvent: ChatroomMemberBlockEvent): void => {
   },
   onChatRoomNotifyBan: (banEvent: ChatroomMemberBanEvent): void => {
   }
 }
 IMEngine.getInstance().setChatroomNotifyEventListener(listener);
监听
增加聊天室事件通知监听器
 let listener: ChatroomNotifyEventListener = {
   onChatroomNotifyMultiLoginSync: (syncEvent: ChatroomSyncEvent): void => {
   },
   onChatroomNotifyBlock: (blockEvent: ChatroomMemberBlockEvent): void => {
   },
   onChatRoomNotifyBan: (banEvent: ChatroomMemberBanEvent): void => {
   }
 }
 IMEngine.getInstance().addChatroomNotifyEventListener(listener);
监听
监听
创建群组
群信息(GroupInfo)支持设置的属性:<br>
1,群ID(id),最大长度 64 个字符。支持大小写英文字母与数字的组合<br>
2,群名称(name),最长不超过 64 个字符<br>
3,群头像(portraitUri),长度不超过 128 个字符<br>
4,群简介(introduction),最大长度不超过 512 个字符<br>
5,群公告(notice),最大长度不超过 1024 个字符<br>
6,群扩展信息(extProfile),默认最多可设置 10 个,需要通过开发者后台或 API 设置后才能使用,否则设置失败<br>
7,主动加入群权限模式(joinPermission)<br>
8,将群成员移出群组设置模式(removeMemberPermission)<br>
9,邀请他人入群模式(invitePermission)<br>
10,被邀请入群模式(inviteHandlePermission)<br>
11,群信息更新模式(groupInfoEditPermission)<br>
12,群成员信息更新模式(memberInfoEditPermission)<br>
其中:群ID(id)、群名称(name)必填,否则接口调用失败。<br>
`processCode` 参数说明:<br>
当群组的 `inviteHandlePermission` 为被邀请人需要同意才能进群时,`processCode` 返回 `GroupNeedInviteeAccept` ( 25427 ),表示需要被邀请人同意后才能进入群组。<br>
当群组的 `inviteHandlePermission` 为不需被邀请人同意时,`processCode` 返回 Success ( 0 ),被邀请人会直接加入群组。<br>
 // 群 Id。必填,不能为空,长度不超过 64 个字符,大小写英文字母与数字的组合,不能包含空格
 let groupId = "groupId";
 // 群名称。必填,不能为空,长度不超过 64 个字符
 let groupName = "groupName";
 let portraitUri = "";
 let introduction = "这是一个测试群";
 let notice = "";
 let joinPermission = 0; // 需要群主验证
 let removeMemberPermission = 0; // 群主
 let invitePermission = 0; // 群主
 let inviteHandlePermission = 0; // 不需要被邀请人同意
 let groupInfoEditPermission = 0; // 群主
 let memberInfoEditPermission = 0; // 群主+管理员+自己
 let hashMap = new HashMap<string, string>();
 hashMap.set("kye1", "value1");
 hashMap.set("ley2", "value2");
 let groupInfo = new GroupInfo();
 groupInfo.setGroupId(groupId);
 groupInfo.setGroupName(groupName);
 groupInfo.setPortraitUri(portraitUri);
 groupInfo.setIntroduction(introduction);
 groupInfo.setNotice(notice);
 groupInfo.setJoinPermission(joinPermission);
 groupInfo.setRemoveMemberPermission(removeMemberPermission);
 groupInfo.setInvitePermission(invitePermission);
 groupInfo.setInviteHandlePermission(inviteHandlePermission);
 groupInfo.setGroupInfoEditPermission(groupInfoEditPermission);
 groupInfo.setMemberInfoEditPermission(memberInfoEditPermission);
 groupInfo.setExtProfile(hashMap);
 // 设置加入群组的用户Id,非必填,一次最多允许 30 个用户加入。
 let userIds = ["user1Id", "user2Id"];
 IMEngine.getInstance().createGroup(groupInfo, userIds).then(result => {
   if (EngineError.Success !== result.code) {
     // 创建群组失败
     if (result.data) {
       let ret: GroupResultWithProcessCode<string> = result.data;
       if (ret.dataArray) {
         let array: Array<string> = ret?.dataArray; // 失败的 key 数组
       }
     }
   } else {
     // 创建群组成功
     if (result.data) {
       let ret: GroupResultWithProcessCode<string> = result.data;
       let processCode = ret.processCode; // 业务错误码
     }
   }
 });
群组信息
加入群组的用户 Id 数组,一次最多允许 30 个用户加入。
更新群组资料
群信息(GroupInfo)支持设置的属性:<br>
1,群ID(id),最大长度 64 个字符。支持大小写英文字母与数字的组合<br>
2,群名称(name),最长不超过 64 个字符<br>
3,群头像(portraitUri),长度不超过 128 个字符<br>
4,群简介(introduction),最大长度不超过 512 个字符<br>
5,群公告(notice),最大长度不超过 1024 个字符<br>
6,群扩展信息(extProfile),默认最多可设置 10 个,需要通过开发者后台或 API 设置后才能使用,否则设置失败<br>
7,主动加入群权限模式(joinPermission)<br>
8,将群成员移出群组设置模式(removeMemberPermission)<br>
9,邀请他人入群模式(invitePermission)<br>
10,被邀请入群模式(inviteHandlePermission)<br>
11,群信息更新模式(groupInfoEditPermission)<br>
12,群成员信息更新模式(memberInfoEditPermission)<br>
其中:群ID(id)、群名称(name)必填,否则接口调用失败。<br>
 // 群 Id
 let groupId = "groupId";
 let groupName = "groupName";
 let portraitUri = "";
 let introduction = "这是一个测试群";
 let notice = "";
 let joinPermission = 0; // 需要群主验证
 let removeMemberPermission = 0; // 群主
 let invitePermission = 0; // 群主
 let inviteHandlePermission = 0; // 不需要被邀请人同意
 let groupInfoEditPermission = 0; // 群主
 let memberInfoEditPermission = 0; // 群主+管理员+自己
 let hashMap = new HashMap<string, string>();
 hashMap.set("kye1", "value1");
 hashMap.set("key2", "value2");
 let groupInfo = new GroupInfo();
 groupInfo.setGroupId(groupId);
 groupInfo.setGroupName(groupName);
 groupInfo.setPortraitUri(portraitUri);
 groupInfo.setIntroduction(introduction);
 groupInfo.setNotice(notice);
 groupInfo.setJoinPermission(joinPermission);
 groupInfo.setRemoveMemberPermission(removeMemberPermission);
 groupInfo.setInvitePermission(invitePermission);
 groupInfo.setInviteHandlePermission(inviteHandlePermission);
 groupInfo.setGroupInfoEditPermission(groupInfoEditPermission);
 groupInfo.setMemberInfoEditPermission(memberInfoEditPermission);
 groupInfo.setExtProfile(hashMap);
 IMEngine.getInstance().updateGroupInfo(groupInfo).then(result => {
   if (EngineError.Success !== result.code) {
     // 更新群组信息失败
     if (result.data) {
       let array: Array<string> = result.data; // 具体失败的 key 数组
     }
   }
   // 更新群组信息成功
 });
群信息, groupId 必填,不能为空,长度不超过 64 个字符,大小写英文字母与数字的组合,不能包含空格
批量获取群组资料
注意:只返回已存在的群组信息
 // 群 Id 列表
 let groupIds = ["group1Id", "group2Id"];
 IMEngine.getInstance().getGroupsInfo(groupIds).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取群信息失败
     return;
   }
   // 获取群信息成功
   let ret : Object = result;
   if (result.data) {
     ret = Array.from(result.data as Array<GroupInfo>);
   }
 });
群 Id 数组。支持批量查询,单次查询最多支持 20 个群组。
操作完成后,结果通过此回调返回。
分页获取指定群组的群成员列表
 // 群 Id
 let groupId = "groupId";
 // 通过 role 参数指定拉取全部群成员角色类型的群成员信息
 let role = GroupMemberRole.Undef; // 未定义角色(使用此枚举代表查询全部类型群成员)
 // 分页拉取参数
 let pageToken = "";
 // 设置分页大小,取值范围为 [1~100]。
 let count = 10;
 // 按加入群组时间正序、倒序获取。true:正序;false:倒序。
 let order = false;
 // 分页请求参数
 let paging_option = new PagingQueryOption(pageToken, count, order)
 IMEngine.getInstance().getGroupMembersByRole(groupId, role, paging_option).then(result => {
   if (EngineError.Success !== result.code) {
     // 拉取失败
     return;
   }
   // 拉取成功
   if (result.data) {
     let ret: PagingQueryResult<GroupMemberInfo> = result.data;
     let pageToken: string = ret.pageToken;
     let totalCount: number = ret.totalCount;
     let data = Array.from(ret.data as Array<GroupMemberInfo>);
     // 使用返回的 pageToken 拉取下一页
   }
 });
群组Id。
查询群成员角色。
分页请求参数。包含页面标识(非必填,不填返回第一页数据)、每页条数(最大不超过 100 条)、是否正序查询(默认按加入群组时间倒序)
操作完成后,结果通过此回调返回。注意:此接口返回分页数据的总条数。
获取已加入指定群成员信息
 // 群 Id
 let groupId = "groupId";
 // 设置查询用户 Id 列表
 let userIds = ["user1Id", "user2Id"];
 IMEngine.getInstance().getGroupMembers(groupId, userIds).then(result => {
   if (EngineError.Success !== result.code) {
     // 拉取失败
     return;
   }
   // 拉取成功
   let ret: object = result;
   if (result.data) {
     ret = Array.from(result.data as Array<GroupMemberInfo>);
   }
 });
群组 Id
用户 Id 列表,一次最多不超过 100 个
操作完成后,结果通过此回调返回。
检查用户是否在群组中
 let groupId = "test_group";
 let userIds = ["user1", "user2"];
 IMEngine.getInstance().checkUserInGroup(groupId, userIds).then(result => {
   if (EngineError.Success !== result.code) {
     // 失败
     return;
   }
   if (result.data) {
     let ret: Array<string> = result.data;
   }
 });
群组 Id
用户 Id 列表,一次最多不超过 100 个
操作完成后,结果通过此回调返回。
踢出群组成员
 // 群 Id
 let groupId = "groupId";
 // 用户 Id 列表
 let userIds = ["user1Id", "user2Id"];
 // 是否移除群成员禁言状态(默认为 true)
 let removeMute = true;
 // 是否移除白名单(默认为 true)
 let removeWhiteList = true;
 // 是否移除群组特别关注的用户(默认为 true)
 let removeFavoriteMembers = true;
 let config = new QuitGroupConfig(removeMute, removeWhiteList, removeFavoriteMembers);
 IMEngine.getInstance().kickGroupMembers(groupId, userIds, config).then(result => {
   if (EngineError.Success !== result.code) {
     // 操作失败
   }
   // 操作成功
 });
群组 Id
用户 Id 列表,一次最多不超过 100 个
移除群组成员配置
操作完成后,结果通过此回调返回。
退出群组
 // 群 Id
 let groupId = "groupId";
 // 是否移除群成员禁言状态 (默认为 true)
 let removeMute = true;
 // 是否移除白名单(默认为 true)
 let removeWhiteList = true;
 // 是否移除群组特别关注的用户(默认为 true)
 let removeFavoriteMembers = true;
 let config = new QuitGroupConfig(removeMute, removeWhiteList, removeFavoriteMembers);
 IMEngine.getInstance().quitGroup(groupId, config).then(result => {
   if (EngineError.Success !== result.code) {
     // 退出失败
   }
   // 退出成功
 });
群组 Id
退出群组配置
操作完成后,结果通过此回调返回。
解散群组
 let groupId = "groupId";
 IMEngine.getInstance().dismissGroup(groupId).then(result => {
   if (EngineError.Success !== result.code) {
     // 解散失败
   }
   // 解散成功
 });
群组 Id
操作完成后,结果通过此回调返回。
转让群组
 // 群 Id
 let groupId = "groupId";
 // 转让后的群主用户 Id
 let newOwnerId = "userId";
 // 转让后退出群组
 let autoQuit = true;
 // 是否移除群成员禁言状态(默认为 true)
 let removeMute = true;
 // 是否移除白名单(默认为 true)
 let removeWhiteList = true;
 // 是否移除群组特别关注的用户(默认为 true)
 let removeFavoriteMembers = true;
 let config = new QuitGroupConfig(removeMute, removeWhiteList, removeFavoriteMembers);
 IMEngine.getInstance().transferGroupOwner(groupId, newOwnerId, autoQuit, config).then(result => {
   if (EngineError.Success !== result.code) {
     // 转让失败
   }
   // 转让成功
 });
群组 Id,必填,不能为空,长度不超过 64 个字符,大小写英文字母与数字的组合,不能包含空格
新群主用户 Id,必填,不能为空,长度不超过 64 个字符,大小写英文字母与数字的组合,不能包含空格
是否自动退出群组,必填,true 表示自动退出群组,false 表示不自动退出群组
转让群组配置,必填,不能为空
操作完成后,结果通过此回调返回。
添加群管理员
 // 群 Id
 let groupId = "groupId";
 // 管理员用户 Id 列表
 let userIds = ["user1Id", "user2Id"];
 IMEngine.getInstance().addGroupManagers(groupId, userIds).then(result => {
   if (EngineError.Success !== result.code) {
     // 添加失败
   }
   // 添加成功
 });
群组 Id,必填,不能为空,长度不超过 64 个字符,大小写英文字母与数字的组合,不能包含空格
用户 Id 列表,必填,用户 Id 必须为群组成员,一次最多设置 10 个群成员为管理员,管理员上限为 10 个,群主不支持设置为管理员
操作完成后,结果通过此回调返回。
移除群管理员
 // 群 Id
 let groupId = "groupId";
 // 管理员用户 Id 列表
 let userIds = ["user1Id", "user2Id"];
 IMEngine.getInstance().removeGroupManagers(groupId, userIds).then(result => {
   if (EngineError.Success !== result.code) {
     // 移除失败
   }
   // 移除成功
 });
群组 Id,必填,不能为空,长度不超过 64 个字符,大小写英文字母与数字的组合,不能包含空格
用户 Id 列表,必填,用户 Id 必须为群组成员,一次最多操作 10 个管理员
操作完成后,结果通过此回调返回。
设置群成员资料
群成员信息更新模式 memberInfoEditPermission ,决定是否可以修改群成员资料
 // 群 Id
 let groupId = "test_group";
 // 群成员用户 Id
 let userId = "userId";
 // 群成员昵称
 let nickname = "name";
 // 群成员附加信息
 let extra = "extra";
 IMEngine.getInstance().setGroupMemberInfo(groupId, userId, nickname, extra).then(result => {
   if (EngineError.Success !== result.code) {
     // 操作失败
     if (result.data) {
       let array: Array<string> = result.data; // 失败的 key 数组
     }
     // 操作成功
   }
 });
群组 ID,必填,不能为空,长度不超过 64 个字符,大小写英文字母与数字的组合,不能包含空格
群成员用户 ID,必填,不能为空,长度不超过 64 个字符,大小写英文字母与数字的组合,不能包含空格
群成员昵称,长度不超过 64 个字符,不支持纯空格
群成员附加信息,长度不超过 128 个字符,注意:传 null 代表不设置此字段
根据群成员昵称查询群成员信息
 // 群 Id
 let groupId = "groupId";
 // 群成员昵称,不能为空最长不超过 64 个字符
 let nickname = "name";
 // 分页拉取参数
 let pageToken = null; // 首次查询可以传 null
 // 设置分页大小,取值范围为 [1~200]。
 let count = 10;
 // 按加入群组时间正序、倒序获取。true:正序;false:倒序。
 let order = false;
 // 分页请求参数
 let paging_option = new PagingQueryOption(pageToken, count, order)
 IMEngine.getInstance().searchGroupMembers(groupId, nickname, paging_option).then(result => {
   if (EngineError.Success !== result.code) {
     // 拉取失败
     return;
   }
   // 拉取成功
   if (result.data) {
     let ret: PagingQueryResult<GroupMemberInfo> = result.data;
     let pageToken: string = ret.pageToken;
     let totalCount: number = ret.totalCount;
     let data = Array.from(ret.data as Array<GroupMemberInfo>);
     // 使用返回的 pageToken 拉取下一页
   }
 });
群组 Id
群成员昵称搜索关键字。注意:不能为空最长不超过 64 个字符,不支持纯空格;支持模糊搜索查询;昵称为空时,默认搜索用户名
分页请求参数。包含页面标识(非必填,不填返回第一页数据)、每页条数(最大不超过 200 条)、是否正序查询(默认倒序)
加入群组
 // 群 Id
 let groupId = "groupId";
 IMEngine.getInstance().joinGroup(groupId).then(result => {
   if (EngineError.Success !== result.code) {
     // 加入群组请求
     return;
   }
   if (result.data) {
     // 加入群组请求成功时需要处理 processCode
     let ret: GroupResultWithProcessCode<void> = result.data;
     let processCode = ret.processCode;
   }
 });
- 当群组的 `joinPermission` 为需要群主或管理员审批时,`code` 返回 `GroupJoinGroupNeedManagerAccept` ( 25424 ),表示需要等待群主或管理员的审批。
- 当群组的 `joinPermission` 为不用验证时,`code` 返回 Success ( 0 ),表示加入群组成功。
群组 Id
邀请用户加入群组
 // 群 Id
 let groupId = "groupId";
 // 用户 Id 列表
 let userIds = ["user1Id", "user2Id"];
 IMEngine.getInstance().inviteUsersToGroup(groupId, userIds).then(result => {
   if (EngineError.Success !== result.code) {
     // 邀请加入群组请求失败
     return;
   }
   if (result.data) {
     // 邀请加入群组请求成功需要处理 processCode
     let ret: GroupResultWithProcessCode<void> = result.data;
     let processCode = ret.processCode;
   }
 });
谁可以邀请他人入群方式 {@link GroupOperationPermission},决定是否可以邀请他人
邀请加入群组处理方式 {@link GroupInviteHandlePermission},决定是否可以加入群组
- 当该群组主动加入权限 joinPermission 为需群主或管理员审批时,code 返回 GroupJoinGroupNeedManagerAccept( 25424 ),表示需要等待群主或管理员审批。同时群主或管理员会收到群组申请的事件回调。
- 当该群组主动加入权限 joinPermission 为不用验证,被邀请加入群组权限 inviteHandlePermission 为需要被邀请人同意时,code 返回 GroupNeedInviteeAccept( 25427 ),表示需要被邀请人同意。
群组 Id,必填,不能为空,长度不超过 64 个字符,大小写英文字母与数字的组合,不能包含空格
用户 Id 列表,一次最多不超过 30 个
用户同意加入群组
 // 群 Id
 let groupId = "groupId";
 // 发出邀请的用户 Id
 let inviterId = "inviterId";
 IMEngine.getInstance().acceptGroupInvite(groupId, inviterId).then(result => {
   if (EngineError.Success !== result.code) {
     // 用户同意加入群组失败
     return;
   }
   // 用户同意加入群组成功
 });
群组 Id
发出邀请的用户 Id
用户拒绝加入群组
 // 群 Id
 let groupId = "groupId";
 // 发出邀请的用户 Id
 let inviterId = "inviterId";
 // 拒绝原因
 let reason = "拒绝原因";
 IMEngine.getInstance().refuseGroupInvite(groupId, inviterId, reason).then(result => {
   if (EngineError.Success !== result.code) {
     // 用户拒绝加入群组失败
   }
   // 用户拒绝加入群组成功
 });
群组 ID,必填,不能为空,长度不超过 64 个字符,大小写英文字母与数字的组合,不能包含空格
邀请者 ID
拒绝原因,非必填项,拒绝时可选择是否输入拒绝原因,内容不超过 128 个字符
群主或管理员同意用户加入群组
 // 群 Id
 let groupId = "test_group";
 // 发出邀请的用户 Id
 let inviterId = "inviterId";
 // 申请入群用户 Id
 let applicantId = "applicantId";
 IMEngine.getInstance().acceptGroupApplication(groupId, inviterId, applicantId).then(result => {
   if (EngineError.Success !== result.code) {
     // 同意加入群组请求失败
     return;
   }
   if (result.data) {
     // 同意加入群组请求成功需要处理 processCode
     let ret: GroupResultWithProcessCode<void> = result.data;
     let processCode = ret.processCode;
   }
 });
- 当群组的 `inviteHandlePermission` 为需要被邀请人同意时,若 `code` 返回 `GroupNeedInviteeAccept` (25427),表示需等待被邀请人同意方可加入群组。
- 当群组的 `inviteHandlePermission` 为无需被邀请人同意时,若 `code` 返回 `Success` (0),表示被邀请人已成功加入群组。
以上仅适用于邀请加入群组的情况,当用户主动申请加入群组时,`code` 始终为 `Success` (0)。
群组 ID,必填,不能为空,长度不超过 64 个字符,大小写英文字母与数字的组合,不能包含空格
邀请人用户 ID,非必填,如果是邀请入群,则传邀请人 ID;如果是用户主动加群,可以为空。
申请入群用户 ID
群主或管理员拒绝用户加入群组
 // 群 Id
 let groupId = "groupId";
 // 发出邀请的用户 Id
 let inviterId = "inviterId";
 // 申请入群用户 Id
 let applicantId = "applicantId";
 // 拒绝原因
 let reason = "拒绝原因";
 IMEngine.getInstance().refuseGroupApplication(groupId, inviterId, applicantId, reason).then(result => {
   if (EngineError.Success !== result.code) {
     // 拒绝加入群组请求失败
   }
   // 拒绝加入群组请求成功
 });
群组 ID,必填,不能为空,长度不超过 64 个字符,大小写英文字母与数字的组合,不能包含空格
邀请人用户 ID,非必填,如果是邀请入群,则传邀请人 ID;如果是主动加群,可以为空。
申请者 ID
拒绝原因,非必填项,拒绝时可选择是否输入拒绝原因,内容不超过 128 个字符
分页获取群组请求列表
 // 分页拉取参数
 let pageToken = null;
 // 设置分页大小,取值范围为 [1~100]。
 let count = 10;
 // 按操作时间正序、倒序获取。true:正序;false:倒序。
 let order = false;
 // 分页请求参数
 let paging_option = new PagingQueryOption(pageToken, count, order)
 // 查询发出的申请 + 收到的申请类型的请求
 let directionArray:Array<GroupApplicationDirection> = [GroupApplicationDirection.ApplicationSent, GroupApplicationDirection.ApplicationReceived];
 // 查询管理员待处理 + 管理员拒绝 + 已加入类型的申请
 let statusArray: Array<GroupApplicationStatus> = [GroupApplicationStatus.ManagerUnHandled, GroupApplicationStatus.ManagerRefused, GroupApplicationStatus.Joined];
 IMEngine.getInstance().getGroupApplications(paging_option, directionArray, statusArray).then(result => {
   if (EngineError.Success !== result.code) {
     // 拉取失败
     return
   }
   // 拉取成功
   if (result.data) {
     let data : PagingQueryResult<GroupApplicationInfo> = result.data;
     let pageToken: string = data?.pageToken;
     let totalCount: number = data?.totalCount;
     let infoArr: Array<GroupApplicationInfo> = Array.from(data?.data);
     // 使用返回的 pageToken 拉取下一页
   }
 });
分页请求参数。参照PagingQueryOption,包含页面标识(非必填,不填返回第一页数据)、每页条数(最大不超过 200 条)、是否正序查询(默认倒序)
请求的方向数组
群组请求状态数组
操作完成后,结果通过此回调返回。按操作时间倒序排序。注意:此接口不返回分页数据的总条数。
按角色获取已加入群组的资料
 // 通过 role 参数指定拉取全部群成员角色类型的群
 let role : GroupMemberRole  = GroupMemberRole.Undef; // 按需使用角色枚举值
 // 分页拉取参数
 let pageToken = null;
 // 设置分页大小,取值范围为 [1~100]。
 let count = 10;
 // 按加入群组时间正序、倒序获取。true:正序;false:倒序
 let order = false;
 // 分页请求参数
 let paging_option = new PagingQueryOption(pageToken, count, order);
 IMEngine.getInstance().getJoinedGroupsByRole(role, paging_option).then(result => {
   if (EngineError.Success !== result.code) {
     // 拉取失败
     return
   }
   // 拉取成功
   if (result.data) {
     let data: PagingQueryResult<GroupInfo> = result.data;
     let pageToken: string = data?.pageToken;
     let totalCount: number = data?.totalCount;
     let arr: Array<GroupInfo> = Array.from(data?.data as Array<GroupInfo>);
     // 使用返回的 pageToken 拉取下一页
   }
 });
群成员角色
查询选项,包含 页面标识(非必填,不填返回第一页数据)、每页条数(最大不超过 100 条)、是否正序查询(默认倒序)
按群名称搜索我加入的群组
 // 群名称
 let groupName = "test group";
 // 分页拉取参数
 let pageToken = null;
 // 设置分页大小,取值范围为 [1~200]。
 let count = 10;
 // 按加入群组时间正序、倒序获取。true:正序;false:倒序。
 let order = false;
 // 分页请求参数
 let paging_option = new PagingQueryOption(pageToken, count, order)
 IMEngine.getInstance().searchJoinedGroups(groupName, paging_option).then(result => {
   if (EngineError.Success !== result.code) {
     // 拉取失败
     return;
   }
   // 拉取成功
   if (result.data) {
     let data: PagingQueryResult<GroupInfo> = result.data;
     let pageToken: string = data?.pageToken;
     let totalCount: number = data?.totalCount;
     let arr: Array<GroupInfo> = Array.from(data?.data as Array<GroupInfo>);
     // 使用返回的 pageToken 拉取下一页
   }
 });
群名称搜索关键字。不能为空最长不超过 64 个字符,不支持纯空格,支持模糊搜索查询时需要去掉前后空格。
分页请求参数。参照PagingQueryOption,包含页面标识(非必填,不填返回第一页数据)、每页条数(最大不超过 200 条)、是否正序查询(默认倒序)
操作完成后,结果通过此回调返回。注意:此接口返回分页数据的总条数。
批量获取我加入的群组
 let groupIds = ["group1Id", "group2Id"];
 IMEngine.getInstance().getJoinedGroups(groupIds).then(result => {
   if (EngineError.Success !== result.code) {
     // 获取失败
     return;
   }
   // 获取成功
   let ret: object = result;
   if (result.data) {
     ret = Array.from(result.data as Array<GroupInfo>);
   }
 });
群Id列表。最多不超过 20 个
操作完成后,结果通过此回调返回。
设置群组备注名
 // 群 Id
 let groupId = "groupId";
 // 群备注名
 let remark = "group remark";
 IMEngine.getInstance().setGroupRemark(groupId, remark).then(result => {
   if (EngineError.Success !== result.code) {
     // 设置失败
     return;
   }
   // 设置成功
 });
群组 ID,必填,不能为空,长度不超过 64 个字符,大小写英文字母与数字的组合,不能包含空格
群备注,字符串长度不超过 64 个字符。传 null 或 空字符串 表示移除群备注
添加群组特别关注用户
 let groupId = "groupId";
 let userIds = ["user1Id", "user2Id"];
 IMEngine.getInstance().addGroupFollows(groupId, userIds).then(result => {
   if (EngineError.Success !== result.code) {
     // 添加失败
   }
   // 添加成功
 });
群组 Id,必填,不能为空,长度不超过 64 个字符,大小写英文字母与数字的组合,不能包含空格
用户 Id 列表,单次最多关注 100 个用户
删除群组特别关注用户
 // 群 Id
 let groupId = "groupId";
 // 用户 Id 列表
 let userIds = ["user1Id", "user2Id"];
 IMEngine.getInstance().removeGroupFollows(groupId, userIds).then(result => {
   if (EngineError.Success !== result.code) {
     // 失败
   }
 });
群组 Id,必填,不能为空,长度不超过 64 个字符,大小写英文字母与数字的组合,不能包含空格
用户 Id 列表,单次取消关注 100 个用户
查询群组特别关注用户列表
 // 群 Id
 let groupId = "groupId";
 IMEngine.getInstance().getGroupFollows(groupId).then(result => {
   if (EngineError.Success !== result.code) {
     // 查询失败
     return;
   }
   // 查询成功
   let ret : Object = result;
   if (result.data) {
     ret = Array.from(result.data);
   }
 });
群 Id。只支持普通群。
添加群组事件回调监听
 let listener: GroupEventListener = {
   onGroupOperation : (
      groupId: string,
      operatorInfo: GroupMemberInfo,
      groupInfo: GroupInfo,
      operation: GroupOperation,
      memberInfos: Array<GroupMemberInfo>,
      operationTime: number
    ): void => {
    },
    onGroupInfoChanged : (
      operatorInfo: GroupMemberInfo,
      fullGroupInfo: GroupInfo,
      properties: Array<string>,
      operationTime: number
    ): void => {
    },
    onGroupMemberInfoChanged : (
      groupId: string,
      operatorInfo: GroupMemberInfo,
      memberInfo: GroupMemberInfo,
      operationTime: number
    ): void => {
    },
    onGroupApplicationEvent : (
      info: GroupApplicationInfo
    ): void => {
    },
    onGroupRemarkChangedSync : (
      groupId: string,
      operationType: GroupOperationType,
      groupRemark: string,
      operationTime: number
    ): void => {
    },
    onGroupFollowsChangedSync : (
      groupId: string,
      operationType: GroupOperationType,
      userIds: Array<string>,
      operationTime: number
    ): void => {
    }
 }
 IMEngine.getInstance().addGroupEventListener(listener);
监听
移除群组事件回调监听
 let listener: GroupEventListener = {
   onGroupOperation : (
      groupId: string,
      operatorInfo: GroupMemberInfo,
      groupInfo: GroupInfo,
      operation: GroupOperation,
      memberInfos: Array<GroupMemberInfo>,
      operationTime: number
    ): void => {
    },
    onGroupInfoChanged : (
      operatorInfo: GroupMemberInfo,
      fullGroupInfo: GroupInfo,
      properties: Array<string>,
      operationTime: number
    ): void => {
    },
    onGroupMemberInfoChanged : (
      groupId: string,
      operatorInfo: GroupMemberInfo,
      memberInfo: GroupMemberInfo,
      operationTime: number
    ): void => {
    },
    onGroupApplicationEvent : (
      info: GroupApplicationInfo
    ): void => {
    },
    onGroupRemarkChangedSync : (
      groupId: string,
      operationType: GroupOperationType,
      groupRemark: string,
      operationTime: number
    ): void => {
    },
    onGroupFollowsChangedSync : (
      groupId: string,
      operationType: GroupOperationType,
      userIds: Array<string>,
      operationTime: number
    ): void => {
    }
 }
 IMEngine.getInstance().removeGroupEventListener(listener);
监听
获取机器人列表
 IMEngine.getInstance().getAllRobots().then(result => {
   // code 不为 0 时,表示获取到的是本地数据
   let ret: object = result;
   if (result.data) {
     ret = Array.from(result.data);
   }
 });
获取机器人信息
 let robotId = "robotId";
 IMEngine.getInstance().getRobotById(robotId).then(result => {
   // code 不为 0 时,表示获取到的是本地数据
 });
机器人 ID
添加机器人事件回调监听
 let listener: RobotEventListener = {
   onRobotSyncCompleted : (
      groupId: string,
      code: number,
      nativeArr: Array<RobotInfo>
    ): void => {
    }
 }
 IMEngine.getInstance().addRobotEventListener(listener);
监听
移除机器人事件回调监听
 let listener: RobotEventListener = {
   onRobotSyncCompleted : (
      code: number
    ): void => {
    },
 }
 IMEngine.getInstance().removeRobotEventListener(listener);
监听
添加消息修改事件监听
 let listener: MessageModifiedListener = {
   onMessageModified: (messages: Array<Message>) => {
     // 接收到的某条消息被修改时,会触发此回调
   },
   onModifiedMessageSyncCompleted: () => {
     // 离线的消息修改记录同步完成时,会触发此回调
   }
 }
 IMEngine.getInstance().addMessageModifiedListener(listener);
监听
移除消息修改事件监听
 let listener: MessageModifiedListener = {
   onMessageModified: (message: Message) => {
     // 消息修改
   },
   onModifiedMessageSyncCompleted: () => {
     // 消息修改同步完成
   }
 }
 IMEngine.getInstance().removeMessageModifiedListener(listener);
监听
修改消息
 let content = new TextMessage();
 content.content = "content";
 let params: IModifyMessageParams = {
   messageUId: "messageUid",
   messageContent: content,
 }
 IMEngine.getInstance().modifyMessageWithParams(params).then(result => {
   // 修改消息成功
 });
修改消息参数
刷新引用消息
 let conversationIdentifier = new ConversationIdentifier();
 conversationIdentifier.conversationType = ConversationType.Private;
 conversationIdentifier.targetId = "targetId";
 let referenceMessageUidList = new Array<string>();
 referenceMessageUidList.push("messageUid1");
 referenceMessageUidList.push("messageUid2");
 let params: IRefreshReferenceMessageParams = {
   conversationIdentifier: conversationIdentifier,
   messageUIds: referenceMessageUidList
 }
 IMEngine.getInstance().refreshReferenceMessageWithParams(params, (msg: Array<MessageResult>) => {
   // 被引用消息在本地,刷新 ui
 }, (msg: Array<MessageResult>) => {
   // 被引用消息在服务端,刷新 ui
 }).then(result => {
   // 接口调用失败,错误处理
 });
被引用消息在本地获取到的引用消息结果回调
被引用消息在远端获取到的引用消息结果回调
IM SDK 核心类
Version
1.0.0