更新记录

5.5.0(2022-10-13)

  1. 新增直播浮窗功能(内测);

5.4.1(2022-07-26)

  1. 修复Android的自定义消息无法使用extension的bug;

5.4.0(2022-06-21)

  1. 修复iOS缺少onInviteeAccepted事件bug;
  2. 优化日志管理和文件路径配置;
  3. 新增消息修改回调;
查看更多

平台兼容性

Android Android CPU类型 iOS
适用版本区间:4.4 - 12.0 armeabi-v7a:未测试,arm64-v8a:未测试,x86:未测试 适用版本区间:9 - 15

原生插件通用使用流程:

  1. 购买插件,选择该插件绑定的项目。
  2. 在HBuilderX里找到项目,在manifest的app原生插件配置中勾选模块,如需要填写参数则参考插件作者的文档添加。
  3. 根据插件作者的提供的文档开发代码,在代码中引用插件,调用插件功能。
  4. 打包自定义基座,选择插件,得到自定义基座,然后运行时选择自定义基座,进行log输出测试。
  5. 开发完毕后正式云打包

付费原生插件目前不支持离线打包。
Android 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/android
iOS 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/ios

注意事项:使用HBuilderX2.7.14以下版本,如果同一插件且同一appid下购买并绑定了多个包名,提交云打包界面提示包名绑定不一致时,需要在HBuilderX项目中manifest.json->“App原生插件配置”->”云端插件“列表中删除该插件重新选择


腾讯云IM

即时通信 IM 提供全球接入、单聊、群聊、好友管理、群组管理、资料关系链托管、帐号鉴权等全方位解决方案,并提供完备的 App 接入、后台管理接口,可以应用于社交沟通、互动直播、 智能客服、物联网通信、企业通信、系统消息通知、游戏交流等场景。

接口模式(纯API)

扫描下方二维码,安装示例代码,快速体验插件功能:

Android iOS 联系我们
Android示例代码 iOS示例代码 技术支持

扫码添加技术支持(微信号: ruanyunkeji006),开通测试账号。

UI模式

扫描下方二维码,安装示例代码,快速体验插件功能:

Android iOS 联系我们
Android示例代码 iOS示例代码 技术支持

扫码添加技术支持(微信号: ruanyunkeji006),开通测试账号。

定制UI

扫码添加我们技术支持(微信号: ruanyunkeji006),联系定制UI

技术支持

建议扫码添加我们技术支持,协助接入和测试。

联系我们 微信号 更多功能
联系我们
ruanyunkeji006

消息多媒体文件下载
离线推送
自动签名

API 接口文档

使用教程

快速开始

基础配置

创建IM应用

  • 加载插件

加载uniapp平台的原生插件,需要自定义基座后才能使用,您可以按照自定义基座文档进行。

uniApp module模块需要加载才能使用,模块名称为: RY-TencentIMPro

var Im = uni.requireNativePlugin("RY-TencentIMPro");
  • 腾讯云配置

注册或登录腾讯云账号,实名认证后,开通即时通信IM

  1. 点击"添加新应用"创建新应用
  2. 点击创建的应用,进入应用,点击"SDKAppID"后面的复制按钮,复制sdkAppId,并保存;
  3. 点击"显示密钥",会显示密钥,点击"密钥"后面的复制按钮,复制key,并保存。
  • 生成签名

手动签名点击 UserSig生成&校验 选择对应的sdkAppId的应用,输入userId,获取对应的用户签名userSig;

如果您需要【自动签名】,联系我们获取。

初始化与登录

初始化

RY-TencentIM 是 IM SDK 主核心类也是 IM SDK 的入口类,负责 IM SDK 的初始化、登录、消息收发,建群退群等功能。调用 init 接口即可完成初始化:

Im.init({
  sdkAppId: 140xxxx97,
  docPath: plus.io.convertLocalFileSystemURL('_doc')
}, ret => {
  console.log(ret);
});

Im.setSDKListener({}, (ret) => {
  if (ret.hasOwnProperty('eventType')) {
    if ('onConnecting' == ret.eventType) {

    }

    if ('onConnectSuccess' == ret.eventType) {

    }

    if ('onConnectFailed' == ret.eventType) {

    }
  }
});

初始化接口包含一个必填参数sdkAppId。

sdkAppId

sdkAppId 即应用 Id,它是腾讯云 IM 服务用于区分客户账号的唯一标识。每一个独立的 App 都建议申请一个新的 sdkAppId,不同 sdkAppId 之间的消息天然隔离,不能互通。 您可以在 即时通信 IM 控制台 查看所有的 sdkAppId,单击【添加新应用】即可创建新的 sdkAppId。

sdkAppId

日志级别

参数logLevel用于对 SDK 进行初始化配置,其中较常用的是对日志级别的设置,即 logLevel 参数,日志级别如下表所示:

日志级别 LOG 输出量
0 不输出任何 log
1 输出 DEBUG,INFO,WARNING,ERROR 级别的 log
2 输出 INFO,WARNING,ERROR 级别的 log
3 输出 WARNING,ERROR 级别的 log
4 输出 ERROR 级别的 log
  • IM SDK 的日志默认存储于 /Library/Caches/ 目录下。
  • 从 V 4.7.1 开始,IM SDK 的日志开始采用微信团队的 xlog 模块进行输出,xlog 日志默认是压缩的,需要使用 python 脚本进行解压。
    • 获取解压脚本:若使用 Python 2.7,则单击 Decode Log 27 获取解压脚本;若使用 Python 3.0,则单击 Decode Log 30 获取解压脚本。
    • 在 Windows 或者 Mac 控制台输入如下命令即可对 log 文件进行解压,解压后的文件以 xlog.log 结尾,可以直接使用文本编辑器打开。
python decode_mars_nocrypt_log_file.py imsdk_yyyyMMdd.xlog

事件监听器

setSDKListener提供了网络状态以及用户信息变更的监听:

事件回调 事件描述 推荐操作
onConnecting 正在连接到腾讯云服务器 适合在 UI 上展示“正在连接”状态
onConnectSuccess 已经成功连接到腾讯云服务器 -
onConnectFailed 连接腾讯云服务器失败 可以提示用户当前网络连接不可用
onKickedOffline 当前用户被踢下线 此时可以 UI 提示用户“您已经在其他端登录了当前账号,是否重新登录?”
onUserSigExpired 登录票据已经过期 请使用新签发的 UserSig 进行登录
onSelfInfoUpdated 当前用户的资料发生了更新 可以在 UI 上更新自己的头像和昵称

注意:

若收到 onUserSigExpired 回调,说明您登录用的 UserSig 票据已经过期,请更新后重新登录。如果继续使用过期的 UserSig,会导致 SDK 登录死循环。

登录

只有在IM登录成功后,才能使用 IM SDK 的各项能力。

登录时机

以下场景需调用登录:

  • App 启动后首次使用 IM SDK 的能力时。
  • onUserSigExpired 回调时,即登录票据已过期时,需要使用新的 UserSig 进行登录。
  • onKickOffline 回调时,即当前用户被踢下线时,可以通过 UI 提示用户“您已经在其他端登录了当前账号,是否重新登录?” 如果用户选择“是”,就可以进行重新登录。

以下场景无需调用登录:

  • 用户的网络断开并重新连接后,不需要调用 login 函数,IM会自动上线。
  • 当一个登录过程在进行时,不需要进行重复登录。
多端登录

同样类型的两台手机不能同时登录一个帐号,例如两台苹果手机不能同时登录一个帐号。但是一台安卓手机和一台苹果手机会被认为是两端,可以同时登录。多端登录相关配置请参考 登录设置。

登出

登出比较简单,使用 logout 函数即可。

消息收发

消息分类

腾讯云 IM 消息按照消息的发送目标可以分为:“单聊消息”(又称 “C2C 消息”)和“群聊消息” 两种

消息分类 API关键词 详细解释
单聊消息 C2CMessage 又称 C2C 消息,在发送时需要指定消息接收者的 UserID,只有接受者可以收到该消息。
群聊消息 GroupMessage 在发送时需要指定目标群组的 groupID,该群中的所有用户均能收到消息。

按照消息承载的内容可以分为:“文本消息”、“自定义(信令)消息”,“图片消息”、“视频消息”、“语音消息”、“文件消息”、“位置消息”、“群 Tips 消息”等几种类型。

消息分类 API关键词 详细解释
文本消息 TextElem 即普通的文字消息,该类消息会经过腾讯云 IM 的敏感词过滤。
自定义消息 CustomElem 即一段二进制 buffer,通常用于传输您应用中的自定义信令,内容不会经过敏感词过滤。
图片消息 ImageElem SDK 会在发送原始图片的同时,自动生成两种不同尺寸的缩略图,三张图分别被称为原图、大图、微缩图。
视频消息 VideoElem 一条视频消息包含一个视频文件和一张配套的缩略图。
语音消息 SoundElem 支持语音是否播放红点展示。
文件消息 FileElem 文件消息最大支持100MB
位置消息 LocationElem 地理位置消息由位置描述、经度(longitude )和维度(latitude)三个字段组成。
群 Tips 消息 GroupTipsElem 群 Tips 消息常被用于承载群中的系统性通知消息,例如有成员进出群组,群的描述信息被修改,群成员的资料发生变化等。

收发简单消息

提供了一组简单的消息收发接口,虽只能用于文本消息和自定义(信令)消息的收发,但使用方法特别简单,只需要几分钟即可完成对接。

发送文本和信令消息(简化接口)

调用 sendC2CTextMessage或者sendGroupTextMessage可以发送文本消息,其中文本消息会经过即时通信 IM 的敏感词过滤,包含的敏感词消息在发送时会报80001错误码。

调用 sendC2CCustomMessage 或者 sendGroupCustomMessage 可以发送 C2C 自定义(信令)消息,自定义消息本质是一段二进制 buffer,通常用于传输您应用中的自定义信令,内容不会经过敏感词过滤。

接收文本和信令消息(简化接口)

通过setSimpleMsgListener 可以监听简单的文本和信令消息,复杂的图片、视频、语音消息则需要通过中定义的setAdvancedMsgListener实现。

注意: setSimpleMsgListenersetAdvancedMsgListener 请勿混用,以免产生逻辑 BUG。

经典示例:直播群中收发弹幕消息

直播场景下,在直播群中收发弹幕消息是非常普遍的交互方式,其实现方式非常简单,通过简单消息接口即可满足:

  1. 主播调用 createGroup 创建一个直播群(AVChatRoom),并在“正在直播”的房间列表中记录群组 ID。
  2. 观众选择自己喜欢的主播,并调用 joinGroup 加入该主播创建的直播群。
  3. 消息的发送方可以通过 sendGroupTextMessage 群发弹幕文本消息。
  4. 消息的接收方可以通过 setSimpleMsgListener 注册简单消息监听器,并通过监听回调函数 onRecvGroupTextMessage 获取文本消息。

为直播间增加“点赞飘心”的功能,“点赞飘心”属于一条指令,操作步骤如下:

  1. 定义一个的自定义消息类型,例如一个 JSON 字符串:{ "command": "favor", "value": 101 }。
  2. 通过 sendGroupCustomMessage 接口进行消息的发送,并通过 onRecvGroupCustomMessage 进行接收。

收发富媒体消息

图片、视频、语音、文件、地理位置等类型的消息称为“富媒体消息”。相比于简单消息,富媒体消息的收发相对复杂:

  • 在发送时,富媒体消息需要先用对应的 createXXXMessage 函数创建一个消息对象,再调用对应的 send 接口发送。
  • 在接收时,富媒体消息需要先判断字段 elemType,elemType代表对应的消息类型。
发送富媒体消息

本文以图片消息为例,介绍发送一条富媒体消息的过程:

  1. 发送方调用 createImageMessage 创建一条图片消息。
  2. 发送方调用 sendMessage 接口将刚才创建的消息对象发送出去。
