本文详细介绍如何建立一个简单的项目并使用 Agora RTM SDK 实现消息发送与接收。
登录 RTM 系统包括以下流程:
发送和接收点对点消息包括以下流程:
发送和接收频道消息包括以下流程:
按照以下步骤,在控制台创建一个 Agora 项目。
在项目管理页面,点击创建按钮。
在弹出的对话框内输入项目名称,选择鉴权机制为 APP ID + Token。
点击提交,新建的项目就会显示在项目管理页中。
Agora 会给每个项目自动分配一个 App ID 作为项目唯一标识。
在 Agora 控制台的项目管理页面,找到你的项目,点击 App ID 右侧的眼睛图标就可以直接复制项目的 App ID。
点击编辑进入编辑项目页面,你可以点击眼睛图标查看并复制 App 证书。
为提高项目的安全性,Agora 使用 Token(动态密钥)对即将加入 RTM 系统的用户进行鉴权。
为了方便测试,Agora 提供生成临时 RTM Token 的功能,具体步骤如下:
新建一个目录 RTM_quickstart
。在目录下运行 npm init
创建一个 package.json
文件,然后创建以下文件
index.html
index.js
此时你的目录中包含以下文件:
RTM_quickstart
├─ index.html
├─ index.js
└─ package.json
你可以选择以下方法集成 SDK。本示例使用 npm 进行集成。
下载 Agora RTM SDK for Web。将 libs
中的 JS 文件保存到你的项目下。
在 HTML 文件中,对 JS 文件进行引用。
<script src="path to the JS file"></script>
(可选)你可以通过下面的步骤开启智能提示和类型检查:
将压缩包中路径为 libs/agora-rtm-sdk.d.ts
的文件保存到你所操作的项目下。
在你的 JS 或 TS 文件开头加入下面的注释(其中 path to the TS file
替换为 agora-rtm-sdk.d.ts
的路径):
/// <reference path="path to the TS file" />
在 package.json
中的 dependencies
字段中加入 agora-rtm-sdk
及对应版本:
{
"name": "web",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"agora-rtm-sdk": "latest"
},
"author": "",
"license": "ISC"
}
在你的 JS 或 TS 文件中导入 AgoraRTM
模块:
import AgoraRTM from 'agora-rtm-sdk'
index.html
的内容如下。<script src="./dist/bundle.js"></script>
用来引用 webpack 打包之后的bundle.js
文件。webpack 的配置会在后续步骤提及。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>RTM Quickstart</title>
<script src="./dist/bundle.js"></script>
</head>
<body>
<h2 class="left-align">RTM Quickstart</h5>
<form id="loginForm">
<div class="col" style="min-width: 433px; max-width: 443px">
<div class="card" style="margin-top: 0px; margin-bottom: 0px;">
<div class="row card-content" style="margin-bottom: 0px; margin-top: 10px;">
<div class="input-field">
<label>User ID</label>
<input type="text" placeholder="User ID" id="userID">
</div>
<div class="row">
<div>
<button type="button" id="login">LOGIN</button>
<button type="button" id="logout">LOGOUT</button>
</div>
</div>
<div class="input-field">
<label>Channel name: demoChannel</label>
</div>
<div class="row">
<div>
<button type="button" id="join">JOIN</button>
<button type="button" id="leave">LEAVE</button>
</div>
</div>
<div class="input-field channel-padding">
<label>Channel Message</label>
<input type="text" placeholder="channel message" id="channelMessage">
<button type="button" id="send_channel_message">SEND</button>
</div>
<div class="input-field">
<label>Peer Id</label>
<input type="text" placeholder="peer id" id="peerId">
</div>
<div class="input-field channel-padding">
<label>Peer Message</label>
<input type="text" placeholder="peer message" id="peerMessage">
<button type="button" id="send_peer_message">SEND</button>
</div>
</div>
</div>
</div>
</form>
<hr>
<div id="log"></div>
</body>
</html>
index.js
的内容如下。本文使用 import 的方法导入 SDK,并使用 webpack 对 JS 文件进行打包,以避免浏览器兼容性问题。你需要分别将代码中的 "<Your app ID>"
和 "<Your token>"
替换为你之前获取的 App ID 和 Token。
import AgoraRTM from 'agora-rtm-sdk'
// login 方法参数
let options = {
uid: "",
token: ""
}
// 你的 app ID
const appID = "<Your app ID>"
// 你的 token
options.token = "<Your token>"
// 初始化客户端
const client = AgoraRTM.createInstance(appID)
// 客户端事件监听
// 显示对端发送的消息
client.on('MessageFromPeer', function (message, peerId) {
document.getElementById("log").appendChild(document.createElement('div')).append("Message from: " + peerId + " Message: " + message)
})
// 显示连接状态变化
client.on('ConnectionStateChanged', function (state, reason) {
document.getElementById("log").appendChild(document.createElement('div')).append("State changed To: " + state + " Reason: " + reason)
})
let channel = client.createChannel("demoChannel")
channel.on('ChannelMessage', function (message, memberId) {
document.getElementById("log").appendChild(document.createElement('div')).append("Message received from: " + memberId + " Message: " + message)
})
// 显示频道
channel.on('MemberJoined', function (memberId) {
document.getElementById("log").appendChild(document.createElement('div')).append(memberId + " joined the channel")
})
// 频道成员
channel.on('MemberLeft', function (memberId) {
document.getElementById("log").appendChild(document.createElement('div')).append(memberId + " left the channel")
})
// 按钮行为定义
window.onload = function () {
// 按钮逻辑
// 登录
document.getElementById("login").onclick = async function () {
options.uid = document.getElementById("userID").value.toString()
await client.login(options)
}
// 登出
document.getElementById("logout").onclick = async function () {
await client.logout()
}
// 创建并加入频道
document.getElementById("join").onclick = async function () {
// Channel event listeners
// Display channel messages
await channel.join().then (() => {
document.getElementById("log").appendChild(document.createElement('div')).append("You have successfully joined channel " + channel.channelId)
})
}
// 离开频道
document.getElementById("leave").onclick = async function () {
if (channel != null) {
await channel.leave()
}
else
{
console.log("Channel is empty")
}
}
// 发送点对点消息
document.getElementById("send_peer_message").onclick = async function () {
let peerId = document.getElementById("peerId").value.toString()
let peerMessage = document.getElementById("peerMessage").value.toString()
await client.sendMessageToPeer(
{ text: peerMessage },
peerId,
).then(sendResult => {
if (sendResult.hasPeerReceived) {
document.getElementById("log").appendChild(document.createElement('div')).append("Message has been received by: " + peerId + " Message: " + peerMessage)
} else {
document.getElementById("log").appendChild(document.createElement('div')).append("Message sent to: " + peerId + " Message: " + peerMessage)
}
})
}
// 发送频道消息
document.getElementById("send_channel_message").onclick = async function () {
let channelMessage = document.getElementById("channelMessage").value.toString()
if (channel != null) {
await channel.sendMessage({ text: channelMessage }).then(() => {
document.getElementById("log").appendChild(document.createElement('div')).append("Channel message: " + channelMessage + " from " + channel.channelId)
}
)
}
}
}
本文使用 webpack 对项目进行打包,并使用 webpack-dev-server
运行项目。
在 package.json
的 dependencies
字段中添加 webpack
,webpack-cli
,webpack-dev-server
。并在 scripts
字段中增加 build
和 start:dev
命令。
{
"name": "web",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack --config webpack.config.js",
"start:dev": "webpack serve --open --config webpack.config.js"
},
"dependencies": {
"agora-rtm-sdk": "latest",
"webpack": "5.28.0",
"webpack-dev-server": "3.11.2",
"webpack-cli": "4.5.0"
},
"author": "",
"license": "ISC"
}
在项目根目录添加 webpack.config.js
文件,用于配置 webpack。文件内容如下:
const path = require('path');
module.exports = {
entry: './index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, './dist'),
},
devServer: {
compress: true,
port: 9000
}
};
此时你的目录中包含以下文件:
RTM_quickstart
├─ index.html
├─ index.js
├─ package.json
└─ webpack.config.js
在项目根目录运行以下命令,安装依赖项。
$ npm install
运行以下命令使用 webpack 构建并运行项目。
# 使用 webpack 打包
$ npm run build
# 使用 webpack-dev-server 运行项目
$ npm run start:dev
运行成功后,你可以发送和接收点对点消息和频道消息。
RTM 支持多个相互独立的 RtmClient 实例。
在收发点对点消息或进行其他频道操作前,请确保你已成功登录 Agora RTM 系统。
使用频道核心功能前必须通过调用 createChannel 方法创建频道实例。
你可以创建多个 RtmClient 客户端实例,但是每个客户端实例最多只能同时加入 20 个频道。每个频道的 channelId
参数应该不同。
当你不再使用某个实例时,可以通过调用继承的 removeAllListeners
方法删除它的所有监听函数。
接收到的 RtmMessage 消息对象不能重复利用再用于消息发送。