- 实时交互白板的Android版SDK
implementation (name:'qndroid-whiteboard-xxx',ext:"aar") //白板
implementation("com.squareup.okhttp3:okhttp:x.x.x")//需要依赖okhttp
implementation ('com.aliyun.dpa:oss-android-sdk:x.x.x')
android {
defaultConfig{
// 当前仅支持arm架构
ndk {
abiFilters 'armeabi-v7a' , 'arm64-v8a'
}
}
}
- SDK需要在
Application
中初始化一次
class MyApplication : Application(){
override fun onCreate() {
super.onCreate()
QNWhiteBoard.init(this)
}
}
白板的activity的layout文件中引入com.qiniu.droid.whiteboard.QNWhiteBoardView
控件,
控件大小最好与用户设定的白板宽高比相同,否则边缘可能会留白。
例如:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
...
<com.qiniu.droid.whiteboard.QNWhiteBoardView
android:id="@+id/white_board"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="2048:1440"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/horizontalScrollView" />
</androidx.constraintlayout.widget.ConstraintLayout>
实例中通过app:layout_constraintDimensionRatio
参数设定宽高比,比例中的数字时白板的虚拟大小,决定了白板中内容的坐标系。
首先访问自己的服务器获取要加入的白板房间的token(和rtc使用同一个token)参数(房间的创建和token的生成由服务器对接SDK服务端接口)。
如果您还不知道如何生成 RoomToken,请先阅读 七牛实时音视频云接入指南
首先构建进房参数JoinConfig
,然后执行QNWhiteBoard.joinRoom
来加入房间。
val config = JoinConfig(
token //通过后台取到的房间token
).apply {
widthHeightThan=0.5 //白板宽高比 范围[0.5,2.2] 默认0.5
roleId = 6 // 由用户设定的值,指示本用户在房间中的角色,
// 方便用户实现自己的权限管理,默认为0
sessionId = "xxxx" // 如果用户的业务系统支持单用户多点登录并进入同一个白板房间,
// 那么这个id就是全局唯一的用户标识,此时[userId]可能有相同值,
// 但是[sessionId]必须唯一。可空,留空时sdk会自动生成一个随机id。
nickname = "xxx" // 本用户在房间中的昵称,可空。
avatar = "http://xxxx/ssss.jpg" // 本用户在房间中的头像地址,可空。
}
QNWhiteBoard.joinRoom(config);
如果加入房间成功,会收到onJoinSuccess
回调,如果加入失败会收到onJoinFailed
回调。
房间关闭时,比如离开房间的Activity
时,必须调用leaveRoom来退出房间并释放资源,
此方法会同时完成离开房间和资源释放,同时可以自动释放QNAutoRemoveWhiteBoardListener类型的事件监听器(推荐),多次执行是安全的。
通常情况会把它放在Activity.onDestroy
中执行,比如:
override fun onDestroy() {
WhiteBoard.leaveRoom()
super.onDestroy()
}
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/restore"
style="@style/WhiteBoardActionButton"
android:tint="?attr/colorOnPrimary"
app:backgroundTint="?attr/colorSecondary"
app:srcCompat="@drawable/ic_baseline_undo_24"
app:visibleGone="@{viewModel.canRecovery}" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/select"
style="@style/WhiteBoardActionButton"
app:selected="@{viewModel.currentInputType == InputType.SELECT}"
app:srcCompat="@drawable/ic_selection" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/pen"
style="@style/WhiteBoardActionButton"
android:tint="@{viewModel.normalPenStyle.Companion.colors[viewModel.normalPenStyle.colorIndex]}"
app:selected="@{viewModel.currentInputType == InputType.NORMAL}"
app:srcCompat="@drawable/ic_pen_normal" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/mark"
style="@style/WhiteBoardActionButton"
android:tint="@{viewModel.markPenStyle.Companion.colors[viewModel.markPenStyle.colorIndex]}"
app:selected="@{viewModel.currentInputType == InputType.MARK}"
app:srcCompat="@drawable/ic_pen_mark" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/eraser"
style="@style/WhiteBoardActionButton"
app:selected="@{viewModel.currentInputType == InputType.ERASE}"
app:srcCompat="@drawable/ic_eraser" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/laser"
style="@style/WhiteBoardActionButton"
app:selected="@{viewModel.currentInputType == InputType.LASER}"
app:srcCompat="@drawable/ic_pen_laser" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/geometry"
style="@style/WhiteBoardActionButton"
app:selected="@{viewModel.currentInputType == InputType.GEOMETRY}"
app:srcCompat="@drawable/ic_geometry" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/insert_file"
style="@style/WhiteBoardActionButton"
app:srcCompat="@drawable/ic_file_upload" />
</LinearLayout>
.....
//选择笔
inputPen.setOnClickListener((View.OnClickListener) v -> {
//todo 选择笔型号 笔颜色 大小
QNWhiteBoard.setInputMode(InputConfig.pen(17, Color.parseColor("#22ddff")))
});
//插入文件
inputFile.setOnClickListener((View.OnClickListener) v -> { //选择文件
String path = selectFile();
// 插入文件
QNWhiteBoard.insertFile(new FileConfig(File(path)));
});
//使用橡皮
inputErase.setOnClickListener((View.OnClickListener) v -> {
//todo 选择橡皮大小
QNWhiteBoard.setInputMode(InputConfig.erase(12));
});
//撤销
mWhiteBoardViewControllerView.recover.setOnClickListener((View.OnClickListener) v -> {
QNWhiteBoard.recover();
});
QNWhiteBoard.getInstance().addListener(new QNAutoRemoveWhiteBoardListener() {
@Override
public void onJoinSuccess(@NonNull Room var1, @NonNull RoomMember var2) {
//白板房间加入成功
}
@Override
public void onJoinFailed(int var1) {
//白板加入失败
}
@Override
public void onBoardSizeChanged(@NonNull WhiteBoardViewport viewport) {
int width = viewport.size.displayWidth;
int height = viewport.size.displayHeight;
//todo 根据白板ui尺寸变化跟新显示UI样式
}
@Override
public void onWidgetActive(@Nullable ActiveWidgetInfo activeWidgetInfo) {
//用户书写或操作白板时会激活被操作的widget,同时触发此事件
//todo 跟新自定义显示UI
mWhiteBoardViewControllerView.onWidgetActive(activeWidgetInfo);
}
@Override
public void onFilePageChanged(@NonNull ActiveWidgetInfo activeWidgetInfo) {
//当文件被翻页时触发,同时会触发onWidgetActive。 当前仅被激活的文件发生翻页时才会收到此事件
// todo 跟新自定义显示UI
mWhiteBoardViewControllerView.onFilePageChanged(activeWidgetInfo);
}
@Override
public void onWidgetActionEvent(@NonNull WidgetActionEvent var1) {
//widget被执行了某些关键动作
//比如有人插入文件或删除文件会收到此事件。 同时每个远端用户的文件加载情况也会触发此事件,通过此事件可以观察到每个人文件加载成功或失败情况。
// todo 跟新自定义显示UI
mWhiteBoardViewControllerView.onFilePageChanged(activeWidgetInfo);
}
....
});
- 所有用户可以主动调用的方法都是QNWhiteBoard类的静态方法
方法名称 | 方法描述 |
---|---|
init | 初始化白板SDK |
joinRoom | 进入白板房间 |
leaveRoom | 离开白板房间 |
addListener | 添加一个白板事件监听器 |
removeListener | 移除一个白板事件监听器 |
clearListener | 清空所有白板监听器 |
- 所有用户可以主动调用的方法都是QNWhiteBoard类的静态方法
方法名称 | 方法描述 |
---|---|
setDefaultInputMode | 设置白板的默认初始输入模式配置 |
setRetry | 设置白板断线自动重连次数 |
setInputMode | 改变白板的输入模式 |
setBackgroundColor | 设置白板背景色 |
scroll | 垂直滚动白板显示区 |
newBoardPage | 新建白板页 |
insertBoardPage | 插入新白板页 |
jumpBoardPage | 跳转到目标白板页 |
preBoardPage | 后退到上一页 |
nextBoardPage | 前进到下一页 |
deleteBoardPage | 删除白板页 |
insertFile | 向当前白板页中插入文件 |
jumpFilePage | 文件翻页 |
deleteFile | 删除文件 |
recover | 撤销一次擦除的笔迹 |
screenshots | 白板截图 |
cleanBoardPage | 白板清屏 |
- 所有用户可以主动调用的方法都是QNWhiteBoard类的静态方法
方法名称 | 方法描述 |
---|---|
getStatus | 获取白板当前状态 |
getRoom | 获取当前加入的房间信息 |
getMe | 获取当前房间中的个人信息 |
getUsers | 获取当前房间中的用户列表 |
getPageList | 获取当前白板的全部页信息列表 |
getCurrentPage | 获取当前白板页信息 |
getBackgroundColor | 获取当前显示的白板背景色 |
getInputConfig | 获取当前使用的白板输入模式 |
getActiveWidget | 获取当前被激活操作的widget |
canRecovery | 是否存在可还原的笔迹 |
getViewport | 获取当前白板的窗口尺寸信息 |
- 通过调用QNWhiteBoard.addListener可以添加事件监听器,可以在任何时期添加,包括进入白板之前。
- 所有的事件都在QNWhiteBoardListener接口中。如果添加此类的直接子类作为监听器,则添加后必须由用户手动调用QNWhiteBoard.removeListener来移除。此方式通常用于在房间外监听房间中发生的事并记录日志或触发某些全局事件时使用。
- QNWhiteBoardListener存在一个易用的子类QNAutoRemoveWhiteBoardListener,如果添加此类的子类监听器,则用户在调用QNWhiteBoard.leaveRoom时系统会自动清理所有的QNAutoRemoveWhiteBoardListener子类监听器,无需用户手动移除。
事件名称 | 事件描述 |
---|---|
onJoinSuccess | 成功加入白板房间 |
onJoinFailed | 加入房间失败 |
onReconnecting | 白板正在自动重连 |
onReconnected | 自动重连成功 |
onDisconnected | 房间彻底断开连接 |
onBoardStatusChanged | 白板房间状态变化 |
onUserList | 当前已经在房间中的用户列表 |
onUserJoin | 有其它用户加入了房间 |
onUserLeave | 有其它用户离开了房间 |
onBoardPageList | 白板页信息列表 |
onCurrentBoardPageChanged | 白板当前页变化 |
onBoardPageInfoChanged | 某一个白板页信息变化 |
onBoardSizeChanged | 白板的虚拟大小发生变化 |
onBoardScroll | 白板内发生滚动 |
onBackgroundColorChanged | 白板背景色变化 |
onWidgetActive | 有widget被激活 |
onFilePageChanged | 文件被翻页 |
onWidgetActionEvent | widget被执行了某些关键动作 |
onRecoveryStateChanged | 笔迹回收站状态变化 |
|onPageCleaned|清屏成功回调| |onFileScrolled|文件滑动回调|
所有白板SDK的主动用户接口,所有接口线程安全
public static void init(@NonNull Context context , boolean debug)
初始化白板SDK
应用启动后只需调用一次,最好在Application
中调用。
参数 | 描述 |
---|---|
context | Android上下文 |
debug | 是否开启debug模式,如果为true则sdk会输出一些日志 |
public static void joinRoom(@NonNull JoinConfig config)
进入白板房间
只有此方法执行成功才能连通白板,目前sdk仅支持同时进入一个房间,多次调用是安全的,但仅有第一次调用的参数有效,后续调用会被忽略,如需进入其它房间,需要先执行leaveRoom。
加入成功后本地会收到onJoinSuccess回调,加入失败则会收到onJoinFailed回调。 同时远端用户会收到onUserJoin回调。
如果已经加入成功但是发生了掉线,则SDK会尝试自动重连,并收到onReconnecting回调。 重连次数可以通过setRetry修改,重连成功后会收到onReconnected,重连失败会收到onDisconnected,此时必须用户手动调用此方法重新加入房间。
参数 | 描述 |
---|---|
config | 房间和身份信息 |
public static void leaveRoom()
离开白板房间
该方法会断开白板连接并释放资源,同时会清理所有的QNAutoRemoveWhiteBoardListener类型的监听器。 多次调用是安全的。 离开白板后远端用户会收到onUserLeave回调。
public static void addListener(@NonNull QNWhiteBoardListener listener)
添加一个白板事件监听器
如果添加QNWhiteBoardListener的直接子类则会永久存续,直到使用removeListener移除。 如果添加QNAutoRemoveWhiteBoardListener的子类则可以在leaveRoom时自动移除,无需手动执行removeListener。
可以在joinRoom之前或之后添加
参数 | 描述 |
---|---|
listener | 事件监听器 |
public static void removeListener(@NonNull QNWhiteBoardListener listener)
移除一个白板事件监听器
可在任何时候调用。
参数 | 描述 |
---|---|
listener | 监听器实例 |
public static void clearListener()
清空所有白板监听器
会清空所有的监听器,包括QNWhiteBoardListener和QNAutoRemoveWhiteBoardListener类型的全部监听器。
可在任何时候调用。
public static void screenshots(@NonNull ScreenshotsCallback listener)
白板截图
仅在QNWhiteBoardView附加到布局中时有效(即必须有可见的白板),回调ScreenshotsCallback将在非主线程执行。
参数 | 描述 |
---|---|
listener | 截图回调,在非主线程回调,截图成功会返回Bitmap ,失败返回null |
public static void setDefaultInputMode(@NonNull InputConfig config)
设置白板的默认初始输入模式配置
在joinRoom之前调用有效,已经进入房间时调用此方法不会改变当前的输入模式,仅会影响下次进入房间的输入模式。 如需改变当前房间中的输入模式,请调用setInputMode方法。
此方法用于预先设定加入房间后的初始输入配置,反复加入离开房间不会影响此默认设置。 默认设置不会随setInputMode方法改变,即一次设定长期有效。
参数 | 描述 |
---|---|
config | 输入模式配置 |
public static void cleanBoardPage(String pageId)
清空指定页面的画布上的内容
参数 | 描述 |
---|---|
pageId | 页面id |
public static void setRetry(int count)
设置白板断线自动重连次数
默认为10次,设为0表示不自动重连。
参数 | 描述 |
---|---|
count | 重连次数 |
public static void setInputMode(@NonNull InputConfig config)
改变白板的输入模式
此方法用于已经连通白板房间时改变用户对白板的输入模式,包括例如笔迹的粗细和颜色等。
参数 | 描述 |
---|---|
config | 输入模式配置 |
public static void setBackgroundColor(@ColorInt int color)
设置白板背景色
用于在白板房间中改变当前白板页的背景色,未进入房间调用无效。
- 仅能改变当前页面的背景以及此后新增的页面背景,不会影响已经存在的页面背景。
参数 | 描述 |
---|---|
color | 颜色值(支持透明) |
public static void scroll(float offsetY)
垂直滚动白板显示区
- 目前白板是一个纵向可滚动(高大于宽)的矩形,通常白板的可视区WhiteBoardViewport不能呈现完整白板,需要通过滚动来控制可见区。
- 白板内部可以通过用户的双指操作来滚动白板,无需外部干涉,此方法的目的是方便用户实现类似top按钮或滚动条功能。
无论是调用此方法还是用户通过白板手势滚动了白板(包括远程用户滚动白板),都会触发onBoardScroll回调。
参数 | 描述 |
---|---|
offsetY | 白板的垂直偏移量,此值为总量而非增量,当前值在WhiteBoardViewport中描述 |
public static void newBoardPage()
新增白板页
在房间中调用可以在当前页列表末尾插入一个新的页面并会自动跳转到这个新页面。
页面创建成功后用户会收到onCurrentBoardPageChanged、onBoardPageList、onBoardPageInfoChanged三个回调。
public static void insertBoardPage(@NonNull String pageId)
插入新白板页
在指定的页面之前插入一个新白板页,同时白板会自动跳转到新插入的页面。
页面创建成功后用户会收到onCurrentBoardPageChanged、onBoardPageList、onBoardPageInfoChanged三个回调。
参数 | 描述 |
---|---|
pageId | 目标插入位置的页id,此id来自于页数据,可通过getPageList或getCurrentPage获取页列表或当前显示页数据,也可通过onBoardPageList和onCurrentBoardPageChanged回调来收集 |
public static void jumpBoardPage(@NonNull String pageId)
跳转到指定白板页
直接跳页的实现方式。
跳转成功后用户会收到onCurrentBoardPageChanged、onBoardPageInfoChanged回调。
参数 | 描述 |
---|---|
pageId | 跳转目标的页id,此id来自于页数据,可通过getPageList或getCurrentPage获取页列表或当前显示页数据,也可通过onBoardPageList和onCurrentBoardPageChanged回调来收集 |
public static void preBoardPage()
返回到上一页
成功后用户会收到onCurrentBoardPageChanged、onBoardPageInfoChanged回调。
public static void nextBoardPage()
前进到下一页
成功后用户会收到onCurrentBoardPageChanged、onBoardPageInfoChanged回调。
public static void deleteBoardPage(@NonNull String pageId)
删除白板页
删除成功后一定会收到onBoardPageList回调,如果删除的是当前页会同时触发onCurrentBoardPageChanged, 如果删除当前页时仅有的一页,则白板会忽略本次操作。
参数 | 描述 |
---|---|
pageId | 要删除的页id,此id来自于页数据,可通过getPageList或getCurrentPage获取页列表或当前显示页数据,也可通过onBoardPageList和onCurrentBoardPageChanged回调来收集 |
public static void insertFile(@NonNull FileConfig config)
向当前白板页中插入文件
支持的格式有图片jpg,png 文档pdf,doc,docx,dot,wps,wpt,dotx,docm,dotm,rtf 演示文稿ppt,pptx,pot,potx,pps,ppsx,dps,dpt,pptm,potm,ppsm 表格xls,xlsx,xlt,et,ett,xltx,csv,xlsb,xlsm,xltm 如果试图插入不支持的文件类型则会被忽略。
图片尽量上传2K及以下的尺寸,否则某些老旧设备可能无法加载。 office文件需要在线转换格式,所以画面呈现会相对慢一些。
文件插入后会收到大量onWidgetActionEvent回调(与房间人数有关),此回调仅表达了导致文件状态变化的用户信息和此用户的加载情况, 通常用于在界面上表达房间中各成员对此文件的加载状态。
参数 | 描述 |
---|---|
config | 文件配置信息 |
public static void jumpFilePage(@NonNull String widgetId , int pageNo)
文件翻页
对于可翻页的文件,如pdf和office文件,通过调用此方法可以使文件跳到指定序号的页面。
翻页成功后会收到onFilePageChanged回调。
参数 | 描述 |
---|---|
widgetId | 文件的widgetId,每个文件都有一个id,可以通过getActiveWidget方法获取当前用户正在操作的Widget,也可以通过onWidgetActive收集当前正在操作的Widget |
pageNo | 跳转的目标页号,从1开始,如果序号超出文件范围,跳转会失败并忽略 |
public static void deleteFile(@NonNull String widgetId)
删除文件
删除后会触发onWidgetActionEvent回调,如果删除的文件是当前正在激活的widget,则会收到onWidgetActive回调,并且参数为null。
参数 | 描述 |
---|---|
widgetId | 文件的widgetId,每个文件都有一个id,可以通过getActiveWidget方法获取当前用户正在操作的Widget,也可以通过onWidgetActive收集当前正在操作的Widget |
public static void recover()
还原最近一次擦除的笔迹
在输入模式为橡皮模式InputConfig.erase时,本用户擦除的笔迹可以通过调用此方法来还原(回滚)。 一次擦除的笔迹指的是用户从落下手指移动擦除线条到抬起手指为止期间擦掉的所有线条。
- 当切换到其它输入模式或者白板翻页后擦除的笔迹缓存将会清空,将无法再还原擦掉的笔迹,即此方法仅在InputConfig.erase模式下有效。
- 此方法多次调用是安全的。
- 判断当前是否有可还原的笔迹可以通过调用canRecovery或监听onRecoveryStateChanged回调获知。
@NonNull public static BoardStatus getStatus()
获取白板当前状态
也可以监听onBoardStatusChanged。
- 返回
- 当前的白板状态BoardStatus。
@Nullable public static Room getRoom()
获取当前加入的房间信息
与监听onJoinSuccess获得的信息一致。
- 返回
- 房间信息Room,如果未加入房间则会返回null。
@Nullable public static RoomMember getMe()
获取当前房间中的个人信息
与监听onJoinSuccess获得的信息一致。
- 返回
- 自己的成员信息RoomMember,如果未加入房间则会返回null。
@NonNull public static List<RoomMember> getUsers()
获取当前房间中的全部用户列表(包括自己)
此列表与监听onUserList,onUserJoin,onUserLeave收集获得的列表一致。
- 返回
- 一个只读的RoomMember成员信息列表,如果未加入房间则会返回空列表。
@NonNull public static List<WhiteBoardPage> getPageList()
获取当前白板的全部页信息列表
此列表与监听onBoardPageList,onBoardPageInfoChanged处理后获得的列表一致。
- 返回
- 一个只读的WhiteBoardPage白板页信息列表,如果未加入房间则会返回空列表。
@Nullable public static WhiteBoardPage getCurrentPage()
获取当前显示的白板页信息
此信息与监听onCurrentBoardPageChanged获得的信息一致。
- 返回
- 当前白板页信息WhiteBoardPage,如果未加入房间则会返回null。
@ColorInt public static int getBackgroundColor()
获取当前白板页的背景色
此值与监听onBackgroundColorChanged获得的颜色一致。 可通过调用setBackgroundColor改变当前白板页的背景。 默认背景色由服务器创建房间时指定。
- 返回
- 当前白板页颜色值,如果未加入房间则会返回一个固定值
Color.LTGRAY
。
- 当前白板页颜色值,如果未加入房间则会返回一个固定值
@NonNull public static InputConfig getInputConfig()
获取白板当前的输入模式
- 返回
- 通过setInputMode设置的InputConfig,如果未加入房间则会返回默认配置,默认值可通过setDefaultInputMode设置。
@Nullable public static ActiveWidgetInfo getActiveWidget()
获取当前被激活操作的widget信息
此信息与监听onWidgetActive获得的数据一致。
- 返回
- ActiveWidgetInfo,如果当前用户没有操作过任何widget或者用户未加入房间则会返回null。
public static boolean canRecovery()
是否存在可还原的笔迹(擦除还原,仅对笔迹有效)
此值与监听onRecoveryStateChanged回调获取的值一致。
@NonNull public static WhiteBoardViewport getViewport()
获取当前白板的可视区信息,包括白板的大小和偏移
此数据与监听onBoardSizeChanged和onBoardScroll获取的数据一致。 滚动白板可由用户双指手势拖动白板,也可通过程序主动调用scroll完成。
- 返回
- 白板的可视区WhiteBoardViewport,通常此值是跟随用户滚动白板而变化,如果未加入房间则会返回固定值WhiteBoardViewport.IDLE。
所有的白板事件的监听器,所有事件响应均在主线程回调。 可通过addListener添加。
public interface QNAutoRemoveWhiteBoardListener extends QNWhiteBoardListener
能自动移除的白板事件监听器(推荐使用) 此监听器同样可以在任何时期添加,但是会伴随leaveRoom的调用而自动移除,无需用户手动执行removeListener。
void onJoinSuccess(@NonNull Room room , @NonNull RoomMember me)
成功加入白板房间
joinRoom成功后的第一个关键事件(onBoardStatusChanged返回BoardStatus.SUCCESSFUL会先一步触发)。 在这里可以处理一些加入房间成功时的初始化工作。
- 在断线重连成功时同样会触发此事件,之后才会触发onReconnected事件。
参数 | 描述 |
---|---|
room | 房间信息 |
me | 个人信息,由joinRoom传递的JoinConfig中携带的信息 |
void onJoinFailed(int errorCode)
加入房间失败
joinRoom执行失败后触发,因为并没有成功加入房间,所以不会执行自动重连。 失败后需要用户重新调用joinRoom来加入房间。 如果已经成功加入了房间但是发生了断线则会触发onReconnecting尝试自动重连,重连失败则会触发onDisconnected,而不会触发本事件。
参数 | 描述 |
---|---|
errorCode | 失败错误码 |
void onReconnecting(int times)
白板正在自动重连
当白板连接意外断开比如网络波动等,白板会自动尝试重连,在每次尝试开始时会触发此事件。 重连成功后会先触发onJoinSuccess后触发onReconnected, 重连次数达到上限后会触发失败事件onDisconnected。 首次调用joinRoom失败不会自动重连,而是触发onJoinFailed。
重连次数默认10次,可通过setRetry修改。
参数 | 描述 |
---|---|
times | 当前为第几次重试 |
void onReconnected()
自动重连成功
void onDisconnected()
自动重连失败,白板彻底断开连接
即在onReconnecting重试次数达到上限后触发, 此时需要用户重新执行joinRoom加入房间。
void onBoardStatusChanged(@NonNull BoardStatus status)
白板房间状态变化
从joinRoom到leaveRoom之间,只要白板房间的状态发生变化就会触发此事件。 同时此事件触发早于onJoinSuccess,onJoinFailed,onReconnecting等独立事件。 比如调用joinRoom后会立即触发BoardStatus.LOADING的变化,onJoinSuccess触发之前会先触发BoardStatus.SUCCESSFUL的变化。
参数 | 描述 |
---|---|
status | 新的白板状态 |
void onUserList(@NonNull List<RoomMember> users)
当前已经在房间中的用户列表(包括自己)
加入房间后会触发一次返回已经在房间中的用户,自动重连成功后也会触发。
- 如果自己管理用户列表,需要以此回调的作为列表初始数据,并且在重连成功后重置初始列表。
- 后续的远端用户进出事件由onUserJoin和onUserLeave反馈。
- getUsers总是获取当前的完整用户列表。
参数 | 描述 |
---|---|
users | 已经在房间中的用户信息RoomMember列表,此列表为只读列表 |
void onUserJoin(@NonNull RoomMember user)
有远端用户加入了房间
- 如果自己维护用户列表,注意更新列表数据
参数 | 描述 |
---|---|
user | 用户信息 |
void onUserLeave(@NonNull RoomMember user)
有远端用户离开了房间
- 如果自己维护用户列表,注意更新列表数据
参数 | 描述 |
---|---|
user | 用户信息 |
void onBoardPageList(@NonNull List<WhiteBoardPage> list)
白板页信息列表
在首次进入房间和白板页列表结构变化时触发,比如新增页,删除页等等。 仅翻页不会触发此事件。
参数 | 描述 |
---|---|
list | 白板页信息WhiteBoardPage的只读列表,也可以通过getPageList获得 |
void onCurrentBoardPageChanged(@NonNull WhiteBoardPage page)
白板当前页改变
在首次加入房间后和翻页时触发,新增页由于会自动切换到新页面,所以也会触发。
参数 | 描述 |
---|---|
page | 当前显示的白板页信息,也可以通过getCurrentPage获得 |
void onBoardPageInfoChanged(@NonNull WhiteBoardPage page)
某一个白板页信息变化
目前仅白板页的缩略图地址发生变化时才会触发此事件,每当白板发生翻页时都会自动更新上一个页面的缩略图, 所以通常情况下此事件触发的白板页信息不是当前正在显示的页面。
- 由于页号WhiteBoardPage.pageNumber的变化是新增和删除页导致,可能同时影响大量的页信息,所以页号变化没有单独的事件,只能监听onBoardPageList观察整个列表的变化。
参数 | 描述 |
---|---|
page | 有参数变化的新的页信息,当前仅有缩略图地址变化WhiteBoardPage.thumbnails |
void onBoardSizeChanged(@NonNull WhiteBoardViewport viewport)
白板大小变化(虚拟大小)
在白板设定的虚拟大小变化时触发,首次进入白板一定会触发一次。
参数 | 描述 |
---|---|
viewport | 白板的可视区数据 |
void onBoardScroll(@NonNull WhiteBoardViewport viewport)
白板滚动
白板内发生滚动时触发,主动调用scroll也会触发,首次进入白板也会触发。
参数 | 描述 |
---|---|
viewport | 白板的可视区数据 |
void onBackgroundColorChanged(@ColorInt int backgroundColor)
白板背景色改变
当前的白板背景色变化时触发,首次进入白板也会触发。 可通过setBackgroundColor随时改变背景色。
参数 | 描述 |
---|---|
backgroundColor | 新的颜色值 |
void onWidgetActive(@Nullable ActiveWidgetInfo info)
有新的widget被激活
用户书写或操作白板时会激活被操作的widget,同时触发此事件,比如移动文件时会收到被移动的文件信息,在白板上写字时会收到白板的信息。 当此widget是文件且此文件发生翻页后会再次触发此事件,同时也会触发onFilePageChanged。
参数 | 描述 |
---|---|
info | 当前激活的widget信息,null表示用户还没有操作,比如刚刚翻页后 |
void onPageCleaned(@NonNull String pageId)
清空白板完成回调
使用cleanBoardPage后回调。
参数 | 描述 |
---|---|
pageId | 被清空的页面ID |
void onPageCleaned(@NonNull String pageId)
清空白板完成回调
使用cleanBoardPage后回调。
参数 | 描述 |
---|---|
pageId | 被清空的页面ID |
void onFileScrolled(@NonNull WidgetScrollInfo info)
文件滑动到上下顶部边缘监听
参数 | 描述 |
---|---|
info | 滑动信息 |
void onWidgetActionEvent(@NonNull WidgetActionEvent event)
widget被执行了某些关键动作
比如有人插入文件或删除文件会收到此事件。 同时每个远端用户的文件加载情况也会触发此事件,通过此事件可以观察到每个人文件加载成功或失败情况。
- 当前仅文件和图片widget会触发此事件。
参数 | 描述 |
---|---|
event | widget事件信息 |
void onRecoveryStateChanged(boolean isEmpty)
笔迹回收站空与非空的状态变化
当在擦除模式InputConfig.erase擦除笔迹时被擦除的笔迹会移动到回收站导致回收站不为空,会触发此事件。 当反复调用还原笔迹recover导致回收站为空时会触发此事件。 当从擦除模式切换到其他模式或白板翻页后会自动清空回收站,同样有可能触发此事件。
参数 | 描述 |
---|---|
isEmpty | true表示回收站为空,false表示不为空,此时可以通过recover来还原一次擦除操作 |
截图完成回调
screenshots中使用。
void done(@Nullable Bitmap bitmap)
截图完成
参数 | 描述 |
---|---|
bitmap | 截图得到的位图,如果为null表示截图失败,位图大小等于QNWhiteBoardView的像素大小 |
白板的显示控件,用于显示白板内容,当前仅支持同时显示一个白板,如果同时放置了多个白板控件,仅最后一个控件会刷新内容。 布局时此控件的大小最好设定为与白板的虚拟大小WhiteBoardSize的宽高比保持一致,否则多余的边缘会留白。
加入房间时的参数配置
构造函数
public JoinConfig( @NonNull String token)
参数 | 类型 | 可空 | 描述 |
---|
|token|String|否|每次加入房间时生成的标识符,与appId,roomId,userId关联,通常由服务器生成| |roleId|int|否|角色id,默认为0,通常用来标识此用户身份,方便定制用户权限系统| |sessionId|String|是|用户会话id,用于唯一标识用户,如果用户业务系统中有与userId对应的临时用户标识符,比如session或token等,此临时id可以在此传递,如果userId相同但是sessionId不同的两个用户加入了白板,可以视为相同用户的多设备加入白板实现,如果留空则白板会自动生成一个| |nickname|String|是|用户名或昵称,在白板中使用的用户名称| |avatar|String|是|用户头像地址,在白板中显示的用户头像| |widthHeightThan|double|是|白板宽高比 范围[0.5,2.2] 默认0.5| |limitNumber|int|是|人数限制,0代表不限制:如果 >0,代表白板内最多limitNumber个人,只要白板内人数超过limitNumber数量时,就会进不去,默认0| |boardSizeId|int|是|创建的白板(meeting)的大小。有三个可选值:1,2,3 1代表白板是2x2, 2代表白板是3x3, 3代表白板是1x3 默认3| |bgColor|int|是| 表示白板(meeting)的颜色。也有三个值可选: 1,2,3 1 代表白色,2 代表黑色,3 代表绿色。 默认1| |zoomScale|int|是| zoomScale 扩展比 1~5之间 非必填 默认1| |title|String|是| 白板标题(长度 1 ~ 20 支持数字、字符、下划线_),相同的RTC房间,如果title相同,则进相同的房间,一个RTC房间可以有多个白板房间,标题不同就会生成新的, 该字段非必填|
输入模式配置 此类仅提供静态工厂方法。
public static InputConfig pen(@ColorInt int color , float thickness)
创建一个笔书写输入模式配置
参数 | 描述 |
---|---|
color | 笔颜色,支持透明度,适当的透明度可以看作是马克笔实现 |
thickness | 笔粗细,必须大于0 |
public static InputConfig laserPen(@NonNull LaserType laserType)
创建一个激光笔输入模式配置
激光笔是一种瞬时的位置指示型输入模式,指示手指位置的内容。
参数 | 描述 |
---|---|
laserType | 激光笔类型 |
public static InputConfig erase(float size)
创建一个橡皮(擦除)输入模式配置
参数 | 描述 |
---|---|
size | 橡皮面积 |
public static InputConfig geometry(@NonNull GeometryType geometryType , @ColorInt int color , float thickness)
创建一个几何图形输入模式配置
参数 | 描述 |
---|---|
geometryType | 图形类型 |
color | 图形边框的颜色 |
thickness | 图形边框粗细 |
public static InputConfig select()
创建一个选择输入模式配置
此模式可以在白板中框选内容。
向白板插入文件时描述文件信息的配置
构造函数
public FileConfig(@NonNull File file)
public FileConfig(@NonNull File file , @Nullable String name)
public FileConfig(@NonNull File file , @Nullable String name , float left , float top)
public FileConfig(@NonNull File file , @Nullable String name , float left , float top , int boxWidth , int boxHeight)
参数 | 类型 | 可空 | 描述 |
---|---|---|---|
file | File | 否 | 要插入的文件,此文件必须有支持的类型后缀,否则会被系统忽略,支持的类型参考insertFile |
name | String | 是 | 指定文件的实际名称,留空会使用file的名称,此名称不会影响系统对file类型的校验,仅做标识用途,比如file本身是随机串文件名,此处可以赋予它有意义的文件名,此名称会在ActiveWidgetInfo中拿到 |
left | float | 否 | 插入文件时的初始位置的左上角横坐标,默认为0 |
top | float | 否 | 插入文件时的初始位置的左上角纵坐标,默认为0 |
boxWidth | int | 否 | 文件外框的宽度,0表示使用文件自身的宽度 |
boxHeight | int | 否 | 文件外框的高度,0表示使用文件自身的高度 |
被激活的widget信息
白板中的一切都是widget,包括白板,文件,图片,选择框等等,具体参考WidgetType。 当用户操作了一个widget或者在它上面书写时,这个widget会被激活,会触发onWidgetActive事件。
参数 | 类型 | 可空 | 描述 |
---|---|---|---|
id | String | 否 | widgetId,此widget的唯一标识符,后续对widget的操作都会用到此id,比如jumpFilePage和deleteFile |
type | WidgetType | 否 | 指示了此widget的类型 |
userId | String | 是 | 此widget创建者的userId,通常白板页是没有创建者的,由服务器创建 |
name | String | 是 | widget名称,如果此widget是文件或图片时 |
resourceId | String | 是 | 资源id,sdk内部用于标识实际文件的索引,用户通常无需关心 |
path | String | 是 | 文件路径,如果widget是文件或图片,此为它的本地路径(如果插入的原文件是office文件,则此路径是它转换后的pdf路径,并非原始文件) |
currentPageNumber | int | 否 | 如果widget是文件时,此为当前文件的页码,从1开始 |
pageCount | int | 否 | 如果widget是文件时,此为文件的总页数(如果原文件是office文件,则此页数是转换成pdf后的实际页数) |
房间信息
加入白板房间成功后会收到此数据。
参数 | 类型 | 可空 | 描述 |
---|---|---|---|
roomId | String | 否 | 房间的id,与joinRoom时的roomId一致 |
fileGroupId | String | 否 | 白板中的文件在服务器存储的文件组id,用户无需关心 |
chatRoomId | int | 否 | 房间中的聊天室id,暂不支持 |
房间中的成员信息
参数 | 类型 | 可空 | 描述 |
---|---|---|---|
userId | String | 否 | 用户业务系统中的稳定用户id |
sessionId | String | 否 | 用户会话id,用于唯一标识用户,如果成员在joinRoom时未传递此参数,则此参数会由白板自动生成 |
roleId | int | 否 | 角色id,默认为0,通常用来标识此用户身份,方便定制用户权限系统 |
nickname | String | 是 | 用户名或昵称 |
avatar | String | 是 | 用户头像地址 |
白板页信息
参数 | 类型 | 可空 | 描述 |
---|---|---|---|
pageId | String | 否 | 白板页id,每个页面的唯一标识符,后续对白板页的操作会用到,比如jumpBoardPage,deleteBoardPage等 |
pageNumber | int | 否 | 页面序号,从1开始,标识了此页是白板中的第几页 |
thumbnails | String | 否 | 白板页缩略图url,没有时为空字符串 |
白板尺寸信息
此信息的数值基于白板内部的虚拟大小和坐标系,并非实际渲染窗口的纹理大小(实际的纹理大小由WhiteBoardView的像素大小决定)。 以下参数由服务器创建白板房间时指定,通常在一个房间中此信息是固定不变的。
参数 | 类型 | 描述 |
---|---|---|
maxWidth | int | 白板最大宽度 |
maxHeight | int | 白板最大高度 |
displayWidth | int | 白板显示宽度(可视区的宽度,当前仅支持与maxWidth保持一致,即只能垂直延展) |
displayHeight | int | 白板显示高度(可视区的高度,当此参数小于maxHeight时白板可上下滚动) |
public static final WhiteBoardSize ZERO = new WhiteBoardSize(0 , 0 , 0 , 0);
一个空尺寸,在未加入白板时获取到的值。
白板当前可视区信息
所有数值基于白板内部的虚拟大小和坐标系,并非实际渲染窗口的纹理大小。 当白板页滚动时会刷新此数据。
参数 | 类型 | 描述 |
---|---|---|
size | WhiteBoardSize | 白板尺寸 |
offsetX | float | 当前白板水平偏移(当前仅支持垂直滚动,所以此值总是0) |
offsetY | float | 当前白板垂直偏移 |
public static final WhiteBoardViewport IDLE = new WhiteBoardViewport(WhiteBoardSize.ZERO , 0 , 0);
一个空闲值,在未加入白板时获取到的值。
widget动作事件
描述了对文件或图片的关键操作信息,包括加载情况,由谁插入或删除等。 由onWidgetActionEvent提供。
参数 | 类型 | 可空 | 描述 |
---|---|---|---|
sessionId | String | 否 | 动作发出者的sessionId |
type | WidgetType | 否 | widget类型 |
action | WidgetAction | 否 | 动作类型 |
name | String | 是 | widget名称 |
白板房间状态枚举
空闲状态,表示没有进入白板
正在进入白板,即调用joinRoom之后到成功或失败之前的状态。
加入白板成功
加入白板失败
白板正在重连
几何图形类型
在InputConfig.geometry中指定要绘制的几何图形。
名称 | 图形 |
---|---|
RECTANGLE | 矩形 |
CIRCLE | 圆形 |
LINE | 直线 |
ARROW | 箭头 |
激光笔类型
在InputConfig.laserPen中指定激光指示点的样式。
名称 | 样式 |
---|---|
LASER_DOT | 圆点 |
LASER_HAND | 手形图标 |
LASER_ARROWS_WHITE | 白色箭头 |
LASER_ARROWS_BLACK | 黑色箭头 |
widget类型,白板中的一切都是widget
名称 | 类型 |
---|---|
BOARD | 白板 |
FILE | 文件,包括pdf和office |
IMAGE | 图片,jpg和png |
GEOMETRY | 几何图形,由InputConfig.geometry模式绘制 |
SELECTION | 选择框,由InputConfig.select模式选中的内容 |
widget类型,白板中的一切都是widget
名称 | 类型 |
---|---|
BOARD | 白板 |
FILE | 文件,包括pdf和office |
IMAGE | 图片,jpg和png |
GEOMETRY | 几何图形,由InputConfig.geometry模式绘制 |
SELECTION | 选择框,由InputConfig.select模式选中的内容 |
文件滑动信息
在onFileScrolled中回调。
参数 | 类型 | 描述 |
---|---|---|
widgetId | String | 文件widgetId |
scrollToTop | int | 1代表到顶 |
scrollToBottom | int | 1代表到底 |
-keep class com.qiniu.droid.whiteboard.** {*;}
错误码
名称 | 值 | 错误含义 |
---|---|---|
NETWORK_ERROR | 100 | 网络不可用 |
SERVER_ERROR | 101 | 服务器错误或繁忙 |
APP_ID_NOT_EXIST | 200 | appId不存在 |
ROOM_ID_NOT_EXIST | 201 | roomId不存在 |
USER_ID_EMPTY | 202 | userId为空 |
TOKEN_ERROR | 203 | token错误 |
CONNECT_ROOM_FAILED | 300 | 连接房间失败 |
PAGE_INFO_TIMEOUT | 301 | 等待页数据下发超时 |
ROOM_DISCONNECT | 302 | 房间连接中断,可能是网络波动,也可能是房间中传输了错误数据导致被服务器切断 |
INVALID_ARGS | 303 | 加入房间参数错误 |