持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情
腾讯即时通讯IM
要想在小程序中实现类似QQ、微信一对一或者一对多实时聊天功能,可以在腾讯云提供的即时通讯IM基础上进行开发。官方针对不同的应用,比如Web、小程序、Android、IOS、uni-app、Electron、Unity、UE、Flutter和React Native都提供了相应的IM SDK详细文档和简单Demo,开发人员可以先下载Demo查看实现效果,再在IM SDK配置文档的基础上进行开发环境的配置。
本文就将记录如何从零开始配置原生微信小程序即时通讯IM开发环境,为后续实现聊天功能奠定开发基础。
配置原生小程序IM开发环境
IM配置步骤
- 首先需要安装好微信开发者工具,可以直接依据小程序文档进行安装。此处不再过多赘述。
- 登录即时通讯IM控制台,这里需要先注册腾讯云账号,登录成功后,创建新应用并输入应用名称,然后就能够查看该新建应用的状态、业务版本、SDKAppID、创建时间以及到期时间等信息。点击该应用,复制并保存SDKAppID信息以及密钥,后续在小程序中需要使用。如下图
- 获取GenerateTestUserSig.js,该文件在TUIKit源码内,可通过如下命令获取:
git clone https://github.com/tencentyun/TIMSDK.git
,然后单独保存TUIKit/miniprogram/debug/GenerateTestUserSig.js文件,便于后续登录im实时聊天时作为参数传入使用。 - 更改GenerateTestUserSig.js文件中的SDKAPPID和SECRETKEY为我们上一步骤获取的SDKAppID信息以及密钥
该文件主要用于在客户端生成UserSig,前期开发或测试时可以使用,但是如果要上线,更加推荐将UserSig的计算代码集成到服务端并提高获取UserSig的接口。
原生小程序集成IM SDK
该步骤主要是将腾讯云即时通IM SDK集成到小程序项目中。
首先新建一个小程序项目,创建utils文件夹,该文件夹下创建tencentIM文件夹,用于存放IM SDK相关的文件,比如我们将之前获取Usersig的GenerateTestUserSig.js、lib-generate-test-usersig-es.min.js文件就放置于该文件夹下。
安装IM SDK相关插件:通过以下命令安装tim-wx-sdk和tim-upload-plugin,tim-upload-plugin主要用于发送上传图片、文件等。
npm install tim-wx-sdk --save
// 发送图片、文件等消息需要腾讯云 即时通信 IM 上传插件
npm install tim-upload-plugin --save
安装完成后,点击微信开发者工具中:工具-构建npm,开始构建npm,构建完成后代码目录如下图所示:
最后在项目中引入IM SDK相关模块并初始化:
import TIM from 'tim-wx-sdk';
import TIMUploadPlugin from 'tim-upload-plugin';
let options = {
SDKAppID: 0 // 接入时需要将0替换为您的即时通信 IM 应用的 SDKAppID
};
// 创建 SDK 实例,`TIM.create()`方法对于同一个 `SDKAppID` 只会返回同一份实例
let tim = TIM.create(options); // SDK 实例通常用 tim 表示
// 设置 SDK 日志输出级别,详细分级请参见 setLogLevel https://web.sdk.qcloud.com/im/doc/zh-cn/SDK.html#setLogLevel 接口的说明</a>
tim.setLogLevel(0); // 普通级别,日志量较多,接入时建议使用
// tim.setLogLevel(1); // release 级别,SDK 输出关键信息,生产环境时建议使用
// 注册腾讯云即时通信 IM 上传插件
tim.registerPlugin({'tim-upload-plugin': TIMUploadPlugin});
初始化代码
由于后续许多消息监听与收发等代码都需要在SDK初始化之后进行,所以可以将上述初始化代码封装为单独的一个init_TIM方法:
function init_TIM() { //初始化im实时聊天
if (app.globalData.isInit) {
//这里设置了一个全局变量isInit来标记是否已登录,避免重复创建im实例
return false
}
let options = {
SDKAppID: xxxxxx // 接入时需要将0替换为您的即时通信 IM 应用的 SDKAppID
};
// 创建 SDK 实例,`TIM.create()`方法对于同一个 `SDKAppID` 只会返回同一份实例
tim = TIM.create(options); // SDK 实例通常用 tim 表示
// 设置 SDK 日志输出级别,详细分级请参见 setLogLevel 接口的说明
tim.setLogLevel(0); // 普通级别,日志量较多,接入时建议使用
// tim.setLogLevel(1); // release 级别,SDK 输出关键信息,生产环境时建议使用
// 注册腾讯云即时通信IM上传插件
tim.registerPlugin({
'tim-upload-plugin': TIMUploadPlugin
});
// 监听事件,例如:
tim.on(TIM.EVENT.SDK_READY, function (event) {
console.log('SDK_READY');
// 收到离线消息和会话列表同步完毕通知,接入侧可以调用 sendMessage 等需要鉴权的接口
// event.name - TIM.EVENT.SDK_READY
});
tim.on(TIM.EVENT.MESSAGE_RECEIVED, function (event) {
console.log('收到消息');
console.log(event.data);
// // event.name - TIM.EVENT.MESSAGE_RECEIVED
// // event.data - 存储 Message 对象的数组 - [Message]
});
tim.on(TIM.EVENT.MESSAGE_REVOKED, function (event) {
// 收到消息被撤回的通知
// event.name - TIM.EVENT.MESSAGE_REVOKED
// event.data - 存储 Message 对象的数组 - [Message] - 每个 Message 对象的 isRevoked 属性值为 true
console.log('消息被撤回');
console.log(event.data);
});
tim.on(TIM.EVENT.MESSAGE_READ_BY_PEER, function (event) {
// SDK 收到对端已读消息的通知,即已读回执。使用前需要将 SDK 版本升级至 v2.7.0 或以上。仅支持单聊会话。
// event.name - TIM.EVENT.MESSAGE_READ_BY_PEER
// event.data - event.data - 存储 Message 对象的数组 - [Message] - 每个 Message 对象的 isPeerRead 属性值为 true
});
tim.on(TIM.EVENT.CONVERSATION_LIST_UPDATED, function (event) {
// 收到会话列表更新通知,可通过遍历 event.data 获取会话列表数据并渲染到页面
// event.name - TIM.EVENT.CONVERSATION_LIST_UPDATED
// event.data - 存储 Conversation 对象的数组 - [Conversation]
// 更新当前所有会话列表
console.log('发送了消息');
console.log('更新当前所有会话列表');
console.log(event.data);
});
tim.on(TIM.EVENT.GROUP_LIST_UPDATED, function (event) {
// 收到群组列表更新通知,可通过遍历 event.data 获取群组列表数据并渲染到页面
// event.name - TIM.EVENT.GROUP_LIST_UPDATED
// event.data - 存储 Group 对象的数组 - [Group]
});
tim.on(TIM.EVENT.PROFILE_UPDATED, function (event) {
// 收到自己或好友的资料变更通知
// event.name - TIM.EVENT.PROFILE_UPDATED
// event.data - 存储 Profile 对象的数组 - [Profile]
});
tim.on(TIM.EVENT.BLACKLIST_UPDATED, function (event) {
// 收到黑名单列表更新通知
// event.name - TIM.EVENT.BLACKLIST_UPDATED
// event.data - 存储 userID 的数组 - [userID]
});
tim.on(TIM.EVENT.ERROR, function (event) {
// 收到 SDK 发生错误通知,可以获取错误码和错误信息
// event.name - TIM.EVENT.ERROR
// event.data.code - 错误码
// event.data.message - 错误信息
});
tim.on(TIM.EVENT.SDK_NOT_READY, function (event) {
// 收到 SDK 进入 not ready 状态通知,此时 SDK 无法正常工作
// event.name - TIM.EVENT.SDK_NOT_READY
console.log('SDK_NOT_READY');
});
tim.on(TIM.EVENT.KICKED_OUT, function (event) {
// 收到被踢下线通知
// event.name - TIM.EVENT.KICKED_OUT
// event.data.type - 被踢下线的原因,例如:
// - TIM.TYPES.KICKED_OUT_MULT_ACCOUNT 多实例登录被踢
// - TIM.TYPES.KICKED_OUT_MULT_DEVICE 多终端登录被踢
// - TIM.TYPES.KICKED_OUT_USERSIG_EXPIRED 签名过期被踢 (v2.4.0起支持)。
console.log('KICKED_OUT');
});
tim.on(TIM.EVENT.NET_STATE_CHANGE, function (event) {
// 网络状态发生改变(v2.5.0 起支持)。
// event.name - TIM.EVENT.NET_STATE_CHANGE
// event.data.state 当前网络状态,枚举值及说明如下:
// \- TIM.TYPES.NET_STATE_CONNECTED - 已接入网络
// \- TIM.TYPES.NET_STATE_CONNECTING - 连接中。很可能遇到网络抖动,SDK 在重试。接入侧可根据此状态提示“当前网络不稳定”或“连接中”
// \- TIM.TYPES.NET_STATE_DISCONNECTED - 未接入网络。接入侧可根据此状态提示“当前网络不可用”。SDK 仍会继续重试,若用户网络恢复,SDK 会自动同步消息
});
tim.on(TIM.EVENT.FRIEND_APPLICATION_LIST_UPDATED, function (event) {
console.log('需对方验证通过');
console.log(event);
// friendApplicationList - 好友申请列表 - [FriendApplication]
// unreadCount - 好友申请的未读数
const {
friendApplicationList,
unreadCount
} = event.data;
});
tim.on(TIM.EVENT.FRIEND_LIST_UPDATED, function (event) {
console.log('无需对方验证通过,自动添加通过');
console.log(event);
});
tim.on(TIM.EVENT.FRIEND_LIST_UPDATED, function (event) {
console.log('好友列表更新');
console.log(event.data);
getFriendGroupList_TIM();
});
app.globalData.isInit = true; //完成im实例创建后设置标志为true
}
如果要使用到关系链,即添加好友、好友关系等功能,则需要使用tim-wx-friendship.js,该文件在tim-wx-sdk文件夹下:
// import TIM from 'tim-wx-sdk'; // 无需关系链使用
//需要关系链则引入tim-wx-friendship.js
import TIM from '../../miniprogram_npm/tim-wx-sdk/tim-wx-friendship.js';
为了便于管理,可以在tencentIM文件夹下新建一个tim_func文件,该文件中引入SDK相关模块、定义上述初始化init_TIM函数、定义各种方法,这样能够方便的在SDK的各个监听函数中调用相关方法。如下所示:
注意点
- 需要注意的是,由于小程序不存在类似Vue一样的事件监听机制或观察者订阅者的Api,所以需要单独新建一个Event类,去实现类似触发emit、监听on等方法。代码如下:
class Event {
on(event, fn) {
if (typeof fn != "function") {
console.error('fn must be a function')
return
}
this._cbs = this._cbs || {};
(this._cbs[event] = this._cbs[event] || []).push(fn)
}
emit(event) {
this._cbs = this._cbs || {}
var callbacks = this._cbs[event], args
if (callbacks) {
callbacks = callbacks.slice(0)
args = [].slice.call(arguments, 1)
for (var i = 0, len = callbacks.length; i < len; i++) {
callbacks[i].apply(null, args)
}
}
}
}
export default Event
- 如果需要上线,则需要对域名进行配置
将以下域名添加到 request 合法域名:
api.im.qcloud.com
web.sdk.qcloud.com
webim.tim.qq.com
将以下域名添加到socket合法域名
wss://wss.im.qcloud.com
wss://wss.tim.qq.com
将以下域名添加到uploadFile合法域名:
cos.ap-shanghai.myqcloud.com
将以下域名添加到downloadFile合法域名:
cos.ap-shanghai.myqcloud.com