加入白板房间
- Android
更新时间不可用
了解如何快速接入互动白板 SDK,完成环境准备、参数配置、示例运行和核心流程验证。
声网互动白板房间提供丰富的编辑工具,支持展示静态图片、动态 PPT、H5 课件等多种格式的文件,不同终端用户能在白板上实时展示想法,轻松实现多人互动协作。本文介绍如何建立一个简单的项目,使用声网互动白板 SDK 加入房间并实现基础的白板功能。
技术原理
下图展示了加入声网互动白板房间的基本流程。
当你的 App 客户端请求加入互动白板房间时:
- 你的 App 服务端使用 SDK Token 向声网互动白板服务端发起创建房间的请求。
- 成功创建房间后,声网互动白板服务端向你的 App 服务端返回新建房间的房间 UUID。
- 你的 App 服务端使用房间 UUID 生成 room Token,并将房间 UUID 和 room Token 发送给 App 客户端。
- App 客户端使用从声网控制台获取的 AppIdentifier 初始化互动白板 SDK 实例。
- App 客户端调用 SDK 的方法并传入房间 UUID 和 room Token 以加入互动白板房间。
前提条件
- Android Studio
- Android SDK API level 21+
- 有效的声网开发者账号。
- 已在声网控制台开启互动白板服务并获取白板项目的 AppIdentifier 和 SDK Token。
创建 Android 项目
使用 Android Studio 创建一个 Android 项目。
- 项目名设为
WhiteBoard。 - Package 名设为
com.example.whiteboard。 - Activity 类型选择 Empty Activity。
- Minimum SDK 选择 API 21。
添加权限
在 AndroidManifest.xml 文件中添加访问网络权限:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.whiteboard">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.WhiteBoard">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>获取 SDK
打开根目录下的 build.gradle 进行以下配置:
allprojects {
repositories {
google()
mavenCentral()
// 添加以下内容
maven { url 'https://jitpack.io' }
// 对于国内用户,如果 Gradle sync 失败,可以选择国内镜像,例如阿里云 Maven 镜像
maven { url 'https://maven.aliyun.com/nexus/content/repositories/releases/'}
}
}然后打开 app 目录下的 build.gradle 进行如下配置:
dependencies {
// 当前正式版
implementation 'com.github.netless-io:whiteboard-android:2.16.134'
}关于声网互动白板 SDK 的最新版本,详见发版说明。
防止代码混淆
在 proguard-rules.pro 文件中添加以下语句,防止代码混淆:
# SDK model
-keep class com.herewhite.** { *; }实现步骤
现在,我们已经将声网互动白板 SDK 集成到项目中了。接下来我们要调用声网互动白板 SDK 提供的核心 API 实现基础的白板功能。
1. 创建房间
在 App 客户端加入互动白板房间前,你需要在 App 服务端调用互动白板服务端 RESTful API 创建一个房间。详见创建房间(POST)。
请求示例
你可以使用以下 Node.js 脚本发送请求:
信息
使用 Node.js 发送 HTTP 请求前安装 request 模块。你可以运行 npm install request 安装。
var request = require("request");
var options = {
method: "POST",
url: "https://api.netless.link/v5/rooms",
headers: {
"token": "你的 SDK Token",
"Content-Type": "application/json",
"region": "cn-hz",
},
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});如果方法调用成功,声网互动白板服务端将返回新建房间的信息,其中的 uuid 是房间的唯一标识,App 客户端加入房间时需要传入该参数。
响应示例
{
"uuid": "4a50xxxxxx796b", // 房间的 UUID
"teamUUID": "RMmLxxxxxx15aw",
"appUUID": "i54xxxxxx1AQ",
"isRecord": true,
"isBan": false,
"createdAt": "2021-01-18T06:56:29.432Z",
"limit": 0
}2. 生成 Room Token
创建房间并获取新建房间的 uuid 后,你需要在 App 服务端生成 Room Token 并下发给 App 客户端。当 App 客户端加入房间时,声网互动白板服务端会使用该 Token 对其鉴权。
你可以通过以下方式在 App 服务端生成 Room Token:
- 使用代码生成 Room Token,详见在 App 服务端生成 Token。(推荐)
- 调用互动白板服务端 RESTful API 生成 Room Token,详见生成 Room Token(POST)。
下面以调用 RESTful API 的方式为例介绍如何生成 Room Token。
请求示例
你可以使用以下 Node.js 脚本发送请求:
信息
使用 Node.js 发送 HTTP 请求前安装 request 模块。你可以运行 npm install request 安装。
var request = require("request");
var options = {
method: "POST",
// 将 <房间的 UUID> 替换成你的房间 UUID
url: "https://api.netless.link/v5/tokens/rooms/<房间的 UUID>",
headers: {
"token": "你的 SDK Token",
"Content-Type": "application/json",
"region": "cn-hz",
},
body: JSON.stringify({ lifespan: 3600000, role: "admin" }),
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});如果方法调用成功,声网互动白板服务端将返回生成的 Room Token。
响应示例
"NETLESSROOM_YWs9XXXXXXXXXXXZWNhNjk" // Room Token3. 创建 UI
修改 activity_main.xml 为如下内容,可以看到整个视图由一个白板页面填充,页面 com.herewhite.sdk.WhiteboardView 由互动白板 SDK 实现。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<com.herewhite.sdk.WhiteboardView
android:id="@+id/white"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible" />
</LinearLayout>4. 初始化 SDK 并加入房间
编辑 MainActivity.java,实现从初始化 SDK 到加入房间的基本操作。你需要传入以下参数:
appId:互动白板项目的 AppIdentifier。详见获取 AppIdentifier。uuid:房间的 UUID。详见创建房间。uid:用户的唯一标识符,字符串格式,长度不能超过 1024 字节。如果你使用 2.15.0 或之后版本的 SDK,必须传入该参数;如果你使用 2.15.0 之前版本的 SDK,则不需要传入该参数。roomToken:用于鉴权的 Room Token。生成该 Room Token 使用的房间 UUID 必须和上面的房间 UUID 一致。详见生成 Room Token。region:数据中心,必须和创建房间时设置的数据中心一致。
package com.example.whiteboard;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import com.herewhite.sdk.Room;
import com.herewhite.sdk.RoomListener;
import com.herewhite.sdk.RoomParams;
import com.herewhite.sdk.WhiteSdk;
import com.herewhite.sdk.WhiteSdkConfiguration;
import com.herewhite.sdk.WhiteboardView;
import com.herewhite.sdk.domain.MemberState;
import com.herewhite.sdk.domain.Promise;
import com.herewhite.sdk.domain.Region;
import com.herewhite.sdk.domain.RoomPhase;
import com.herewhite.sdk.domain.RoomState;
import com.herewhite.sdk.domain.SDKError;
import com.herewhite.sdk.domain.WindowParams;
public class MainActivity extends AppCompatActivity {
private WhiteboardView whiteboardView;
private WhiteSdk whiteSdk;
private Room room;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
whiteboardView = findViewById(R.id.white);
WhiteSdkConfiguration config = new WhiteSdkConfiguration("APP_IDENTIFIER", true);
config.setRegion(Region.cn);
// 同一房间各端一致使用高性能绘制插件。
config.setUseMultiViews(true);
config.setEnableAppliancePlugin(true);
whiteSdk = new WhiteSdk(whiteboardView, this, config);
RoomParams params = new RoomParams("ROOM_UUID", "ROOM_TOKEN", "CLIENT_UID");
params.setRegion(Region.cn);
params.setWritable(true);
params.setWindowParams(new WindowParams());
RoomListener listener = new RoomListener() {
@Override public void onPhaseChanged(RoomPhase phase) { }
@Override public void onDisconnectWithError(Exception error) { }
@Override public void onKickedWithReason(String reason) { }
@Override public void onRoomStateChanged(RoomState modifyState) { }
@Override public void onCanUndoStepsUpdate(long canUndoSteps) { }
@Override public void onCanRedoStepsUpdate(long canRedoSteps) { }
@Override public void onCatchErrorWhenAppendFrame(long userId, Exception error) { }
};
whiteSdk.joinRoom(params, listener, new Promise<Room>() {
@Override public void then(Room joinedRoom) {
room = joinedRoom;
MemberState state = new MemberState();
state.setCurrentApplianceName("pencil");
state.setStrokeColor(new int[]{255, 0, 0});
room.setMemberState(state);
}
@Override public void catchEx(SDKError error) {
Log.e("Whiteboard", error.getMessage());
}
});
}
private boolean leaving;
@Override
public void onBackPressed() {
if (leaving) return;
if (whiteSdk == null) { finish(); return; }
leaving = true;
whiteSdk.leaveRoom(new Promise<Object>() {
@Override public void then(Object completion) {
// 仅通知退房完成;不是房间状态快照。
room = null;
whiteSdk.releaseRoom();
finish(); // onDestroy 再销毁 View。
}
@Override public void catchEx(SDKError error) {
leaving = false;
Log.e("Whiteboard", "退出失败,请重试", error);
}
});
}
@Override
protected void onDestroy() {
// 正常退出已在 onBackPressed 等待;系统强制销毁不提供异步等待窗口。
if (whiteboardView != null) whiteboardView.destroy();
super.onDestroy();
}
}5. 接入多窗口
SDK 已通过内嵌 Bridge 集成 Window Manager。创建 WhiteSdk 前启用多 View,入房前将窗口配置传给 RoomParams;步骤 4 的完整示例已包含这些配置:
import com.herewhite.sdk.domain.WindowParams;
// 创建 WhiteSdk 前设置。
config.setUseMultiViews(true);
// joinRoom 前设置;WindowParams 可进一步配置窗口显示。
params.setWindowParams(new WindowParams());入房成功后,SDK 自动在 WhiteboardView 内挂载窗口管理器。窗口配置和课件控制见统一页面控制。
6. 接入动态 PPT
内嵌 Bridge 已注册 app-slide。业务服务端完成动态 PPT 转换后,在入房成功回调中,或其后的业务按钮中,用 WindowAppParam.createSlideApp 创建参数,再调用 room.addApp:
import com.herewhite.sdk.domain.WindowAppParam;
import com.herewhite.sdk.domain.Promise;
import com.herewhite.sdk.domain.SDKError;
WindowAppParam slide = WindowAppParam.createSlideApp(
"CONVERSION_TASK_UUID",
"https://convertcdn.netless.link/dynamicConvert",
"教学课件.pptx"
);
room.addApp(slide, new Promise<String>() {
@Override public void then(String appId) {
android.util.Log.i("Whiteboard", "动态 PPT 窗口 ID:" + appId);
}
@Override public void catchEx(SDKError error) {
android.util.Log.e("Whiteboard", error.getMessage());
}
});第一个参数是转换任务 UUID,第二个参数是转换结果的资源地址前缀,末尾不带 /,不能填写 PPT 源文件地址。此工厂方法为窗口生成独立场景目录。创建 App 需要可写权限;房间中已存在的课件会同步显示,不要在每次入房时重复插入。返回窗口 ID 不表示课件资源和首帧全部加载完成。更多说明见展示文件。
7. 开启新教具
创建 WhiteSdk 前同时开启多 View 与新教具;步骤 4 的示例已开启:
config.setUseMultiViews(true);
config.setEnableAppliancePlugin(true);SDK 已内嵌 Appliance Plugin 与 Worker 资源,业务继续使用 room.setMemberState 等原生 API 切换 Pencil、Selector、Eraser、Shape、Text 等教具,无需额外安装或注册 Web 插件。同一房间各端应一致启用。
入房前可通过 RoomParams.appliancePluginOptions 设置教具插件参数。自定义教具、背景图和 Auto Shape 接入见教具插件介绍与启用。
WhiteSdkConfiguration 的初始化开关需在 SDK 创建前设置,入房后不能通过修改此对象启用新教具。SDK 初始化错误通过 CommonCallback.sdkSetupFail 处理。
编译并运行项目
在 Android Studio 中编译并在模拟器或真机上运行项目。入房成功后可在白板上书写,业务按钮可通过步骤 6 的原生 API 打开动态 PPT。
配置远端参数
需要在入房前读取远端参数时,参见动态配置。地址在创建 SDK 前设置,本地显式参数优先;读取失败回退本地参数。