本指南介绍如何使用 Cloudflare RealtimeKit Core SDK 在会议中注册、激活和渲染插件。
插件是运行在会议内部的交互式实时应用程序,例如共享白板或文档查看器。当参与者激活某个插件时,它会对会话中的每个人都变为活动状态。
会议插件对象可在 meeting.plugins 处获取。它公开了 Plugin 对象的两个集合:
all:本地参与者可用的每个插件。active:当前在会话中运行的插件。
// 所有对您可用的插件
const allPlugins = meeting.plugins.all.toArray();
// 当前在会话中处于活动状态的插件
const activePlugins = meeting.plugins.active.toArray();
// 通过 id 获取单个插件
const plugin = meeting.plugins.all.get(pluginId);使用 useRealtimeKitSelector hook 响应式地读取插件。该 hook 仅在您的组件树包裹在 RealtimeKitProvider 中时才起作用。
import { useRealtimeKitSelector } from "@cloudflare/realtimekit-react";
const allPlugins = useRealtimeKitSelector((m) => m.plugins.all.toArray());
const activePlugins = useRealtimeKitSelector((m) => m.plugins.active.toArray());// 所有对您可用的插件
val allPlugins = meeting.plugins.all
// 当前在会话中处于活动状态的插件
val activePlugins = meeting.plugins.active
// 通过 id 获取单个插件
val plugin = meeting.plugins.all.firstOrNull { it.id == pluginId }// 所有对您可用的插件
let allPlugins = meeting.plugins.all
// 当前在会话中处于活动状态的插件
let activePlugins = meeting.plugins.active
// 通过 id 获取单个插件
let plugin = meeting.plugins.all.first { $0.id == pluginId }使用 useRealtimeKitSelector hook 响应式地读取插件。
import { useRealtimeKitSelector } from "@cloudflare/realtimekit-react-native";
const allPlugins = useRealtimeKitSelector((m) => m.plugins.all.toArray());
const activePlugins = useRealtimeKitSelector((m) => m.plugins.active.toArray());
// 通过其命名空间 id 获取单个插件
const plugin = useRealtimeKitSelector((m) => m.plugins.all.get(pluginId));在初始化 SDK 时,您需要注册会话中可用的插件。每个配置提供了 RealtimeKit 用来列出该插件的元数据以及它加载的位置。
将插件配置数组作为 defaults.plugins 传入。每个配置提供了 RealtimeKit 用来列出该插件的元数据以及它渲染的 component。
RealtimeKitClient.init({
authToken: "<auth_token>",
defaults: {
plugins: [
{
// 用户提供的唯一 id。SDK 会为其加上前缀
// `{meetingId}:` 以创建带有命名空间的 `plugin.id`。
id: "whiteboard",
// 插件面板中显示的显示名称
name: "Whiteboard",
// 显示在名称旁边的图标 URL 或数据 URI
icon: "https://example.com/whiteboard.png",
// 本地参与者针对每个插件的权限
permissions: {
canActivate: true,
canDeactivate: true,
},
// 插件处于活动状态时渲染的元素
component: document.createElement("my-whiteboard"),
},
],
},
});component 是一个 HTMLElement。rtk-plugin-main 组件会将其投影到会议布局中,因此您的应用程序样式将继续适用。
每个插件配置都接受以下字段:
| 字段 | 描述 | 类型 | 是否必填 |
|---|---|---|---|
id |
插件的唯一标识符。SDK 会为其加上前缀 {meetingId}: 以形成 plugin.id。 |
string |
是 |
name |
插件面板中显示的显示名称。 | string |
是 |
icon |
显示在名称旁边的图标 URL 或数据 URI。 | string |
是 |
permissions |
控制本地参与者是否可以激活或停用该插件。 | { canActivate: boolean; canDeactivate: boolean } |
是 |
component |
插件处于活动状态时渲染的元素。 | HTMLElement |
是 |
调用 initMeeting 时,将插件配置作为 defaults.plugins 传入。在 React Native 中,component 应该是一个带有 src 属性的对象,其中包含要渲染的 URL —— 您可以在 WebView 中加载它,或使用 UI Kit 来自动处理渲染。
const [meeting, initMeeting] = useRealtimeKitClient();
await initMeeting({
authToken: "<auth_token>",
defaults: {
plugins: [
{
// 用户提供的唯一 id。SDK 会为其加上前缀
// `{meetingId}:` 以创建带有命名空间的 `plugin.id`。
id: "whiteboard",
// 插件面板中显示的显示名称
name: "Whiteboard",
// 显示在名称旁边的图标 URL
icon: "https://example.com/whiteboard.png",
// 本地参与者针对每个插件的权限
permissions: {
canActivate: true,
canDeactivate: true,
},
// 插件处于活动状态时要渲染的 URL。
// 传入一个带有 src 属性的对象:{ src: string }。
component: { src: "https://example.com/whiteboard/" },
},
],
},
});每个插件配置都接受以下字段:
| 字段 | 描述 | 类型 | 是否必填 |
|---|---|---|---|
id |
插件的唯一标识符。SDK 会为其加上前缀 {meetingId}: 以形成 plugin.id。 |
string |
是 |
name |
插件面板中显示的显示名称。 | string |
是 |
icon |
显示在名称旁边的图标 URL。 | string |
是 |
permissions |
控制本地参与者是否可以激活或停用该插件。 | { canActivate: boolean; canDeactivate: boolean } |
是 |
component |
插件处于活动状态时用于渲染的带有 src URL 的对象。 |
{ src: string } |
是 |
将 pluginConfigs 列表传递给 RtkMeetingInfo。当激活插件时,SDK 会直接将每个插件的 url 加载到 WebView 中。
val meetingInfo = RtkMeetingInfo(
authToken = "<auth_token>",
pluginConfigs = listOf(
RtkClientPluginConfig(
// 用户提供的唯一 id。SDK 会为其加上前缀
// `{meetingId}:` 以创建带有命名空间的 `plugin.id`。
id = "whiteboard",
// 插件列表中显示的显示名称
name = "Whiteboard",
// 显示在名称旁边的图标 URL
icon = "https://example.com/whiteboard.png",
// 插件处于活动状态时加载到插件 WebView 中的 URL
url = "https://example.com/whiteboard/",
// 本地参与者针对每个插件的权限
permissions = RtkClientPluginPermissions(
canActivate = true,
canDeactivate = true,
),
),
),
)每个插件配置都接受以下字段:
| 字段 | 描述 | 类型 | 是否必填 |
|---|---|---|---|
id |
插件的唯一标识符。SDK 会为其加上前缀 {meetingId}: 以形成 plugin.id。 |
String |
是 |
name |
插件列表中显示的显示名称。 | String |
是 |
icon |
显示在名称旁边的图标 URL。 | String |
是 |
url |
插件处于活动状态时加载到插件 WebView 中的 URL。 | String |
是 |
permissions |
控制本地参与者是否可以激活或停用该插件。 | RtkClientPluginPermissions |
是 |
将 pluginConfigs 数组传递给 RtkMeetingInfo。当激活插件时,SDK 会直接将每个插件's url 加载到 WebView 中。
let meetingInfo = RtkMeetingInfo(
authToken: "<auth_token>",
pluginConfigs: [
RtkClientPluginConfig(
// 用户提供的唯一 id。SDK 会为其加上前缀
// `{meetingId}:` 以创建带有命名空间的 `plugin.id`。
id: "whiteboard",
// 插件列表中显示的显示名称
name: "Whiteboard",
// 显示在名称旁边的图标 URL
icon: "https://example.com/whiteboard.png",
// 插件处于活动状态时加载到插件 WebView 中的 URL
url: "https://example.com/whiteboard/",
// 本地参与者针对每个插件的权限
permissions: RtkClientPluginPermissions(
canActivate: true,
canDeactivate: true
)
)
]
)每个插件配置都接受以下字段:
| 字段 | 描述 | 类型 | 是否必填 |
|---|---|---|---|
id |
插件的唯一标识符。SDK 会为其加上前缀 {meetingId}: 以形成 plugin.id。 |
String |
是 |
name |
插件列表中显示的显示名称。 | String |
是 |
icon |
显示在名称旁边的图标 URL。 | String |
是 |
url |
插件处于活动状态时加载到插件 WebView 中的 URL。 | String |
是 |
permissions |
控制本地参与者是否可以激活或停用该插件。 | RtkClientPluginPermissions |
是 |
激活操作位于 Plugin 对象上。调用 activate() 会为会话中的每个参与者启用该插件,而 deactivate() 会为每个人停用它。这两种方法都遵循插件的 permissions。
const plugin = meeting.plugins.all.get(pluginId);
// 为所有参与者激活
await plugin.activate();
// 为所有参与者停用
await plugin.deactivate();const plugins = useRealtimeKitSelector((m) => m.plugins);
const plugin = plugins.all.get(pluginId);
// 为所有参与者激活
await plugin.activate();
// 为所有参与者停用
await plugin.deactivate();val plugin = meeting.plugins.all.firstOrNull { it.id == pluginId } ?: return
// 为所有参与者激活
plugin.activate()
// 为所有参与者停用
plugin.deactivate()guard let plugin = meeting.plugins.all.first(where: { $0.id == pluginId }) else { return }
// 为所有参与者激活
plugin.activate()
// 为所有参与者停用
plugin.deactivate()Plugin 对象代表单个插件。您可以从 meeting.plugins 中的任意集合获取它。
| 属性 | 描述 | 类型 |
|---|---|---|
id |
命名空间插件 id,格式为 {meetingId}:{configId}。 |
string |
name |
插件的显示名称。 | string |
icon |
图标 URL 或数据 URI。 | string |
permissions |
本地参与者的激活权限。 | { canActivate: boolean; canDeactivate: boolean } |
component |
插件处于活动状态时渲染的元素。 | HTMLElement |
active |
插件当前是否正在运行。 | boolean |
enabledBy |
激活该插件的参与者。 | string |
| 属性 | 描述 | 类型 |
|---|---|---|
id |
命名空间插件 id,格式为 {meetingId}:{configId}。 |
String |
name |
插件的显示名称。 | String |
icon |
图标 URL。 | String |
permissions |
本地参与者的激活权限。 | RtkClientPluginPermissions |
当插件处于活动状态时,调用 getPluginView() 以获取承载它的 Android WebView,并调用 sendData(eventName, data) 向该 WebView 推送数据。
| 属性 | 描述 | 类型 |
|---|---|---|
id |
命名空间插件 id,格式为 {meetingId}:{configId}。 |
String |
name |
插件的显示名称。 | String |
icon |
图标 URL。 | String |
permissions |
本地参与者的激活权限。 | RtkClientPluginPermissions |
当插件处于活动状态时,调用 getPluginView() 以获取承载它的 WKWebView,并调用 sendData(eventName:data:) 向该 WebView 推送数据。
| 属性 | 描述 | 类型 |
|---|---|---|
id |
命名空间插件 id,格式为 {meetingId}:{configId}。 |
string |
name |
插件的显示名称。 | string |
icon |
图标 URL。 | string |
permissions |
本地参与者的激活权限。 | { canActivate: boolean; canDeactivate: boolean } |
component |
注册时提供的对象。包含渲染层加载的 src URL。 |
{ src: string } |
active |
插件当前是否正在运行。 | boolean |
enabledBy |
激活该插件的参与者的 Id。 | string |
Plugin 对象在状态更改时会触发事件。您可以监听单个插件,也可以在映射(map)上监听以接收其中每个插件的事件。
| 事件 | 描述 |
|---|---|
stateUpdate |
在激活或停用插件时触发。 |
enabled |
当插件对本地参与者变为活动状态时触发。 |
closed |
当插件对本地参与者被停用时触发。 |
ready |
当插件准备就绪可用时触发。 |
const plugin = meeting.plugins.all.get(pluginId);
plugin.on("stateUpdate", ({ active, pluginId }) => {
console.log(`Plugin ${pluginId} active:`, active);
});
// 监听任何被添加到映射中或从映射中移除的插件
meeting.plugins.all.on("pluginAdded", (plugin) => {
console.log("已添加插件:", plugin.name);
});
meeting.plugins.all.on("pluginDeleted", (plugin) => {
console.log("已移除插件:", plugin.name);
});注册 RtkPluginsEventListener 以接收插件事件。
| 回调 | 描述 |
|---|---|
onPluginActivated |
当为所有参与者激活插件时调用。 |
onPluginDeactivated |
当为所有参与者停用插件时调用。 |
onPluginMessage |
当插件向应用发送消息时调用。 |
onPluginFileRequest |
当插件向应用请求文件时调用。 |
val pluginsEventListener = object : RtkPluginsEventListener {
override fun onPluginActivated(plugin: RtkPlugin) {
// 一个插件对所有参与者变为活动状态
}
override fun onPluginDeactivated(plugin: RtkPlugin) {
// 一个插件对所有参与者被停用
}
override fun onPluginMessage(plugin: RtkPlugin, eventName: String, data: Any?) {
// 一个插件向应用发送了消息
}
override fun onPluginFileRequest(plugin: RtkPlugin) {
// 一个插件向应用请求了文件
}
}
meeting.addPluginsEventListener(pluginsEventListener)遵守 RtkPluginsEventListener 协议并注册该监听器以接收插件事件。
| 回调 | 描述 |
|---|---|
onPluginActivated |
当为所有参与者激活插件时调用。 |
onPluginDeactivated |
当为所有参与者停用插件时调用。 |
onPluginMessage |
当插件向应用发送消息时调用。 |
onPluginFileRequest |
当插件向应用请求文件时调用。 |
extension MeetingViewModel: RtkPluginsEventListener {
func onPluginActivated(plugin: RtkPlugin) {
// 一个插件对所有参与者变为活动状态
}
func onPluginDeactivated(plugin: RtkPlugin) {
// 一个插件对所有参与者被停用
}
func onPluginMessage(plugin: RtkPlugin, eventName: String, data: Any?) {
// 一个插件向应用发送了消息
}
func onPluginFileRequest(plugin: RtkPlugin) {
// 一个插件向应用请求了文件
}
}
meeting.addPluginsEventListener(self)如果您使用 UI Kit,RealtimeKit 为插件提供了现成的组件:
rtk-plugins-toggle:打开和关闭插件侧边栏的控制栏按钮。rtk-plugins:包含可用插件的列表,附带激活或停用每个插件的控件。rtk-plugin-main:在会议布局中渲染活动插件的component。
这些组件会读取 meeting.plugins 的内容,因此一旦您在初始化时注册了插件,它们就会自动反映插件的状态。
当插件处于活动状态时,getPluginView() 会返回承载它的 Android WebView。将此视图添加到您的布局中即可显示该插件。
val plugin = meeting.plugins.active.firstOrNull() ?: return
// 返回一个您可以添加到布局中的 Android WebView
val pluginView = plugin.getPluginView()当插件处于活动状态时,getPluginView() 会返回承载它的 WKWebView。将此视图添加到您的视图层级中即可显示该插件。
guard let plugin = meeting.plugins.active.first else { return }
// 返回一个您可以添加到视图层级中的 WKWebView
let pluginView = plugin.getPluginView()React Native UI Kit 为插件提供了现成的组件:
RtkPluginsToggle:打开和关闭插件侧边栏的控制栏按钮。RtkPlugins:列出可用插件并附带激活或停用每个插件的控件的面板。RtkPluginMain:在WebView中渲染活动插件。
一旦在初始化时注册了插件,这些组件就会自动读取 meeting.plugins。如果您使用 RtkMeeting,插件 UI 无需任何额外设置即可包含在内。