接收富媒体消息
  1. 接收方调用setAdvancedMsgListener接口设置高级消息监听。
  2. 接收方通过监听回调 [onRecvNewMessage](https://uniapp.helpyougo.com/web/userpage/documents?id=19 &menuid=onRecvNewMessage01) 获取图片消息。
  3. 接收方解析消息中的 elemType 属性,获取消息内部 Elem 中的具体内容。
经典示例:收发图片

发送方创建一条图片消息并发送:

var self = this;
// 选择图片
uni.chooseImage({
  success: (res) => {
    var imgPath = res.tempFilePaths[0];
    self.imagePath = plus.io.convertLocalFileSystemURL(imgPath);
  }
});
// 创建图片消息
Im.createImageMessage({
  img: self.imagePath
}, ret => {
  if (ret.hasOwnProperty('status')) {
    self.messageKey = ret.messageKey;
  }
});
// 发送图片消息
Im.sendMessage({
  receiver: self.remoteUserId,
  priority: self.priority,
  messageKey: self.messageKey
}, ret => {
});

接收方识别一条图片消息并将解析中包含的原图、大图和微缩图:

if (ret.eventType == 'onRecvNewMessage') {
  ...
  var imageList = elem.imageList;
  ...
}

收发群 @ 消息

群 @ 消息,发送方可以在输入栏监听 @ 字符输入,调用到群成员选择界面,选择完成后以 “@A @B @C......” 形式显示在输入框,并可以继续编辑消息内容,完成消息发送;接收方会在会话界面的群聊天列表,重点显示 “有人@我” 或者“@所有人” 标识,提醒用户有人在群里 @ 自己了。

说明:

目前仅支持文本 @ 消息。

at

发送群 @ 消息
  1. 发送方监听聊天界面的文本输入框,启动群成员选择界面,选择完成后回传选择群成员的Id和昵称信息,Id用来构建消息对象,昵称用来在文本框显示。
  2. 发送方调用createTextAtMessage 创建一条 @ 文本消息。
  3. 发送方调用 sendMessage 接口将刚才创建的 @ 消息对象发送出去。
接收群 @ 消息
  1. 在加载和更新会话处,需要调用 setConversationListener 的 groupAtInfolist 接口获取会话的 @ 数据列表 。
  2. 通过列表中 groupAtInfo 对象的 atType 接口获取 @ 数据类型,并更新到当前会话的 @ 信息。
经典示例:收发群 @ 消息
  • 发送群 @ 消息: 发送方创建一条群 @ 消息并发送。
// 创建@消息
Im.createTextAtMessage({
  text: self.textMsg,
  userIdList: self.userIdList
}, ret => {
  if (ret.hasOwnProperty('status')) {
    self.messageKey = ret.messageKey;
  }
});
// 发送@消息
Im.sendMessage({
  receiver: self.remoteUserId,
  priority: self.priority,
  messageKey: self.messageKey
}, ret => {
});
  • 接收群 @ 消息: 在加载和更新会话处,返回结果里conversation获取群 @ 数据列表,解析当前的 @ 类型,根据 @ 类型显示对应的提示文本。
var atMe = false;
var atAll = false;
switch (atGroupInfo.atType) {
  case 1:
    atMe = true;
  break;
  case 2:
    atAll = true;
  break;
  case 3:
    atMe = true;
    atAll = true;
  break;
}

收发合并转发消息(仅精简版 5.2.210 以上版本支持)

要实现类似于微信的合并转发功能,首先需要根据原始消息列表创建一条合并消息,然后把合并消息发送到对端,对端收到合并消息后再解析出原始消息列表,合并消息的展示还需要标题和摘要信息,如下图所示:

transfer

  • 发送合并转发消息:

通常我们在收到一条合并消息的时候,会在聊天界面这样显示:

vinson 和 lynx 的聊天记录 title (标题)
vinson:新版本 SDK 计划什么时候上线呢? abstract1 (摘要信息1)
lynx:计划下周一,具体时间要看下这两天的系统测试情况.. abstract2 (摘要信息2)
vinson:好的 abstract3 (摘要信息3)

聊天界面只会显示合并消息的标题和摘要信息,只有用户点击合并消息的时候才会展示合并消息列表,我们在创建一条合并消息的时候不仅要设置合并消息列表,还要设置标题和摘要信息,实现流程如下: 1、调用 createMergerMessage 接口创建一条合并消息。 2、调用 sendMessage 接口发送合并消息。

  • 接收合并转发消息:

当我们收到一条合并消息 message,可以先通过合并消息元素 elem 获取 title 和 abstractList UI 展示,当用户点击合并消息的时候再调用 downloadMergerMessage 接口下载合并消息列表 UI 展示。

经典示例:收发合并转发消息
  • 发送合并转发消息: 发送方创建一条合并消息并发送。
// 需要被转发的消息列表,消息列表里可以包含合并消息,不能包含群 Tips 消息
var msgKeyList = ['msgKey1', 'msgKey2', ...];
// 合并消息标题
var title = 'vinson 和 lynx 的聊天记录';
// 合并消息摘要列表
var abstractList = ['abstract1', 'abstract2', ...];
// 合并消息兼容文本,低版本 SDK 如果不支持合并消息,默认会收到一条文本消息,文本消息的内容为 compatibleText
var compatibleText = '请升级最新版本查看合并消息';

Im.createMergerMessage({
  msgKeyList: msgKeyList, 
  title: title, 
  abstractList: abstractList, 
  compatibleText: compatibleText
}, ret => {
  console.log(ret);
});
  • 接收合并转发消息: 接收方收到一条合并消息并解析:
Im.setAdvancedMsgListener({}, ret => {
  if (ret.hasOwnProperty('eventType')) {
    if('onRecvNewMessage' == ret.eventType) {
      if (ret.elemType == 10) {
        ...
      }
    }
  }
});

发送不计入未读数的消息(仅精简版 5.3.425 及以上版本支持)

正常情况下,无论是发送 C2C 单聊消息还是发送 Group 群消息,都会计入未读消息数(通过会话对象 conversation 的 unreadCount 接口,可以拿到一个会话的未读消息数)。当您希望发送一些不计入未读计数的消息时,比如提示类或者控制类的消息,可以按照下面的方式来发送:

Im.setMessage({
  messageKey: 'fdaax123fdasd',
  // 设置不计入未读消息总数的标记
  isExcludedFromUnreadCount: true
}, ret => {
  console.log(ret);
});

// 发送进度
Im.setSendMessageListener({}, ret => {
  console.log(ret);
});

Im.sendMessage({
  messageKey: 'fdaax123fdasd', 
  receiver: 'userA', 
  priority: 0, 
  onLineUserOnly: YES
}, ret => {
  console.log(ret);
})

发送不计入未读数的消息(仅精简本 5.3.425 以上版本支持)

正常情况下,无论是发送 C2C 单聊消息还是发送 Group 群消息,都会计入未读消息数(通过会话对象 V2TIMConversation 的 unreadCount 参数,可以拿到一个会话的未读消息数)。当您希望发送一些不计入未读计数的消息时,比如提示类或者控制类的消息,可以按照下面的方式来发送:

Im.setMessage({
  messageKey: 'fdaax123fdasd',
  // 设置不计入会话 lastMsg 的标记
  isExcludedFromLastMessage: true
}, ret => {
  console.log(ret);
});

// 发送进度
Im.setSendMessageListener({}, ret => {
  console.log(ret);
});

// 发送消息
Im.sendMessage({
  messageKey: 'fdaax123fdasd', 
  receiver: 'userA', 
  priority: 0, 
  onLineUserOnly: YES
}, ret => {
  console.log(ret);
})

设置 APNS 离线推送(offlinePushInfo)

当接收方的 App 被 kill 或者被切到后台时,IM SDK 无法通过正常的网络连接收取新消息。如需实现在此场景下接收方仍能感知到新消息,需要使用苹果提供的 APNs 服务,即“苹果离线推送”,更多详细请参见 开启 iOS 离线推送

设置 APNS 离线推送的标题和声音

您可以在发送消息时,通过 sendMessage 接口中的 offlinePushInfo 字段,设置 APNS 离线推送的标题和声音。

Im.sendMessage({
  messageKey: 'fdafsxxxafdas', 
  groupId: 'groupA', 
  priority: 0, 
  onlineUserOnly: false, 
  offlinePushInfo: {
    title: '自定义推送 Title 展示',
    iOSSound = '01.caf'
  }
}, ret => {
  console.log(ret);
});
点击推送消息跳转到对应的聊天窗口

如需实现该功能,发送消息时需设置离线推送对象 offlinePushInfo 的扩展字段 ext,收到消息的用户打开 App 时可以通过 didReceiveRemoteNotification 系统回调获取到扩展字段 ext,再根据 ext 内容跳转到对应的聊天界面。

本文以 “denny 给 vinson 发送消息” 的场景为例。

  • 发送方:denny 需在发送消息时设置推送扩展字段 ext:
Im.sendMessage({
  messageKey: 'fdafsxxxafdas', 
  groupId: 'groupA', 
  priority: 0, 
  onlineUserOnly: false, 
  offlinePushInfo: {
    title: '文本消息',
    ext: 'jump to denny'
  }
}, ret => {
  console.log(ret);
});
  • 接收方:vinson 的 App 虽然不在线,但可以接收到 APNS 离线推送,当 vinson 点击推送消息时会启动 App

设置消息为只能在线接收(onlineUserOnly)

某些场景下,您可能希望发出去的消息只被在线用户接收,即当接收者不在线时就不会感知到该消息。您只需在 sendMessage 时,将参数 onlineUserOnly 设置为 true ,此时发送出去的消息与普通消息相比,会有如下差异点:

  • 不支持离线存储,即如果接收方不在线就无法收到。
  • 不支持多端漫游,即如果接收方在一台终端设备上一旦接收过该消息,无论是否已读,都不会在另一台终端上再次收到。
  • 不支持本地存储,即本地的云端的历史消息中均无法找回。
经典示例:实现“对方正在输入”功能

在 C2C 单聊场景下,您可以通过 sendMessage 接口发送 "自己正在输入" 的提示性消息,接收方收到该消息时可以在 UI 界面展示 "对方正在输入"

// 给 userA 发送 "自己正在输入" 的提示消息
var customStr = '{"command": "textInput"}';
Im.createCustomMessage({
  customMsg: customStr
}, ret => {
  Im.sendMesasge({
    receiver: 'userA', 
    mesageKey: ret.messageKey
  }, ret => {
    console.log(ret);
  });
});

设置接收消息免打扰(仅精简本 5.3.425 以上版本支持)

SDK 支持三种类型的消息接收选项:

  • 0:在线时正常接收消息,离线时接收离线推送通知
  • 1:在线和离线都不接收消息
  • 2:在线时正常接收消息,离线时不接收离线推送通知

您可以调用 setC2CReceiveMessageOpt 接口设置单聊消息免打扰,调用 setGroupReceiveMessageOpt 接口设置群聊消息免打扰。

撤回消息

发送方通过 revokeMessage 接口可以撤回一条已经发送成功的消息。默认情况下,发送者只能撤回2分钟以内的消息,您可以按需更改消息撤回时间限制,在腾讯云IM控制台下:

消息撤回设置

  • 在【登录与消息】页面,单击【消息撤回设置】右侧的【编辑】。
  • 在弹出的【消息撤回设置】对话框中,设置消息可撤回时长。
  • 单击【确定】保存配置。

消息的撤回同时需要接收方 UI 代码的配合:当发送方撤回一条消息后,接收方会收到消息撤回通知 onRecvMessageRevoked,通知中包含被撤回消息的 msgId,您可以根据 msgId 判断 UI 层是哪一条消息被撤回了,然后把对应的消息气泡切换成 "消息已被撤回" 状态。

发送方撤回一条消息
Im.revokeMessage({
  msgId: 'ffkdsaxxxxlkerd',
  userId: 'test002',
}, ret => {
  console.log(ret);
});
接收方感知消息被撤回
  1. 调用 setAdvancedMsgListener 设置高级消息监听。
  2. 通过 onRecvMessageRevoked 接收消息撤回通知。
Im.setAdvancedMsgListener({}, ret => {
  if (ret.hasOwnProperty('eventType')) {
    if ('onRecvMessageRevoked' == ret.eventType) {
      // msgList 为当前聊天界面的消息列表
      msgList.foreach(msg, index) {
        if (msg.msgId == ret.msgId) {
          //msg 即为被撤回的消息,您需要修改 UI 上相应的消息气泡的状态
        }
      }
    }
  }
})

给消息增加已读回执

在 C2C 单聊场景下,当接收方通过 markC2CMessageAsRead 接口将来自某人的消息标记为已读时,消息的发送方将会收到“已读回执”,表示“xxx 已经读过我的消息了”。

注意: 目前仅 C2C 单聊消息支持已读回执,群聊场景暂不支持。虽然群聊消息也有对应的 markGroupMessageAsRead 接口,但群消息的发送者目前无法收到已读回执。

接收方标记消息已读
//将来自 haven 的消息均标记为已读
Im.markC2CMessageAsRead({
  userId: 'haven',
}, ret => {
  console.log(ret);
});
发送方感知消息已读

消息已读回执的事件通知位于高级消息监听器 setAdvancedMsgListener 中,如需支持感知消息已读,需要先通过 setAdvancedMsgListener 设置监听器,然后通过 setAdvancedMsgListener#onRecvC2CReadReceipt 回调即可感知接收方的已读确认。

Im.setAdvancedMsgListener({}, ret => {
  if (ret.hasOwnProperty('eventType')) {
    if ('onRecvC2CReadReceipt' == ret.eventType) {
      // 发送方可能一次性会收到多个已读回执,因此这里采用数组的回调形式
      ret.receiptList.foreach((receipt, index) {
        // 消息接收者 receiver
        var userId = receipt.userId;
        // 已读回执时间,聊天窗口中时间戳小于或等于 timestamp 的消息都可以被认为已读
        var timestamp = receipt.timestamp;
      });
    }
  }
});

查看历史消息

您可以调用 getC2CHistoryMessageList 获取单聊历史消息,调用 getGroupHistoryMessageList 获取群聊历史消息。如果当前设备网络连接正常,SDK 会默认从服务器拉取历史消息;如果没有网络连接,SDK 会直接从本地数据库中读取历史消息。

分页拉取历史消息

SDK 支持分页拉取历史消息,一次分页拉取的消息数量不宜太大,否则会影响拉取速度,建议一次最多拉取20条。 本文以分页拉取名为 groupA 的群的历史消息,每次分页拉取20条为例,示例代码如下:

self = this;
// 第一次拉取 lastMsg 传 '',表示从最新的消息开始拉取 20 条消息
Im.getGroupHistoryMessageList({
  groupId: 'groupA',
  count: 20,
  msgId: ''
}, ret => {
  if (ret.hasOwnProperty('status')) {
    var messageList = ret.messageList;
    // 分页拉取返回的消息默认是按照从新到旧排列
    if (msgs.count > 0) {
      // 获取下一次分页拉取的起始消息
      var lastMsg = messageList[messageList.length - 1];
      // 拉取剩下的20条消息
      Im.getGroupHistoryMessageList({
        groupId: 'groupA',
        count: 20,
        msgId: lastMsg.msgId
      }, ret => {
        // 拉取消息结束
      });
    }
  }

现实场景中的分页拉取,通常由用户的滑动操作触发的,用户每下拉一次消息列表就触发一次分页拉取。但原理上跟上述示例代码类似,都是以 msgId 作为分页的标记,以 count 控制每次拉取的消息条数。

历史消息的注意事项
  • 历史消息存储时长如下: 体验版:免费存储7天,不支持延长 专业版:免费存储7天,支持延长 旗舰版:免费存储30天,支持延长 延长历史消息存储时长是增值服务,您可以登录 即时通信 IM 控制台 修改相关配置。
  • 只有会议群(Meeting)(对应老版本的 ChatRoom 群)才支持拉取到用户入群之前的历史消息。
  • 直播群(AVChatRoom)中的消息均不支持本地存储和多终端漫游,因此对直播群调用 getGroupHistoryMessageList 接口是无效的。

删除消息

对于历史消息,您可以调用 deleteMessages 接口删除历史消息,消息删除后,无法再恢复。

设置消息权限

只允许好友间收发消息

SDK 默认不限制非好友之间收发消息。如果您希望仅允许好友之间发送单聊消息,您可以在 即时通信 IM 控制台 >【功能配置】>【登录与消息】>【好友关系检查】中开启"发送单聊消息检查关系链"。开启后,用户只能给好友发送消息,当用户给非好友发消息时,SDK 会报20009错误码。

不接收某人的消息

不接收某人消息可以选择拉黑某人或则设置某人消息免打扰,拉黑某人后再也收不到对方的任何消息,设置消息免打扰后可以更改消息 免打扰状态。

拉黑某人:

调用 addToBlackList 接口把该用户加入黑名单,即拉黑该用户,当消息发送者被拉黑后,发送者默认不会感知到“被拉黑”的状态,即发送消息后仍展示发送成功(实际上此时接收方不会收到消息)。如果需要被拉黑的发送者收到消息发送失败的提示,请在 即时通信 IM 控制台 >【功能配置】>【登录与消息】>【黑名单检查】中关闭"发送消息后展示发送成功",关闭后,被拉黑的发送者在发送消息时,SDK 会报20007错误码。

设置某人消息免打扰(仅精简版 5.3.425 以上版本支持):

调用 setC2CReceiveMessageOpt 接口,设置消息接收选项为 1 状态。

不接收某个群组的消息

精简版 5.3.425 以上版本,请调用 setGroupReceiveMessageOpt 接口,设置消息接收选项为 1 状态。

敏感词过滤

SDK 发送的文本消息默认会经过即时通信 IM 的敏感词过滤,如果发送者在发送的文本消息中包含敏感词,SDK 会报 80001 错误码。

敏感词

常见问题

1. 为什么会收到重复的消息?
  • 请检查 setSimpleMsgListenersetAdvancedMsgListener 是否混用。如果混用,当收到文本消息或自定义消息时,两个监听都会回调,会导致收到重复消息。
  • 请检查同一个监听对象是否重复 add,如果监听对象不再使用,请主动调用对应的 delSimpleMsgListener 或 delAdvancedMsgListener 接口移除多余的监听器。
2. App 卸载重装后已读回执为什么失效了?

在单聊场景下,接收方如果调用 markC2CMessageAsRead 设置消息已读,发送方收到的已读回执里面包含了对方已读的时间戳 timestamp,SDK 内部会根据 timestamp 判断消息对方是否已读, timestamp 目前只在本地保存,程序卸载重装后会丢失。

3. 如何发送多个 Elem 的消息?

如果您的消息需要多个 elem,可以在创建 Message 对象后,通过 Message 对象的 Elem 成员调用 appendElem 方法添加下一个 elem 成员。

以文本消息 + 自定义消息为例:

Im.appendElem({
  messageKey: 'xxafdsa2iwlxaxxx',
  elemKey: 'xxxxxfdsjalflwe'
}, ret => {
  console.log(ret);
});
4. 如何解析多个 Elem 的消息?

通过返回的 message 对象正常解析出第一个 elem 属性。 如果有多个elem,其他属性会在 elemList 属性列表中,如果不存在,会返回空数组 []。

5. 各种不同类型的消息应该如何解析?

解析消息相对复杂,我们自动解析了各种类型消息解析的 示例代码,消息类型为消息返回值里的elemType字段。

会话管理

展示会话列表

用户在登录 App 后,可以像微信那样展示最近会话列表。整个过程分为拉取会话列表、处理更新通知和更新 UI 内容(包括未读计数),本文主要介绍这些步骤的详细细节。

会话列表
拉取会话列表

用户在登录后调用 getConversationList 拉取本地会话列表做 UI 展示,会话列表是一个 conversation 对象的列表,每一个对象都代表一个会话。

由于本地会话可能较多(例如超过500个),一次性全部加载完毕可能会耗时很久,导致界面展示比较慢。为了提升用户体验,getConversationList() 接口支持分页拉取能力:

  1. 首次调用 getConversationList() 接口时,可以指定其参数 nextSeq 为0 ,表示从头开始拉取会话列表,并指定 count 为50,表示一次拉取50个会话对象。
  2. 按照从新到旧的顺序拉取会话列表,当首次拉取会话列表成功后,getConversationList 的回调结果中会包含下次分页拉取的 nextSeq 字段以及会话拉取是否完成的 isFinish 字段:
    • 如果 isFinished 返回 true,表示所有会话已经拉取完成。
    • 如果 isFinished 返回 false ,表示还有更多的会话可以拉取。此时并不意味着要立刻开始拉取“下一页”的会话列表。在常见的通信软件中,分页拉取通常由用户的滑动操作触发的,用户每下拉一次会话列表就触发一次分页拉取。
  3. 当用户继续下拉会话列表时,如果还有更多的会话可以拉取,可以继续调用 getConversationList 接口,并传入新一轮的 nextSeq 和 count 参数(数值来自上一次拉取返回的 ret 对象)。
  4. 重复执行 步骤3 直至 isFinished 返回 true。
显示会话列表
获取到 conversation 对象后,即可在 UI 上展示,conversation 有如下关键字段常被用于构造会话列表: 字段名称 含义
showName 会话名称
faceUrl 会话头像
unreadCount 用于显示未读计数,表示有多少条未读消息
recvOpt 会话接收选项
lastMessage 最后一条消息,用于显示会话的消息摘要
groupAtInfoList 会话 @ 信息,用于展示 "有人 @ 我"、"@ ALL" 等信息
isPinned 会话是否置顶,仅精简版本支持
更新会话列表

IM SDK 会在登录成功后、用户上线后、以及断线重连后,自动更新会话列表。更新过程如下:

  • 当有会话更新时,例如新收到一条消息,会通过 setConversationListener 中的 onConversationChanged 事件通知您。
  • 当有会话新增时,会通过 setConversationListener 中的 onNewConversation 事件通知您。

注意:

为保证会话列表顺序符合最后一条消息的排序原则,您需要根据 lastMessage 中的 timestamp 对数据源重新排序。

示例代码

示例代码将介绍如何拉取、展示和更新会话列表:

// 1. 设置会话监听
Im.setConversationListener({}, ret => {
  if (ret.hasOwnProperty('eventType')) {
    if ('onNewConversation' == ret.eventType) {
      // 收到会话新增的回调
    }
    if ('onConversationChanged' == ret.eventType) {
      // 收到会话更新的回调
    }
  }
  console.log(ret);
});

// 2. 登录
Im.login({
  userId: 'test001'
}, ret => {
  // 3. 拉取50个本地会话做UI展示, nextSeq第一次拉取传0
  Im.getConversationList({
    nextSeq: 0,
    count: 50
  }, ret => {
    console.log(ret);
    // 拉取成功,更新UI显示
    // 4. 如果会话还没拉取完,按需继续拉取,nextSeq 传上次拉取返回的 nextSeq
    if (!ret.isFinished) {
      Im.getConversationList({
        nextSeq: ret.nextSeq, 
        count: 50
      }, ret => {
        // 拉取成功,更新 UI 会话列表
      });
    }
  });
});

获取所有会话的未读消息总数(仅精简版 5.3.425 以上版本支持)

调用 getTotalUnreadMessageCount 接口可以获取所有会话的未读消息总数。您不用再遍历会话列表,把单个会话的未读数相加,才能得到未读总数。当会话的未读总数发生变更的时候,SDK 会主动向您的 App 回调 onTotalUnreadMessageCountChanged,把最新的未读总数通知给您。

置顶会话(仅精简版 5.3.425 以上版本支持)

会话置顶指的是把特定的好友或者群会话固定在会话列表的最前面,新版本 SDK 增加了主动设置或者取消会话置顶的接口 pinConversation ,同时支持漫游和多端同步。 会话对象 conversation 新增了 isPinned 接口,用于判断会话的置顶状态。当会话的置顶状态发生变更的时候,SDK 会向您的 App 回调 onConversationChanged

删除会话

调用 deleteConversation 接口可以删除某个会话,会话删除不支持多端同步,删除会话时默认删除本地和服务器历史消息,且无法恢复。

草稿箱

在发送消息时,可能会遇到消息尚未编辑完就要切换至其它聊天窗口的情况,这些未编辑完的消息可通过 setConversationDraft 接口保存,以便于回到聊天界面后调用 draftText 继续编辑内容

注意:

  • 草稿仅支持文本内容。
  • 草稿仅在本地保存,不会存储到服务器,因此不能多端同步,程序卸载重装会失效。

常见问题

1. 最近会话列表的保存数量上限是多少?

本地存储的会话列表没有数量上限,云端存储的会话列表最大数量为100。 如果一个会话长时间没有信息变更,该会话在云端最多保存7天,如需放宽限制,请联系我们。

2. 为什么换了一个手机登录相同帐号后拉取的会话列表不一致?

本地存储的会话和云端存储的会话并不总是一致的,如果用户不主动调用 deleteConversation 接口删除本地的会话,该会话就会一直存在。而云端存储的会话最大只会保存100条,且对于长时间没有信息变更的会话,云端最多保存7天,所以不同的终端本地显示的会话可能会不一样。

3. 为什么会拉取到重复的会话?

调用 getConversationList 接口拉取的会话可能已经通过 onNewConversation 回调接口添加到了 UI 会话列表的数据源中,因此为了避免重复添加同一个会话,您需要在 UI 会话列表数据源中根据 conversationId 找到相同的会话并做替换。

4. IM SDK 支持会话置顶吗?

IM SDK 从5.3.425版本开始支持会话置顶功能并可以同步到云端。

群组管理

群类型介绍

即时通信 IM 群组分为以下类型:

  • 好友工作群(Work):类似普通微信群,创建后仅支持已在群内的好友邀请加群,且无需被邀请方同意或群主审批。
  • 陌生人社交群(Public):类似 QQ 群,创建后群主可以指定群管理员,用户搜索群 ID 发起加群申请后,需要群主或管理员审批通过才能入群。
  • 临时会议群(Meeting):创建后可以随意进出,且支持查看入群前消息;适合用于音视频会议场景、在线教育场景等与实时音视频产品结合的场景。
  • 直播群(AVChatRoom):创建后可以随意进出,没有群成员数量上限,但不支持历史消息存储;适合与直播产品结合,用于弹幕聊天场景。

每种群类型的功能特性及限制如下表所示:

功能项 好友工作群(Work) 陌生人社交群(Public) 临时会议群(Meeting) 直播群(AVChatRoom)
可用群成员角色 群主、普通成员 群主、管理员、普通成员 群主、管理员、普通成员 群主、普通成员
是否支持申请加群 不支持 支持,但需要群主或管理员审批 支持,且无需审批 支持,且无需审批
是否支持成员邀请他人加群 支持 不支持 不支持 不支持
是否支持群主退群 支持 不支持 不支持 不支持
群组资料修改权限 任意群成员均可修改 群主和管理员 群主和管理员 群主
“踢人”权限 群主可踢人 群主和管理员可踢人,但管理员仅支持踢普通群成员 群主和管理员可踢人,但管理员仅支持踢普通群成员 不支持踢人,可用“禁言”功能达到类似效果
“禁言”权限 不支持禁言 群主和管理员可禁言, 但管理员仅支持禁言普通群成员 群主和管理员可禁言, 但管理员仅支持禁言普通群成员 群主可禁言
是否支持未读消息计数 支持 支持 不支持 不支持
是否支持查看入群前消息记录 不支持 不支持 支持 不支持
是否支持云端历史消息存储 体验版:7天
专业版 :默认7天,最高支持 增值 延长至360天
旗舰版 :默认30天,最高支持 增值 延长至360天
体验版:7天
专业版 :默认7天,最高支持 增值 延长至360天
旗舰版 :默认30天,最高支持 增值 延长至360天
体验版:7天
专业版 :默认7天,最高支持 增值 延长至360天
旗舰版 :默认30天,最高支持 增值 延长至360天
不支持
群组数量 体验版:最多同时存在100个,已解散的群组不计数
专业版或旗舰版:无上限
体验版:最多同时存在100个,已解散的群组不计数
专业版或旗舰版:无上限
体验版:最多同时存在100个,已解散的群组不计数
专业版或旗舰版:无上限
体验版:最多同时存在10个,已解散的群组不计数
专业版:最多同时存在50个,已解散的群组不计数;支持 增值 扩展直播群创建数至无上限
旗舰版:无上限
群成员数量 体验版:20人/群
专业版 :默认为200人/群,最高支持 增值 扩展至2000人/群
旗舰版 :默认为2000人/群,最高支持 增值 扩展至6000人/群
体验版:20人/群
专业版 :默认为200人/群,最高支持 增值 扩展至2000人/群
旗舰版 :默认为2000人/群,最高支持 增值 扩展至6000人/群
体验版:20人/群
专业版 :默认为200人/群,最高支持 增值 扩展至2000人/群
旗舰版 :默认为2000人/群,最高支持 增值 扩展至6000人/群
群成员人数无上限

说明:

专业版或旗舰版 sdkAppId 下,所有群类型日净增群组数上限为1万个。免费峰值群组数为10万个/月,超出免费量将产生 套餐外超量费用。

群组管理

创建群组
简化版接口

调用 createGroup 接口,并指定需要的 groupType、groupId 和 groupName 参数,即可简单创建一个群组。

高级版接口

如果您想在创建群组的同时初始化群的信息,例如群简介、群头像、以及最初的几个群成员等,可以调用createGroupWithMemberList接口实现。

var self = this;
Im.createGroupWithMemberList({
  groupInfo: {
    groupId: self.groupId, 
    groupType: self.groupType,
    groupName: self.groupName,
    notification: self.notification
  },
  memberList: [
    {
      userId: self.remoteUserId,
      role: 0
    }
  ],
  introduction: self.introduction,
    faceUrl: self.faceUrl
}, ret => {
  uni.showToast({
    title: JSON.stringify(ret),
    icon: "none"
  });
});
  • 参数 groupType 是字符串类型,可以选择 “Work”、“Public”、“Meeting” 和 “AVChatRoom” 中的任何一个,各种不同类型之间的差异请参见 群类型介绍。
  • 参数 groupID 用于指定群组 ID,它用于唯一标识一个群,请勿在同一个 SDKAppID 下创建相同 groupID 的群。如果您指定 groupID 为 nil,系统会为您默认分配一个群 ID。
  • 参数 groupName 用于指定群的描述信息,最长支持30个字节。
加入群组

不同类型的群,加群的方法不同, 下面根据加群流程从简单到复杂进行逐一介绍:

类型 好友工作群(Work) 陌生人社交(Public) 临时会议(Meeting) 直播群(AVChatroom)
加群方法 必须由其他群成员邀请 用户申请,群主或管理员审批 用户可随意加入 用户可随意加入
场景一: 用户可以自由进出群

临时会议群(Meeting)和直播群(AVChatRoom)主要用于满足成员进进出出的交互场景,例如在线会议,秀场直播等。因此,这两种类型群的入群流程最为简单。

用户调用 joinGroup 即可加入该群,加群成功后,全体群成员(包括加群者)都会收到 onMemberEnter 回调。

场景二: 需被邀请才能进入群

好友工作群(Work)类似微信群和企业微信群,适用于工作交流,在交互设计上限制用户主动加入,只能由现有的群成员邀请才能加群。

现有的群成员调用inviteUserToGroup邀请另一个用户入群,全体群成员(包括邀请者自己)会收到setGroupListener#onMemberInvited 回调。

场景三:需要审批才能进入群

陌生人社交群(Public)类似 QQ 中的各种兴趣群和部落区,任何人都可以申请入群,但需要经过群主或管理员审批才能真正入群。陌生人社交群默认需要群主或管理员进行审批才能加群的,但群主或管理员也可以通过 setGroupInfo 接口调整加群选项(groupAddOpt),可以设置为更严格的“禁止任何人加群”,也可以设置为更宽松的“放开审批流程”。

  • 0: 禁止任何人加群。
  • 1: 需要群主或管理员审批才能加入(默认值)。
  • 2: 取消审批流程,任何用户都可以加入。

需要审批才能进入群的流程如下:

审批流程

  1. 申请者提出加群申请

申请者调用 joinGroup申请加群。

  1. 群主或管理员处理加群申请

群主或管理员在收到加群申请的回调 onReceiveJoinApplication 后调用接口 getGroupApplicationList 获取加群申请列表,然后通过 acceptGroupApplication或者refuseGroupApplication来同意或者拒绝某一条加群请求。

  1. 申请者收到处理结果

请求加群被同意或者拒绝后,请求者会收到 V2TIMGroupListener 中的 onApplicationProcessed 回调,其中 isAgreeJoin 为 true 表示同意加群,反之被拒绝。同意加群后,全员(包括请求者)收到 onMemberEnter 回调。

退出群组

调用 quitGroup 可以退出群组,退群者会收到 onQuitFromGroup 回调,群其他成员会收到 onMemberLeave 回调。

注意:

对于陌生人社交群(Public)、临时会议群(Meeting)和直播群(AVChatRoom),群主不可以退群的,群主只能 解散群组。

解散群组

调用 dismissGroup 可以解散群组,全员会收到 onGroupDismissed 回调。

注意:

  • 对于陌生人社交群(Public)、临时会议群(Meeting)和直播群(AVChatRoom),群主随时可以解散群。
  • 工作群(Work)的解散最为严格,即使群主也不能随意解散,只能由您的业务服务器调用 解散群组 REST API 解散。
获取已加入的群组

调用 getJoinedGroupList 可以获取已加入的好友工作群(Work)、陌生人社交群(Public)、临时会议群(Meeting)列表,但直播群(AVChatRoom)不包含在此列表中。

群资料和群设置

获取群资料

调用 getGroupsInfo 可以获取群资料,该接口支持批量获取。您可以一次传入多个 groupId 获取多个群的群资料。

修改群资料

调用 setGroupInfo 可以修改群资料。群资料被修改后,全员会收到 onGroupInfoChanged 回调。

注意:

  • 好友工作群(Work)所有群成员都可以修改群基础资料。
  • 陌生人社交群(Public)、临时会议群(Meeting)只有群主或管理员可以修改群基础资料。
  • 直播群(AVChatRoom)只有群主可以修改群基础资料。

注意:

  • 好友工作群(Work)所有群成员都可以修改群基础资料。
  • 陌生人社交群(Public)、临时会议群(Meeting)只有群主或管理员可以修改群基础资料。
  • 直播群(AVChatRoom)只有群主可以修改群基础资料。
Im.setGroupInfo({
  groupId: 'group001',
  faceUrl: 'http://xxxx.xxx.xxx/xxx.png'
}, ret => {
  console.log(ret);
});
设置群消息的接收选项

任何群成员都可以调用 setReceiveMessageOpt 接口修改群消息接收选项。群消息接收选项包括:

  • 0:在线正常接收消息,离线时会有厂商的离线推送通知。
  • 1:不会接收到群消息。
  • 2:在线正常接收消息,离线不会有推送通知。

根据群消息接收选择可以实现群消息免打扰:

  • 完全不接收群内消息 群消息接收选项设置为 2 后,群内的任何消息都收不到,会话列表也不会更新。

  • 接收群内消息但不提醒,在会话列表界面显示小圆点,而不显示未读数

说明:

此方式需使用未读计数功能,因此仅适用于好友工作群(Work)和陌生人社交群(Public)。

群消息接收选项设置为 1,当群内收到新消息,会话列表需要更新时,可以通过会话中的 getUnreadCount 获取到消息未读数。根据 getRecvOpt 判断获取到的群消息接收选项为 2 时显示小红点而非消息未读数。

群属性(群自定义字段)

设计了全新的群自定义字段,我们称之为 "群属性",其特性如下:

  1. 不再需要控制台配置,客户端可以直接增删改查群属性。
  2. 最多支持16个群属性,每个群属性的大小最大支持4k,所有群属性的大小最大支持16k。
  3. 目前仅支持直播群(AVChatRoom)。
  4. initGroupAttributes、setGroupAttributes、deleteGroupAttributes 接口合并计算, SDK 限制为5秒10次,超过后回调8511错误码;后台限制1秒5次,超过后返回10049错误码。
  5. getGroupAttributes 接口 SDK 限制5秒20次。

基于群属性,我们可以做语聊房的麦位管理,当有人上麦的时候,可以设置一个群属性管理上麦人信息,当有人下麦的时候,可以删除对应群属性,其他成员可以通过获取群属性列表来展示麦位列表。

初始化群属性

调用 initGroupAttributes 接口可以初始化群属性,如果该群之前有群属性,会先清空原来的群属性。

设置群属性

调用 setGroupAttributes 接口可以设置群属性,如果设置的群属性不存在,会自动添加该群属性。

删除群属性

调用 deleteGroupAttributes 接口可以删除指定群属性,如果 keys 字段填 null ,则会清空所有的群属性。

获取群属性

调用 getGroupAttributes 接口可以获取指定群属性,如果 keys 字段填 null ,则会获取所有的群属性。

群属性更新

群属性有任何的更新变化,都会通过 onGroupAttributeChanged 回调出来所有的群属性字段。

群成员管理

获取群成员列表

调用 getGroupMemberList 可以获取某个群的群成员列表,该列表中包含了各个群成员的资料信息,例如用户ID(userId)、群名片(nameCard)、头像(faceUrl)、昵称(nickName)、进群时间(joinTime)等信息。 一个群中的成员人数可能很多(例如5000+),群成员列表的拉取接口支持过滤器(filter)和分页拉取(nextSeq)两个高级特性。

过滤器

在调用 getGroupMemberList 接口时,您可以指定 filter 确定是否仅拉取特定角色的信息列表。

过滤器 过滤类型
0 拉取所有群成员的信息列表
1 仅拉取群主的信息列表
2 仅拉取群管理员的信息列表
3 仅拉取普通群成员的信息列表
Im.getGroupMemberList({
  groupId: 'group001',
  filter: 1, 
  nextSeq: 0
}, ret => {
  if (ret.hasOwnProperty('status') && ret.status) {
    // 拉取成功
  } else {
    // 拉取失败
  }
});
分页拉取(nextSeq)

很多情况下,用户界面上并不需要展示全部的群成员信息,只需展示群成员列表的第一页即可,等用户单击“下一页”或在列表页下拉刷新时,才需要拉取更多的群成员。针对此类场景,您可以使用分页拉取。

在调用 getGroupMemberList 接口时,一次最多返回50个成员,您可以通过 nextSeq 参数分页拉取成员列表,nextSeq参数为分页拉取标志,第一次拉取时请填0。当首次拉取群成员信息成功后,返回的回调结果中会包含 nextSeq 字段:

  • 如果 nextSeq 等于0,表示已经拉取到了全部的群成员列表。
  • 如果 nextSeq 大于0,表示还有更多的群成员信息可以拉取。您可以根据用户在 UI 上的操作,选择是否进行第二次接口调用以拉取更多的群成员信息。当您进行第二次拉取时,需要将上一次拉取返回的结果中的 nextSeq 作为参数,传入 getGroupMemberList 接口。
// 示例代码:通过 nextSeq 参数进行分页拉取
Im.getGroupMemberList({
  groupId: 'group001',
  filter: 1, 
  nextSeq: 0
}, ret => {
  if (ret.hasOwnProperty('status') && ret.status) {
    // nextSeq 如果大于 0 ,继续分页拉取
    if (ret.nextSeq > 0) {
      Im.getGroupMemberList({
        groupId: 'group001',
        filter: 1, 
        nextSeq: 0
      }, ret => {
        if (ret.hasOwnProperty('status') && ret.status) {
          // 第二次分页拉取成功
        } else {
          // 第二次分页拉取失败
        }
      }
    }
  } else {
    // 第一次分页拉取失败
  }
});
获取群成员资料

调用 getGroupMembersInfo 可以获取群成员资料,该接口支持批量获取,您可以一次传入多个 userId 获取多个群成员的资料,从而提升网络传输效率。

修改群成员资料

群主或管理员可以调用 setGroupMemberInfo 接口修改群成员的群名片(nameCard)、 群成员角色(role)、禁言时间(muteUntil)以及自定义字段等与群成员相关的资料。

禁言

群主或管理员可以通过 muteGroupMember 禁言某一个群成员并设置禁言时间,禁言时间单位为秒,禁言信息存储于群成员的 muteUntil 属性字段中。群成员被禁言后,全员(包括被禁言的群成员)都会收到 onMemberInfoChanged 事件回调。 群主或管理员也可以通过 setGroupInfo 接口对整个群进行禁言,将 allMuted 属性字段设置为 true 即可。全群禁言没有时间限制,需将群资料 allMuted 设置为 false 才能解除禁言。

踢人

群主或管理员调用 kickGroupMember 接口可以实现踢人。由于直播群(AVChatRoom)对进群没有限制,因此直播群(AVChatRoom)没有支持踢人的接口,您可以使用 muteGroupMember 达到同样的目的。 成员被踢后,全员(包括被踢人)会收到 onMemberKicked 回调。

切换群成员角色

群主调用 setGroupMemberRole 可以对陌生人社交群(Public)或临时会议群(Meeting)中的群成员进行角色切换,可切换角色包括普通成员、管理员。

  • 被设置为管理员后,全员(包括被设置的成员)会收到 onGrantAdministrator 回调。
  • 被取消管理员后,全员(包括被设置的成员)会收到 onRevokeAdministrator 回调。
转让群主

群主可以调用 transferGroupOwner 把群主转让给其他群成员。 群主转让后,全员会收到 onGroupInfoChanged 回调,其中 infoList中的 type 为4,value 值为新群主的 userId。

常见问题

1. 直播群(AVChatRoom)中途掉线又连接上后,能否继续接收消息?

可以继续接收消息,但是直播群(AVChatRoom)中的消息不支持云端存储,因此无法拉取到掉线期间的消息。

2. 为什么群成员进群和退群收不到通知?

请确认群组类型:

  • 临时会议群(Meeting)不支持群成员变更通知。
  • 直播群(AVChatRoom)消息限制40条/秒,会优先保证高优先级消息的收发,超过限制后会优先丢弃低优先级的消息。
3. 为什么会议群(Meeting) 中的未读数一直为零?

临时会议群(Meeting)和直播群(AVChatRoom)分别配合会议和直播的音视频场景,因此这两类群组均不支持未读消息计数。

信令管理

概述

信令接口是基于 IM 消息提供的一套邀请流程控制的接口,可以实现多种实时场景,例如:

  • 直播聊天室中进行上麦、下麦管理。
  • 聊天场景中实现类似微信中的音视频通话功能。
  • 教育场景中老师邀请同学们举手、发言的流程控制。

功能

信令接口支持以下功能:

单聊邀请

在使用 简单收发消息接口 或 富媒体消息接口 进行单聊的同时,可以使用 invite 信令接口进行点对点呼叫,对方收到邀请通知 onReceiveNewInvitation 后可以选择接受、拒绝或等待超时。

群聊邀请

首先需通过 建群、加群、退群、解散群以及群资料 和 群成员 相关接口完成对群组的管理,并监听群内的相关事件回调 setGroupListener。然后群成员可以在群内发起群呼叫邀请 inviteInGroup,被邀请的群成员会收到邀请通知 onReceiveNewInvitation 后可以选择接受、拒绝或等待超时。

取消邀请

主叫可以在超时前且被叫未处理前取消邀请 cancel。被邀请者会收到取消通知 onInvitationCancelled,该邀请流程结束。

取消邀请

接受邀请

被叫收到邀请通知 onReceiveNewInvitation 后可以在超时前且主叫取消前接受邀请 accept,主叫会收到接受邀请通知 onInviteeAccepted,所有被叫处理完后(包括接受、拒绝、超时)该邀请流程结束。

接收邀请

拒绝邀请

被叫收到邀请通知 onReceiveNewInvitation 后可以在超时前且主叫取消前拒绝邀请 reject,主叫会收到拒绝邀请通知 onInviteeRejected,所有被叫处理完后(包括接受、拒绝、超时)该邀请流程结束。

邀请超时

若邀请接口的超时时间大于0,且被叫未在超时时间之内响应则邀请超时,主叫和被叫都会收到超时通知 onInvitationTimeout,所有被叫处理完后(包括接受、拒绝、超时)该邀请流程结束。若邀请接口的超时时间等于0,则不会有超时通知。

邀请超时

应用场景案例

音视频通话

在开源项目 TUIKit Demo 中,我们基于 TRTC 组件 并对其稍作修改提供了一个适合聊天场景的1v1和多人音视频通话的方案,您可以直接基于我们提供的 Demo 进行修改适配。我们以1v1视频通话为例介绍下信令接口跟 TRTC SDK 的结合使用。

1v1视频通话的流程:
  1. 邀请者根据业务层生成的 roomId 进入该 TRTC 房间,同时调用信令邀请接口 invite 发起音视频通话请求,并把 roomId 放到邀请接口的自定义字段中。
  2. 被邀请者收到信令邀请通知 onReceiveNewInvitation,并通过自定义数据拿到 roomId,界面开始响铃。
  3. 被邀请者处理邀请通知:
    • 接受邀请需调用信令 accept 接口,并根据 roomId 进入到 TRTC 房间,并同时调用 openCamera() 函数打开自己本地的摄像头,双方收到 TRTC SDK 的 onRemoteUserEnterRoom 回调后记录本次通话的开始时间。
    • 拒绝邀请需调用信令 reject 接口结束本次通话。
    • 如果被邀请者正在跟其他人通话,则调用信令 reject 接口拒绝本次邀请,并在自定义数据中告诉对方是由于本地线路忙而拒绝。
  4. 接听并当双方的音视频通道建立完成后,通话的双方都会接收到 TRTC SDK 的 onUserVideoAvailable 的事件通知,表示对方的视频画面已经拿到。此时双方用户均可以调用 TRTC SDK 接口 startRemoteView 展示远端的视频画面。远端的声音默认是自动播放的。
  5. 通话结束即某一方挂断电话,该用户退出 TRTC 房间。对方收到 TRTC SDK 的 onRemoteUserLeaveRoom 回调后计算通话总时长并再次发起一次邀请,此邀请的自定义数据中标明是结束通话并附带通话时长,方便 UI 界面做展示。
时序图

TRTC时序图

教育场景中老师邀请学生举手发言

该场景为老师先让同学们举手,再从举手的同学中选一个同学进行发言。详细流程如下:

  1. 老师调用 inviteInGroup 接口邀请同学们举手,自定义 data 中填入“举手操作”,同学们收到 onReceiveNewInvitation 回调。
  2. 同学们根据 onReceiveNewInvitation 中的 inviteeList 和 data 字段判断被邀请者里有自己且是举手操作,那么调用 accept 接口举手。
  3. 如果有学生举手,所有人都可以收到 onInviteeAccepted 回调,判断 data 中的字段为“举手操作”,展示举手学生列表。
  4. 老师从举手成员列表中邀请某个同学进行发言,调用 inviteInGroup 接口,此时自定义 data 中填入“发言操作”,学生们都收到 onReceiveNewInvitation 回调。
  5. 学生根据 onReceiveNewInvitation 回调中的 inviteeList 和 data 字段判断被邀请者里有自己且是发言操作,则调用 accept 接口发言。
  6. 如果有学生发言,所有人都可以收到 onInviteeAccepted 回调,判断 data 中的字段为“发言操作”,展示发言成员列表。

用户资料与关系链

用户资料管理

查询和修改自己的资料

查询自己的资料接口为 getUsersInfo,其中参数 userIdList 需填入自己的 userId。 修改自己的资料接口为 setSelfInfo。修改自己的资料成功后,会收到 onSelfInfoUpdated 回调。

查询非好友用户资料

查询非好友资料接口同查询自己的资料 getUsersInfo,参数 userIdList 填入非好友的 userId 即可。

查询和修改好友资料

查询指定的好友资料接口为 getFriendsInfo,从回调信息中通过 V2TIMFriendGetResult 的 relation 字段可以得到该用户与自己的关系:

0 表示不是好友。 1 表示互为好友。 2 表示对方在我的好友列表中。

修改指定的好友信息接口为 setFriendInfo ,可修改好友备注等资料。

屏蔽某人消息

  • 拉黑某人 如需屏蔽某人的消息,请调用 addToBlackList 接口把该用户加入黑名单,即拉黑该用户。 被拉黑的用户默认不会感知到“被拉黑”的状态,消息发送后不会返回已被对方拉黑的错误码。如果希望被拉黑的用户在发消息时返回已被对方拉黑的错误提醒,可以参考 被拉黑的用户发消息怎么给错误提示。

  • 解除拉黑 从黑名单中移除对方后可再次接收对方的消息,可调用 deleteFromBlackList

  • 获取黑名单列表 您可以通过 getBlackList 查看已拉黑多少用户,并对黑名单人员进行管理。

好友管理

是否需要加好友

在发送单聊消息的时候,默认不检查好友关系。在客服场景中,如果用户需要先加客服为好友才能进行沟通非常不方便,因此该默认设置常用于在线客服等场景。

如需实现类似“微信”或者“QQ”中“先加好友,再发消息”的交互体验,您可以在 即时通信 IM 控制台 >【功能配置】>【登录与消息】>【好友关系检查】中开启"发送单聊消息检查关系链"。开启后,用户只能给好友发送消息,当用户给非好友发消息时,SDK 会报20009错误码。

好友关系

好友列表管理

支持好友关系链逻辑,您可以调用 getFriendList 接口获取好友列表,调用 deleteFromFriendList 接口删除好友关系,也可以调用 addFriend 接口添加好友。

根据对方用户资料中的加好友需要验证与否,可以分为两种处理流程:

第一种:加好友不需要对方验证
  1. 用户 A 和 B 调用 setFriendListener 设置关系链监听。
  2. 用户 B 通过 setSelfInfo 函数里的 allowType 字段设置为0加好友不需要验证。
  3. 用户 A 调用 addFriend 申请添加 B 为好友即可添加成功。
    • 如果申请参数 好友的 application 中 addType 设置为双向好友即0,则用户 A 和 B 都会收到 onFriendListAdded 回调;
    • 如果设置为单向好友即1,则只有用户 A 收到 onFriendListAdded 回调。
第二种:加好友需要通过对方验证
  1. 用户 A 和 B 调用 setFriendListener 设置关系链监听。
  2. 用户 B 通过 setSelfInfo 函数里的 allowType 字段设置为1加好友需要验证 。
  3. 用户 A 调用 addFriend 申请添加 B 为好友,接口的成功回调参数中 result 中的 resultCode 返回30539,表示需要等待用户 B 的验证,同时 A 和 B 都会收到 onFriendApplicationListAdded 的回调。
  4. 用户 B 会收到 onFriendApplicationListAdded 的回调,当好友申请参数的application 中的 type 为 1 时,可以选择接受或者拒绝:
好友分组管理

在某些场景下,您可能需要对好友进行分组,例如分为 "大学同学"、"公司同事" 等,您可以调用以下接口实现。

功能描述 接口指引
新建好友分组 createFriendGroup
删除好友分组 deleteFriendGroup
修改好友分组 renameFriendGroup
获取好友分组 getFriendGroupList
添加好友到一个分组 addFriendsToFriendGroup
从分组中删除某好友 deleteFriendsFromFriendGroup

常见使用问题

1. 非好友之间怎么禁止收发消息?

SDK 默认不限制非好友之间收发消息。如果您希望只允许好友之间收发消息,请在 即时通信 IM 控制台 >【功能配置】>【登录与消息】>【好友关系检查】中开启"发送单聊消息检查关系链"。开启之后,给陌生人发消息时,SDK 会报20009错误码。

2. 被拉黑的用户发消息怎么给错误提示?

当消息发送者被拉黑后,发送者默认不会感知到“被拉黑”的状态,即发送消息后仍展示发送成功(实际上此时接收方不会收到消息)。如果需要被拉黑的发送者收到消息发送失败的提示,请在 即时通信 IM 控制台 >【功能配置】>【登录与消息】>【黑名单检查】中关闭"发送消息后展示发送成功",关闭后,被拉黑的发送者在发送消息时,SDK 会报20007错误码。

3. 增强版获取用户资料为什么不是最新的?

增强版 SDK 中用户资料的更新分好友和陌生人两种情况:

  • 好友资料:由于好友资料更新时,后台会主动向 SDK 发送系统通知,因此好友资料可以实时更新。
  • 陌生人资料:陌生人资料更新时,由于没有好友关系,后台无法向 SDK 发送系统通知,因此无法实时更新;为了避免每次获取用户资料都向后台发起网络请求,SDK 增加了缓存逻辑,对同一个用户主动向后台拉取资料的时间间隔为10分钟。

腾讯云视频语音通话

该模块实现腾讯云视频语音通话, 支持视频通话和语音通话, 提供类似微信的视频通话和语音通话功能,适用多人、双人视频语音模式、网络会议、在线医疗、视频客服、金融双录等场景。

快速开始

步骤1: 集成插件

  • 加载插件

插件名称: RY-TencentTrtcCalling

在使用前,你需要先加载插件。

<RY-TencentTrtcCalling class="trtc" ref="calling" v-bind:style = "{ width: playerWidth, height: playerHeight }" @onClick="onClick"></RY-TencentTrtcCalling>

说明:

可以通过修改width和height参数值的大小,来修改视频容器的大小。

  • 腾讯云配置

注册或登录腾讯云账号,实名认证后,点击实时音视频,点击"创建应用"创建实时音视频应用。

步骤2: 开始使用插件

使用RY-TencentTrtcCalling,需要调用 init 初始化模块,才可以调用其他的接口功能。

this.$refs.calling.init({}, ret => {
  console.log(ret);
});

步骤3: 设置监听

调用 setCallingListener 可以设置监听,视频通话会返回相关的事件回调。

this.$refs.calling.setCallingListener({}, ret => {
  console.log(ret);
});

步骤4: 登录

调用 login 完成组件的登录,其中几个关键参数的填写请参考下表

参数名 作用
sdkAppId 您可以在 实时音视频控制台 中查看 sdkAppId
user 当前用户的Id,字符串类型,只允许包含英文字母(a-z 和 A-Z)、数字(0-9)、连词符-和下划线 _
userSig 如何计算 UserSig
this.$refs.calling.login({
  sdkAppId: sdkAppId,
  userId: userId,
  userSig: userSig
}, ret => {
  console.log(ret);
});

步骤5: 实现1V1通话

  1. 发起方: 调用 call 发起视频或语音通话的请求。
  2. 接收方: 当接收方处于已登录状态时,监听器会收到 setCallingListener#onInvited 的事件回调,回调中的callType为发起方的填写的通话类型,您可以通过此参数启动相应的界面。
  3. 接收方: 如果希望接听通话,接收方可以调用 accept 函数,如果此时是视频通话,可以同时调用 openCamera 函数打开自己的本地摄像头。接收方也可以使用 reject 拒绝此次通话。
  4. 当双方音视频通道建立完成,通话双方还会收到 setCallingListener#onUserVideoAvailable 或 setCallingListener#onUserAudioAvailable 的事件回调。此时双方用户可以调用startRemoteView 展示远端的视频画面。视频通话远端的声音默认是自动播放的。
// 1.监听回调
this.$refs.calling.setCallingListener({}, ret => {
  // 接听/拒绝
  // 此时 B 如果也登录了IM系统,会收到 onInvited 回调
  // 可以调用 TRTCCalling的accept方法接受 / TRTCCalling的reject 方法拒绝
  if (ret && ret.hasOwnProperty('eventType')) {
    if ('onInvited' == ret.eventType) {
      this.$refs.calling.accept({}, ret => {
        console.log(ret);
      });
    }
    // 2.观看对方的画面
    // 由于 A 打开了摄像头,B 接受通话后会收到 onUserVideoAvailable 回调
    if ('onUserVideoAvailable' == ret.eventType) {
      if (ret.available) {
        this.$refs.calling.startRemteView({
          userId: ret.userId,
          rect: {
            x: 0, 
            y: 0, 
            w: self.playerWidth, 
            h: self.playerHeight
          }
        }, ret => {
          console.log(ret);
        });
        // 就可以看到对方画面了
      } else {
        // 停止渲染画面
        this.$refs.calling.stopRemoteView({
          userId: ret.userId
        }, ret => {
          console.log(ret);
        });
      }
    }
  }
});

// 3.调用组件的其他功能函数发起通话或挂断等
// 注意:必须在登录后才可以正常调用
// 发起视频通话
this.$refs.calling.call({
  userId: 'test002',
  type: 1
}, ret => {
  console.log(ret);
});
// 挂断
this.$refs.calling.hangup({}, ret => {
  console.log(ret);
});
// 拒绝
this.$refs.calling.reject({}, ret => {
  console.log(ret);
});

步骤6: 实现多人通话

  1. 发起方:多人视频/语音通话需要调用 groupCall 函数,并传入用户Id列表(userIdList)、群组 IM Id(groupId)、通话类型(type),其中 userIdList 为必填参数,groupId 为选填参数,type 为通话类型可以填写1或者2。
  2. 接收端:通过监听器监听 setCallingListener#onInvited 事件回调能够接收到此呼叫请求,其中参数列表就是发起方填入的参数列表,callType 参数为通话类型,您可以通过此参数启动相应的界面。
  3. 接收端:收到回调后可以调用 accept 方法接听此次通话,也可以选择用 reject 方法拒绝通话。
  4. 如果超过一定时间(默认30s)没有回复,接收方监听器会收到 setCallingListener#onCallingTimeOut 的事件回调,发起方监听器会收到 setCallingListener#onNoResp 回调。通话发起方在多个接收均未应答时 hangup ,每个接收方监听器均会收到 setCallingListener#onCallingCancel 回调。
  5. 如果需要离开当前多人通话可以调用 hangup 方法。
  6. 如果通话中有用户中途加入或离开,那么其他用户监听器均会接收到setCallingListener#onUserEnter或setCallingListener#onUserLeave 回调。

说明:

接口 groupCall 中的 groupId 参数是 IM 中的群组Id,如果填写该参数,那么通话请求消息的信令消息是通过群Id发送出去的,这种消息广播方式比较简单可靠。如果不填写,那么 RY-TencentTrtcCalling 组件会采用单发消息逐一通知。

this.$refs.calling.groupCall({
  userIdList: [
    'test002'
  ],
  type: 1,
  groupId: 'group001'
}, ret => {
  console.log(ret);
});

this.$refs.calling.openCamera({
  isFront: true,
  rect: {
    x: 0, 
    y: 0, 
    w: self.playerWidth, 
    h: self.playerHeight
  }
}, ret => {
  console.log(ret);
});

腾讯云视频互动直播

腾讯云实时语音, 提供互动直播的功能,包括直播、互动连麦、主播 PK、低延时观看、弹幕聊天等 在互动直播场景下的相关能力,可用于秀场直播、互动大班课、互动小班课和直播答题等场景。

快速接入

步骤1: 插件的加载和配置

  • 加载插件

首先,uniapp平台的原生插件,需要自定义基座后才能使用,您可以按照自定义基座文档进行。

其次,新建nvue文件,注意该模块必须在nvue中使用。

插件名称为: RY-TencentTrtcLiveRoom,使用标签

<RY-TencentTrtcLiveRoom ref="liveRoom" v-bind:style = "{ width: playerWidth, height: playerHeight }"></RY-TencentTrtcLiveRoom>

备注:

可以通过改变width和height参数的大小,来改变视图容器的大小。

  • 腾讯云配置
  1. 注册或登录腾讯云账号,并进行实名认证;
  2. 点击实时音视频,点击"创建应用"创建实时音视频应用。
  • 生成签名

手动签名点击 UserSig生成&校验 选择对应的sdkAppId的应用,输入userId,获取对应的用户签名userSig;

如果您需要【自动签名】,联系我们(微信号: ruanyunkeji006)获取。

步骤2: 插件初始化

必须调用 init 函数后,才可以使用插件个各个功能。

this.$refs.liveRoom.init({}, ret => {
  console.log(ret);
});

步骤3: 设置监听器

直播的相关信息通过 setLiveRoomListener 返回的事件回调来反馈,有关 事件回调 中含有事件的详细相关说明和参数。

this.$refs.liveRoom.setLiveRoomListener({}, ret => {
  console.log(ret);
});

步骤4: 登录

执行 login 登录后,您才可以执行各个直播相关的操作。

var self = this;
this.$refs.liveRoom.login({
  sdkAppId: self.sdkAppId,
  userId: self.userId,
  userSig: self.userSig
}, ret => {
  uni.showToast({
    title: JSON.stringify(ret),
    icon: "none"
  });
});

步骤5: 主播端开播

  1. 主播登录后,可以调用 setSelfProfile 设置自己的昵称和头像。
  2. 主播在开播前可先调用 startCameraPreview 开启摄像头预览,也可以配置美颜相关功能进行美颜设置。
  3. 主播调整美颜效果后,可以调用 createRoom 创建新的直播间。
  4. 主播调用 startPublish 开始推流。

主播端开播

// 1.主播设置昵称和头像
self.$refs.liveRoom.setSelfProfile({
  userName: 'A',
  avatarUrl: 'faceUrl'
}, ret => {
  console.log(ret);
});
// 2.主播开播前预览并设置美颜参数
this.$refs.liveRoom.startCameraPreview({
  isFront: self.isFront,
  rect: {
    x: 0, 
    y: 0, 
    w: self.playerWidth,
    h: self.playerHeight
  }
}, ret => {
  console.log(ret);
});
// 3.主播创建房间
self.$refs.liveRoom.createRoom({
  roomId: 123456789,
  roomName: '测试房间', 
  coverUrl: 'http://xxx.xxx.xxx/xxx.png'
}, ret => {
  uni.showToast({
    title: JSON.stringify(ret),
    icon: "none"
  });
});
// 4.主播开启推流并将流发布到 CDN
this.$refs.liveRoom.startPublish({
  streamId: 'A_stream'
}, ret => {
  console.log(ret);
});

步骤6: 观众端观看

  1. 观众端执行登录后,可以调用 setSelfProfile 设置自己的昵称和头像。
  2. 观众端向业务后台获取最新的直播房间列表。

说明:

Demo 中的直播间列表仅做演示使用,直播间列表的业务逻辑千差万别,腾讯云暂不提供直播间列表的管理服务,请自行管理您的直播间列表。

  1. 观众端调用 getRoomInfos 获取房间的详细信息,该信息是在主播端调用 createRoom 创建直播间时设置的简单描述信息。

注意:

如果您的直播间列表包含了足够全面的信息,可跳过调用getRoomInfos相关步骤。

  1. 观众选择一个直播间,调用 enterRoom 并传入房间号即可进入该房间。
  2. 调用 startPlay 并传入主播的 userId 开始播放。
    • 若直播间列表已包含主播端的 userId 信息,观众端可直接调用 startPlay 并传入主播的 userId 即可开始播放;
    • 若在进房前暂未获取主播的 userId,观众端在进房后会收到主播setLiveRoomListener#onAnchorEnter 的事件回调,该回调中携带主播的 userId 信息,调用 startPlay 即可播放。

观众端观看

// 1.假定您从业务后台获取房间列表为 roomIdList
// 2.通过调用 getRoomInfos 获取房间的详细信息
this.$refs.liveRoom.getRoomInfos({
  roomIdList: roomIdList
}, ret => {
  console.log(ret);
  // 获取到房间详细信息后,您可以在主播列表页面展示主播昵称、头像等相关信息
});
// 3.选择房间 roomId 进入
self.$refs.liveRoom.enterRoom({
  roomId: roomId,
}, ret => {
  console.log(ret);
});

this.$refs.liveRoom.setLiveRoomListener({}, ret => {
  if (ret.hasOwnProperty('eventType') {
    // 4.观众收到主播进房通知,开始播放
    if ('onAnchorEnter' == ret.eventType) {
      // 5.观众播放主播画面
      this.$refs.liveRoom.startPlay({
        userId: ret.userId,
        rect: {
          x: 0, 
          y: 0,
          w: self.playerWidth / 2,
          h: self.playerHeight / 2
        }
      }, ret => {
        console.log(ret);
      });
    }
  });
});

步骤7: 观众与主播连麦

  1. 观众端调用 setLinkMicListener 设置连麦监听,然后 requestJoinAnchor 向主播端发起连麦请求。
  2. 主播端会收到setLiveRoomListener#onRequestJoinAnchor(即有观众请求与您连麦)的事件通知。
  3. 主播端可以通过调用 responseJoinAnchor 决定是否接受来自观众端的连麦请求。
  4. 观众端连麦监听会收到回调通知,该结果通知会携带来自主播端的处理结果。
  5. 如果主播同意连麦请求,观众端可调用 startCameraPreview 开启本地摄像头,随后调用 startPublish 启动观众端的推流。
  6. 主播端会在观众端启动通知后收到 setLiveRoomListener#onAnchorEnter (即另一路音视频流已到来)通知,该通知会携带观众端的 userId。
  7. 主播端调用 startPlay 即可看到连麦观众的画面。

观众与主播连麦

// 观众端:
// 1.观众端发起连麦请求
this.$refs.liveRoom.requestJoinAnchor({
  reason: self.reason
}, ret => {
  // 4.主播接受了观众的请求
  if (ret.agree) {
    // 5.观众启动预览,开启推流
    this.$refs.liveRoom.startCameraPreview({
      isFront: true,
      rect: {
        x: 0, 
        y: 0, 
        w: self.playerWidth,
        h: self.playerHeight
      }
    }, ret => {
      console.log(ret);
    });
    this.$refs.liveRoom.startPublish({
      streamId: 'stream002'
    }, ret => {
      console.log(ret);
    });
  }
});

// 主播端:
// 2.主播端收到连麦请求
this.$refs.liveRoom.setLiveRoomListener({}, ret => {
  if (ret.hasOwnProperty('eventType')) {
    if ('onRequestJoinAnchor' == ret.eventType) {
      // 3.同意对方的连麦请求
      this.$refs.liveRoom.responseJoinAnchor({
        userId: ret.userInfo.userId,
        isAgree: true, 
        reason: 'This is a reason'
      }, ret => {
        console.log(ret);
      });
    }
    // 6.主播收到连麦观众的上麦通知
    if ('onAnchorEnter' == ret.eventType) {
      // 7.主播播放观众画面
      this.$refs.liveRoom.startPlay({
        userId: ret.userId,
        rect: {
          x: 0, 
          y: 0,
          w: self.playerWidth,
          h: self.playerHeight
        }
      }, ret => {
        console.log(ret);
      });
    }
  }
});

步骤8:主播与主播 PK

  1. 主播 A 调用 setRoomPKListener 设置跨房PK监听,然后调用 requestRoomPK 向主播 B 发起 PK 请求。
  2. 主播 B 会收到 setLiveRoomListener#onRequestRoomPK 回调通知。
  3. 主播 B 调用 responseRoomPK 决定是否接受主播 A 的 PK 请求。
  4. 主播 B 接受主播 A 的请求,等待setLiveRoomListener#onAnchorEnter 通知,调用 startPlay 显示主播 A。
  5. 主播 A 的跨房PK监听收到回调通知,PK 请求是否被同意。
  6. 主播 A 请求被同意,等待 setLiveRoomListener#onAnchorEnter 通知,调用 startPlay 显示主播 B。

主播与主播PK

// 主播 A:
// 主播 A 创建12345的房间
this.$refs.liveRoom.createRoom({
  roomId: 12345,
  roomName: 'roomA', 
  coverUrl: 'http://xxx.xxx.xxx/coverA.png'
}, ret => {
  console.log(ret);
})
// 1.主播 A 向主播 B 发起 PK 请求
this.$refs.liveRoom.requestRoomPK({
  roomId: 54321,
  userId: 'B'
}, ret => {
  console.log(ret);
  // 5.收到是否同意的回调
  if (ret.agree) {
  }
});

this.$refs.liveRoom.setLiveRoomListener({}, ret => {
  if (ret.hasOwnProperty('eventType')) {
    // 4.主播 B 收到主播 A 进房的通知,播放主播 A 的画面
    if ('onAnchorEnter' == ret.eventType) {
      this.$refs.liveRoom.startPlay({
        userId: ret.userId,
        rect: {
          x: 0, 
          y: 0,
          w: self.playerWidth,
          h: self.playerHeight
        }
      }, ret => {
        console.log(ret);
      });
    }
  }
});

// 主播 B:
// 主播 B 创建54321的房间
this.$refs.liveRoom.createRoom({
  roomId: 54321,
  roomName: 'roomB', 
  coverUrl: 'http://xxx.xxx.xxx/coverA.png'
}, ret => {
  console.log(ret);
});

this.$refs.liveRoom.setLiveRoomListener({}, ret => {
  if (ret.hasOwnProperty('eventType')) {
    // 2.主播 B 收到主播 A 的消息
    if ('onRequestRoomPK' == ret.eventType) {
      // 3.主播 B 回复主播 A 接受请求
      this.$refs.liveRoom.responseRoomPK({
          userId: ret.userInfo.userId,
          isAgree: true, 
          reason: 'This is a reason'
        }, ret => {
          console.log(ret);
        });
    }
    // 4.主播 B 收到主播 A 进房的通知,播放主播 A 的画面
    if ('onAnchorEnter' == ret.eventType) {
      this.$refs.liveRoom.startPlay({
        userId: ret.userId,
        rect: {
          x: 0, 
          y: 0,
          w: self.playerWidth,
          h: self.playerHeight
        }
      }, ret => {
        console.log(ret);
      });
    }
  }
});

responseRoomPK 主播响应跨房PK请求

var self = this;
this.$refs.liveRoom.responseRoomPK({
  userId: self.remoteUserId,
  isAgree: self.isAgree, 
  reason: self.reason
}, ret => {
  uni.showToast({
    title: JSON.stringify(ret),
    icon: "none"
  });
});

步骤9:实现文字聊天和弹幕消息

  • 通过 sendRoomTextMsg 可以发送普通的文本消息,所有在该房间内的主播和观众均可以收到setLiveRoomListener#onRecvRoomTextMsg 回调。

即时通信 IM 后台有默认的敏感词过滤规则,被判定为敏感词的文本消息不会被云端转发。

// 发送端:发送文本消息
this.$refs.liveRoom.sendRoomTextMsg({
  msg: 'Hello World!'
}, ret => {
  console.log(ret);
});

// 接收端:监听文本消息
this.$refs.liveRoom.setLiveRoomListener({}, ret => {
  if (ret.hasOwnProperty('eventType')) {
    if ('onRecvRoomTextMsg' == ret.eventType) {
      console.log('收到来自ret.fromUser.userName的文本消息:ret.message')
    }
  }
});

自定义消息常用于传输自定义信令,例如用于点赞消息的发送和广播。、

// 发送端:您可以通过自定义Cmd来区分弹幕和点赞消息
// eg:"CMD_DANMU"表示弹幕消息,"CMD_LIKE"表示点赞消息
this.$refs.liveRoom.sendRoomCustomMsg({
  cmd: 'CMD_DANMU', 
  msg: 'Hello world'
}, ret => {
  console.log(ret);
});
this.$refs.liveRoom.sendRoomCustomMsg({
  cmd: 'CMD_LIKE', 
  msg: ''
}, ret => {
  console.log(ret);
});

this.$refs.liveRoom.setLiveRoomListener({}, ret => {
  if (ret.hasOwnProperty('eventType')) {
    // 接收端:监听自定义消息
    if ('onRecvRoomCustomMsg' == ret.eventType) {
      if ('CMD_DANMU' == ret.command) {
        console.log('收到来自ret.fromUser.userName的文本消息:ret.message')
      }
      if ('CMD_LIKE' == ret.command) {
        console.log('ret.fromUser.userName给您点了个赞!')
      }
    }
  }
});

腾讯云多人视频会议

腾讯云多人视频会议, 提供多人视频会议功能,包括屏幕分享、美颜、低延时会议等在多人视频会议场景下的相关能力。

支持以下功能:

  • 主持人创主持人创建会议房间,参会人员输入房间号后进入会议。
  • 参会人员之间进行屏幕分享。
  • 支持发送各种文本消息和自定义消息。

快速开始

步骤1: 插件的加载和配置

  • 加载插件

首先,加载uniapp平台的原生插件,需要自定义基座后才能使用,您可以按照自定义基座文档进行。

其次,新建nvue文件,注意该插件必须在nvue中使用。

插件名称为: RY-TencentTrtcMeeting,

该插件为Component类型,需要使用标签对来引用。

<RY-TencentTrtcMeeting ref="meeting" v-bind:style = "{ width: playerWidth, height: playerHeight }"></RY-TencentTrtcMeeting>

备注:

可以通过改变width和height参数的大小,来改变视图容器的大小。

  • 腾讯云配置
  1. 注册或登录腾讯云账号,并进行实名认证;
  2. 点击实时音视频,点击"创建应用"创建实时音视频应用。
  • 生成签名

手动签名点击 UserSig生成&校验 选择对应的sdkAppId的应用,输入userId,获取对应的用户签名userSig;

如果您需要【自动签名】,联系我们(微信号: ruanyunkeji006)获取。

步骤2: 开始使用插件

init 初始化插件之后,才可以调用各个接口功能。

this.$refs.meeting.init({
  docPath: plus.io.convertLocalFileSystemURL('_doc')
}, ret => {
  console.log(ret);
});

步骤3: 设置监听器

调用设置监听器 setMeetingListener,监听会议的事件回调

this.$refs.meeting.setMeetingListener({}, ret => {
  console.log(ret);
});

步骤4: 登录

调用 login 函数完成组件的登录,请填写以下关键参数:

参数名 作用
sdkAppId 您可以在 实时音视频控制台 中查看 sdkAppId
userId 当前用户的Id,字符串类型,只允许包含英文字母(a-z、A-Z)、数字(0-9)、连词符 - 和下划线 _
userSig 用户签名
this.$refs.meeting.login({
  sdkAppId: 1423xx38,
  userId: 'test001',
  userSig: 'jkwic1xxx2mn12'
}, ret => {
  console.log(ret);
});

步骤5: 创建多人会议

  1. 主持人执行 步骤4 登录后,可以调用 setSelfProfile 设置自己的昵称和头像。
  2. 主持人调用 setMeetingListener 可以进行事件监听,调用 createMeeting 创建新的会议房间。
  3. 主持人可以调用 startCameraPreview 进行视频画面的采集,也可以调用 startMicrophone 进行声音的采集。

说明:

非企业版 SDK 不支持变脸和贴图挂件功能,如果有企业版需求,请联系我们上方的技术客服。

创建多人会议

// 1.主播设置昵称和头像
this.$refs.meeting.setSelfProfile({
  userName: 'A',
  avatarUrl: 'http://xxx.myqcloud.com/xxx.png'
}, ret => {
  console.log(ret);
});

// 2.主播创建房间
this.$refs.meeting.createMeeting({
  roomId: self.roomId
}, ret => {
  if (ret.status) {
    // 创建房间成功
    this.$refs.meeting.startCameraPreview({
      isFront: true,
      rect: {
        x: 0, 
        y: 0, 
        w: self.playerWidth,
        h: self.playerHeight
        }
    }, ret => {
      console.log(ret);
    });
    this.$refs.meeting.startMicrophone({}, ret => {
      console.log(ret);
    });
  }
});

步骤6:参会成员进入多人会议

  1. 参会成员执行 步骤4 登录后,可以调用 setSelfProfile 设置自己的昵称和头像。
  2. 参会成员调用 enterMeeting 并传入会议房间号即可进入会议房间。
  3. 参会成员可以调用 startCameraPreview 进行视频画面的采集,调用 startMicrophone 进行声音的采集。
  4. 如果有其他的参会成员打开了摄像头,会收到 onUserVideoAvailable 的事件,此时可以调用 startRemoteView 并传入 userId 开始播放。

成员进入

// 1. 参会成员设置昵称和头像
this.$refs.meeting.setSelfProfile({
  name: 'A', 
  avatarUrl: 'http://xxx.myqcloud.com/xxx.png'
}, ret => {
  console.log(ret);
});

// 2. enterMeeting 函数实现
this.$refs.meeting.enterMeeting({
  roomId: 1234
}, ret => {
  if (ret.status) {
    this.$refs.meeting.startCameraPreview({
      rect: {
        x: 0, 
        y: 0, 
        w: self.playerWidth, 
        h: self.playerHeight
      }
    }, ret => {
      console.log(ret);
    });
    this.$refs.meeting.startMicrophone({}, ret => {
      console.log(ret);
    });
  } else {
    console.log('进入会议失败: ' + ret.msg);
  }
});
this.$refs.meeting.setMeetingListener({}, ret => {
  if (ret.hasOwnProperty('eventType')) {
    //收到回调,并调用 startRemoteView,传入 userId 开始播放
    if ('onUserVideoAvailable' == ret.eventType && ret.available) {
      this.$refs.meeting.startRemoteView({
        userId: ret.userId, 
        rect: {
          x: 0, 
          y: 0, 
          w: self.playerWidth / 2, 
          h: self.playerHeight / 2
        }
      }, ret => {
        console.log(ret);
      });
    } else {
      this.$refs.meeting.stopRemoteView({
        userId: ret.userId
      }, ret => {
        console.log(ret);
      });
    }
  }
});

步骤7:屏幕分享

  1. 调用 startScreenCapture,传入编码参数即可实现屏幕分享功能,具体信息请参见示例代码。
  2. 会议中其他成员会收到 onUserVideoAvailable 的事件通知。

注意:

屏幕分享和摄像头采集是两个互斥的操作,如果需要打开屏幕分享功能,请先调用stopCameraPreview 关闭摄像头采集。

this.$refs.meeting.startScreenCapture({}, ret => {
  console.log(ret);
});

步骤8:实现文字聊天和禁言消息

即时通信 IM 后台有默认的敏感词过滤规则,被判定为敏感词的文本消息不会被云端转发。

// 发送端:发送文本消息
this.$refs.meeting.sendRoomTextMsg({
  msg: 'Hello World!'
}, ret => {
  console.log(ret);
});

this.$refs.metting.setMeetingListener({}, ret => {
  if (ret.hasOwnProperty('eventType')) {
    // 接收端:监听文本消息
    if ('onRecvRoomTextMsg' == ret.eventType) {
      console.log('收到来自:' + ret.userInfo.userId + '的消息' + ret.message);
    }
  }
});

自定义消息常用于传输自定义信令,例如用于禁言之类的会场控制等。

// 发送端:您可以通过自定义 Cmd 来区分禁言通知
// eg:"CMD_MUTE_AUDIO"表示禁言通知
this.$refs.meeting.sendRoomCustomMsg({
  cmd: 'CMD_MUTE_AUDIO',
  msg: '1'
}, ret => {
  console.log(ret);
});

this.$refs.metting.setMeetingListener({}, ret => {
  if (ret.hasOwnProperty('eventType')) {
    // 接收端:监听自定义消息
    if ('onRecvRoomCustomMsg' == ret.eventType) {
      console.log('收到来自:' + ret.userInfo.userId + '的禁言通知' + ret.message);
    }
  }
});

腾讯云语音聊天室

该模块提供语音聊天室的功能, 包括麦位管理、低延时语音互动、文字聊天等 TRTC 在语音聊天场景下的相关能力,可以用于语聊房、语音电台、在线 K 歌等语音互动直播场景。

快速开始

步骤1: 加载插件

  • 加载插件

首先,uniapp平台的原生插件,需要自定义基座后才能使用,您可以按照自定义基座文档进行自定义基座操作。

新建nvue文件,注意该模块必须在nvue中使用。

插件名称为: RY-TencentTrtcVoiceRoom,使用标签

<RY-TencentTrtcVoiceRoom ref="voiceRoom" v-bind:style = "{ width: playerWidth, height: playerHeight }"></RY-TencentTrtcVoiceRoom>
  • 腾讯云配置

注册或登录腾讯云账号,实名认证后,开通实时音视频

  • 生成签名

手动签名点击 UserSig生成&校验 选择对应的sdkAppId的应用,输入userId,获取对应的用户签名userSig;

如果您需要【自动签名】,联系我们(微信号: ruanyunkeji006)获取。

步骤2: 插件初始化

必须调用 init 函数后,才可以使用插件个各个功能。

this.$refs.voiceRoom.init({}, ret => {
  console.log(ret);
});

步骤3: 设置监听

调用 setVoiceRoomListener 函数注册组件的事件回调

this.$refs.voiceRoom.setVoiceRoomListener({}, ret => {
  uni.showToast({
    title: JSON.stringify(ret),
    icon: "none"
  });
});

步骤4: 登录

调用 login 函数完成组件的登录,请参考下表填写关键参数

this.$refs.voiceRoom.login({
  sdkAppId: self.sdkApp Id,
  userId: self.userId, 
  userSig: self.userSig
}, ret => {
    console.log(ret);
});

步骤5: 主播端开播

  1. 主播执行 步骤四 登录后,可以调用 setSelfProfile 设置自己的昵称和头像。
  2. 主播调用 createRoom 创建新的语音聊天室,此时传入房间 Id、上麦是否需要房主确认、麦位数等房间属性信息。
  3. 主播创建房间成功后,调用 enterSeat 进入座位。
  4. 主播收到插件的 setVoiceRoomListener#onSeatListChange 麦位表变化事件通知,此时可以将麦位表变化刷新到 UI 界面上。
  5. 主播还会收到麦位表有成员进入的 setVoiceRoomListener#onAnchorEnterSeat 的事件通知,此时会自动打开麦克风采集。

主播端开播

// 1.房主设置昵称和头像
self.$refs.voiceRoom.setSelfProfile({
  userName: self.userName,
  avatarUrl: self.avatarUrl
}, ret => {
  // 结果回调
  console.log(ret);
});

// 2.房主端创建房间
this.$refs.voiceRoom.createRoom({
  roomId: self.roomId, 
  roomParam: self.roomParam
}, ret => {
  uni.showToast({
    title: JSON.stringify(ret),
    icon: "none"
  });
});

// 创建房间成功后开始占座
this.$refs.voiceRoom.enterSeat({
  seatIndex: 0
}, ret => {
  if (ret.status) {
    // 房主占座成功
  } else {
    // 房主占座失败
  }
});

// 3.占座成功后,收到 onSeatListChange 事件通知
this.$refs.voiceRoom.setVoiceRoomListener({}, ret => {
  if (ret.hasOwnProperty('eventType')) {
    if ('onSeatListChange' == ret.eventType) {
      // 刷新您的麦位列表
    }

    // 4. 收到 onAnchorEnterSeat 事件通知
    if ('onAnchorEnterSeat' == ret.eventType) {
      // 处理房主上麦事件
    }
  }
});

步骤6: 观众端观看

  1. 观众端执行 步骤4 登录后,可以调用 setSelfProfile 设置自己的昵称和头像。
  2. 观众端向业务后台获取最新的语音聊天室房间列表。

说明:

语音聊天室列表仅做演示使用,语音聊天室列表的业务逻辑千差万别,腾讯云暂不提供语音聊天室列表的管理服务,请自行管理您的语音聊天室列表。

  1. 观众端调用 getRoomInfoList 获取房间的详细信息,该信息是在主播端调用 createRoom 创建语音聊天室时设置的简单描述信息。

注意:

如果您的语音聊天室列表包含了足够全面的信息,可跳过调用 getRoomInfoList 相关步骤。

  1. 观众选择一个语音聊天室,调用 enterRoom 并传入房间号即可进入该房间。
  2. 进房后会收到插件的 setVoiceRoomListener#onRoomInfoChange 房间属性变化事件通知,此时可以记录房间属性并做相应改变,例如 UI 展示房间名、记录上麦是否需要请求主播同意等。
  3. 进房后会收到组件的 setVoiceRoomListener#onSeatListChange 麦位表变化事件通知,此时可以将麦位表变化刷新到 UI 界面上。
  4. 进房后还会收到麦位表有主播进入的 setVoiceRoomListener#onAnchorEnterSeat 的事件通知。

观众端观看

// 1.听众设置昵称和头像
self.$refs.voiceRoom.setSelfProfile({
  userName: self.userName,
  avatarUrl: self.avatarUrl
}, ret => {
  // 结果回调
  console.log(ret);
});

// 2.假定您从业务后台获取房间列表为 roomIdList
// 3.通过调用 getRoomInfoList 获取房间的详细信息
this.$refs.voiceRoom.getRoomInfoList({
  roomIdList: self.roomIdList
}, ret => {
  // 获取结果,此时可以刷新UI
  console.log(ret);
});

// 4.选择语音聊天室后,传入 roomId 进入房间
this.$refs.voiceRoom.enterSeat({
  seatIndex: self.seatIndex
}, ret => {
  // 进入房间结果回调
  console.log(ret);
  if (ret.status) {
    // 进房成功
  }
});

步骤7: 麦位管理

主播端:

  1. pickSeat 传入对应的麦位和观众 userId, 可以抱人上麦,房间内所有成员会收到setVoiceRoomListener#onSeatListChange 和 setVoiceRoomListener#onAnchorEnterSeat 的事件通知。
  2. kickSeat 传入对应麦位后,可以踢人下麦,房间内所有成员会收到 setVoiceRoomListener#onSeatListChange 和 setVoiceRoomListener#onAnchorLeaveSeat 的事件通知。
  3. muteSeat 传入对应麦位后,可以静音/解除静音,房间内所有成员会收到 setVoiceRoomListener#onSeatListChange 和 setVoiceRoomListener#onSeatMute 的事件通知。
  4. closeSeat 传入对应麦位后,可以封禁/解禁某个麦位,封禁后观众端将不能再上麦,房间内所有成员会收到 setVoiceRoomListener#onSeatListChange 和 setVoiceRoomListener#onSeatClose 的事件通知。

主播端

观众端:

  1. enterSeat 传入对应的麦位后,可以进行上麦,房间内所有成员会收到 setVoiceRoomListener#onSeatListChange 和 setVoiceRoomListener#onAnchorEnterSeat 的事件通知。
  2. leaveSeat 主动下麦,房间内所有成员会收到 setVoiceRoomListener#onSeatListChange 和 setVoiceRoomListener#onAnchorLeaveSeat 的事件通知。

观众端

麦位操作后的事件通知顺序如下:callback > onSeatListChange > onAnchorEnterSeat 等独立事件。

// case1: 房主抱人上1号麦位
this.$refs.voiceRoom.pickSeat({
  seatIndex: 1, 
  userId: '123'
}, ret => {
  // 结果回调
  console.log(ret);
});

this.$refs.voiceRoom.setVoiceRoomListener({}, ret => {
  if (ret.hasOwnProperty('eventType')) {
    // 3.收到 onSeatListChange 回调,刷新您的麦位列表
    if ('onSeatListChange' == ret.eventType) {
      // 刷新的麦位列表
    }
    // 4.单个麦位变化的通知,可以在这里判断听众是不是真的上麦成功
    if ('onAnchorEnterSeat' == ret.eventType) {
      // 处理上麦事件
    }
  }
});
// case2: 听众主动上2号麦位
this.$refs.voiceRoom.enterSeat({
  seatIndex: 2
}, ret => {
  // 上麦结果回调
  console.log(ret);
});

this.$refs.voiceRoom.setVoiceRoomListener({}, ret => {
  if (ret.hasOwnProperty('eventType')) {
    // 3.收到 onSeatListChange 回调,刷新您的麦位列表
    if ('onSeatListChange' == ret.eventType) {
      // 刷新的麦位列表
    }
    // 4.单个麦位变化的通知,可以在这里判断是不是自己并进行相应处理
    if ('onAnchorEnterSeat' == ret.eventType) {
      // 处理上麦事件
    }
  }
});

步骤8:邀请信令使用

在 麦位管理 中,观众上下麦、主播抱人上麦都不需要经过对方的同意就可以直接操作。 如果您的 App 需要对方同意才能进行下一步操作的业务流程,那么邀请信令可以提供相应支持。

如果您的观众上麦需要申请:

  1. 观众端调用 sendInvitation 传入主播的 userId 和业务的自定义命令字等,此时函数会返回一个 inviteId,记录该 inviteId。
  2. 主播端收到 setVoiceRoomListener#onReceiveNewInvitation 的事件通知,此时 UI 可以弹窗并询问主播是否同意。
  3. 主播选择同意后,调用 acceptInvitation 并传入 inviteId。
  4. 观众端收到 setVoiceRoomListener#onInviteeAccepted 的事件通知,调用 enterSeat 进行上麦。

观众上麦需要申请

// 听众(test002)视角
// 1.调用 sendInvitation,请求上1号麦位
this.$refs.voiceRoom.sendInvitation({
  cmd: 'ENTER_SEAT', 
  userId: 'test001',
  content: '1'
}, ret => {
  // 发送结果回调
  console.log(ret);
});

// 2.收到邀请的同意请求, 正式上麦
this.$refs.voiceRoom.setVoiceRoomListener({}, ret => {
  if (ret.hasOwnProperty('eventType')) {
    if ('onInviteeAccepted' == ret.eventType) {
      if (ret.invitee == 'test002') {
        this.$refs.voiceRoom.enterSeat({
          seatIndex: 1
        }, ret => {
          console.log(ret);
        });
      }
    }
  }
});

// 房主端test001视角
// 1.房主收到请求
this.$refs.voiceRoom.setVoiceRoomListener({}, ret => {
  if (ret.hasOwnProperty('eventType')) {
    if ('onReceiveNewInvitation' == ret.eventType) {
      if (cmd == 'ENTER-SEAT') {
        // 2.房主同意听众请求
        this.$refs.voiceRoom.acceptInvitation({
          inviteId: ret.inviteId
        }, ret => {
          console.log(ret);
        });
      }
    }
  }
})

如果您的主播需要发送邀请才能抱观众上麦:

  1. 主播端调用 sendInvitation 传入观众的 userId 和业务的自定义命令字等,此时函数会返回一个 inviteId,记录该 inviteId。
  2. 观众端收到 setVoiceRoomListener#onReceiveNewInvitation 的事件通知,此时 UI 可以弹窗并询问观众是否同意上麦。
  3. 观众选择同意后,调用 acceptInvitation 并传入 inviteId。
  4. 主播端收到 setVoiceRoomListener#onInviteeAccepted 的事件通知,调用 pickSeat 抱观众上麦。

需要主播发送申请才能抱观众上麦

步骤9:实现文字和弹幕消息

  • 通过 sendRoomTextMsg 可以发送普通的文本消息,所有在该房间内的主播和观众均可以收到 setVoiceRoomListener#onRecvRoomTextMsg 回调

即时通信 IM 后台有默认的敏感词过滤规则,被判定为敏感词的文本消息不会被云端转发。

this.$refs.voiceRoom.sendRoomTextMsg({
  msg: 'This is a msg'
}, ret => {
  console.log(ret);
});

自定义消息常用于传输自定义信令,例如用于点赞消息的发送和广播。

this.$refs.voiceRoom.sendRoomCustomMsg({
  cmd: 'This is a cmd', 
  msg: 'This is a msg'
}, ret => {
  console.log(ret);
});

更多功能

  • 视频语音通话全局监听
  • 消息文件下载(图片、视频、语音和文件等)
  • 离线推送
  • 自动签名

扫码添加, 获取技术支持:

技术支持



微信号: ruanyunkeji006

隐私、权限声明

1. 本插件需要申请的系统权限列表:

Android: "android.permission.RECEIVE_BOOT_COMPLETED", "android.permission.INTERNET", "android.permission.ACCESS_NETWORK_STATE", "android.permission.ACCESS_WIFI_STATE", "aandroid.permission.WRITE_EXTERNAL_STORAGE", "android.permission.READ_EXTERNAL_STORAGE", "android.permission.RECORD_AUDIO", "android.permission.MODIFY_AUDIO_SETTINGS", "android.permission.BLUETOOTH", "android.permission.CAMERA", "android.permission.READ_PHONE_STATE", "android.hardware.camera", "android.hardware.camera.autofocus" iOS: 无

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件使用的腾讯IM SDK会采集数据,详情可参考:https://cloud.tencent.com/document/product/269

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问