This document describes how to create multiple whiteboards using the Super Board SDK and switch between them freely. The example scenario in this document is as follows:
Assume that A creates a whiteboard and operates on it and that B watches the whiteboard in this flow. In the preceding figure, the dotted line indicates that B can obtain related information from the corresponding callback when A performs the operation.
Refer to Getting started to integrate and initialize the SDK and log in to the room. The complete sample code is as follows:
// Integrate the SDK before executing the following code.
// Initialize ZegoExpressEngine.
// We recommend that the following initialization sample code be executed upon app start.
/** Define the SDK engine object. */
ZegoExpressEngine engine;
ZegoEngineProfile profile = new ZegoEngineProfile();
/** Register with the official website and obtain the data in the format similar to 123456789L. */
profile.appID = appID;
/** Register on the official website and obtain a string of 64 characters in the format similar to "0123456789012345678901234567890123456789012345678901234567890123" */.
profile.appSign = appSign;
/** Access in general scenarios. */
profile.scenario = ZegoScenario.GENERAL;
/** Set the application object for the app. */
profile.application = getApplication();
/** Create an engine */
engine = ZegoExpressEngine.createEngine(profile, null);
if (engine != null) {
// Set appID and appSign for Super Board initialization.
ZegoSuperBoardInitConfig config = new ZegoSuperBoardInitConfig();
config.appID = appID;
config.appSign = appSign;
// Call SuperBoardManager to initialize the Super Board SDK.
ZegoSuperBoardManager.getInstance().init(application, config, errorCode -> {
Log.d(TAG, "init ZegoSuperBoardManager result: errorCode = [" + errorCode + "]");
if (errorCode == ZegoSuperBoardError.ZegoSuperBoardSuccess) {
/** Initialization succeeded. */
} else {
/** Initialization failed. */
}
});
}
// Ensure that the Express SDK has been successfully initialized before logging in to a room.
// Define two member variables in the implementation class. (For details, refer to ZegoExpressWrapper.java in the demo.)
// Indicates whether the user is logging in to a room.
private boolean isLoginRoom = false;
// Callback after room login.
private SDKLoginCallback loginResult;
// Callback of room registration status.
engine.setEventHandler(new IZegoEventHandler() {
@Override
public void onRoomStateUpdate(String roomID, ZegoRoomState state, int errorCode, JSONObject extendedData) {
Log.d(TAG, "onRoomStateUpdate:state :" + state + ",errorCode: " + errorCode);
switch (state) {
case DISCONNECTED: {
if (isLoginRoom) {
if (loginResult != null) {
loginResult.onResult(errorCode);
}
// Reset the bool variable.
isLoginRoom = false;
}
}
break;
case CONNECTED: {
if (isLoginRoom) {
// Call the callback of room login success.
if (loginResult != null) {
loginResult.onResult(errorCode);
}
// Reset the bool variable.
isLoginRoom = false;
}
}
break;
}
}
});
String userID = "66668888";
String userName = "Test 01";
// Generate user information.
ZegoUser user = new ZegoUser(userID, userName);
// Set room attributes.
ZegoRoomConfig roomConfig = new ZegoRoomConfig();
roomConfig.isUserStatusNotify = true;
engine.loginRoom(roomID, user, roomConfig);
// Add a mark indicating that the user is logging in to a room.
isLoginRoom = true;
You must upload the file for creating a file whiteboard in advance. For details, refer to Manage shared files.
// In the following sample code, two encapsulation methods are defined to implement the common whiteboard and file whiteboard creation functions.
/**
* Create a common whiteboard.
*/
private void createWhiteboardView() {
// Construct the configuration class ZegoCreateWhiteboardConfig for whiteboard creation.
ZegoCreateWhiteboardConfig config = new ZegoCreateWhiteboardConfig();
// Fields in the class are as follows:
// Whiteboard name.
config.name = "Common whiteboard 01";
// Number of whiteboard pages.
config.pageCount = 5;
// Width of a whiteboard page.
config.perPageWidth = 960;
// Height of a whiteboard page.
config.perPageHeight = 540;
ZegoSuperBoardManager.getInstance().createWhiteboardView(config, (errorCode, subViewModel) -> {
Log.d(TAG, "createPureWhiteboardView() called with: errorCode = [" + errorCode + "], subViewModel = [" + subViewModel + "]");
if (errorCode == 0) {
Log.d(TAG,"Whiteboard creation succeeded");
} else {
Log.d(TAG, "Whiteboard creation failed, errorCode: " + errorCode);
}
});
}
/**
* Create a specified file whiteboard.
* Animated PowerPoint whiteboards and Excel whiteboards can also be created in this way.
* @param fileID File ID, which can be obtained after the uploaded file is transcoded.
*/
private void createFileBoardView(String fileID) {
// Construct the configuration class ZegoCreateFileConfig for file creation.
ZegoCreateFileConfig config = new ZegoCreateFileConfig();
// File ID, which can be obtained after the file is uploaded.
config.fileID = fileID;
ZegoSuperBoardManager.getInstance().createFileView(config, (errorCode, subViewModel) -> {
Log.d(TAG, "createFileView - onViewCreated() called with: errorCode = [" + errorCode + "], subViewModel = [" + subViewModel + "]");
if (errorCode == 0) {
Log.d(TAG, "File creation succeeded.");
} else {
Log.d(TAG, "File creation failed, errorCode: " + errorCode);
}
});
}
Assume that user A creates a common whiteboard, an animated PowerPoint whiteboard, and an Excel whiteboard.
// Operations performed by user A
// A whiteboard can be created only after true is returned for room login in the preceding step.
// Create a common whiteboard.
createWhiteboardView();
// Create an animated PowerPoint whiteboard.
createFileBoardView(fileID);
// Create an Excel whiteboard.
createFileBoardView(fileID);
After the whiteboards are created, SuperBoardView
automatically synchronizes the whiteboard creation to multiple parties. The last created whiteboard, that is, the Excel whiteboard in this example, is displayed by default. User B receives the onRemoteSuperBoardSubViewAdded
notification each time when user A creates a whiteboard. User B can refresh the local UI logic in the corresponding callback.
Register the SuperBoardManager Listener
callback method to listen for remote adding, destroying, and switching of whiteboards.
ZegoSuperBoardManager.getInstance().setManagerListener(new IZegoSuperBoardManagerListener() {
@Override
public void onError(int errorCode) {
Log.d(TAG, "onError() called with: errorCode = [" + errorCode + "]");
// Internal errors of the SDK are thrown here.
}
@Override
public void onRemoteSuperBoardSubViewAdded(@NonNull ZegoSuperBoardSubViewModel subViewModel) {
Log.d(TAG, "onRemoteSuperBoardSubViewAdded() called with: subViewModel = [" + subViewModel + "]");
// Receive remote whiteboard adding.
}
@Override
public void onRemoteSuperBoardSubViewRemoved(@NonNull ZegoSuperBoardSubViewModel subViewModel) {
Log.d(TAG, "onRemoteSuperBoardSubViewRemoved() called with: subViewModel = [" + subViewModel + "]");
// Receive remote whiteboard destroying.
}
@Override
public void onRemoteSuperBoardSubViewSwitched(@NonNull String uniqueID) {
Log.d(TAG, "onRemoteSuperBoardSubViewSwitched() called with: uniqueID = [" + uniqueID + "]");
// Receive remote whiteboard switching.
}
});
Register the SuperBoardView Listener
callback method to listen for SuperBoardView scrolling and page turning.
ZegoSuperBoardView superBoardView = ZegoSuperBoardManager.getInstance().getSuperBoardView();
if (superBoardView != null) {
superBoardView.setBoardViewListener(new IZegoSuperBoardViewListener() {
@Override
public void onScrollChange(int currentPage, int pageCount, ZegoSuperBoardSubViewModel subViewModel) {
// Listen for scrolling.
// Current page and total pages.
}
@Override
public void onSizeChange(Size visibleSize, ZegoSuperBoardSubViewModel subViewModel) {
// Listen for subView resize callback.
}
});
}
You can call setOperationMode
method to grant permissions for clients to operate on the whiteboard.
On the clients with the corresponding permission, users can draw on the whiteboard. For details, refer to Draw on a whiteboard.
User A switches to the second sheet in the Excel whiteboard.
ZegoSuperBoardView superBoardView = getSuperBoardView();
if (superBoardView != null) {
ZegoSuperBoardSubViewModel subViewModel = getCurrentSubViewModel();
if (subViewModel != null) {
// Operations by user A
// Switch to the second sheet in Excel.
superBoardView.switchSuperBoardSubView(subViewModel.uniqueID, 1, errorCode -> {
if (errorCode == 0) {
Log.d(TAG, "Sheet switching succeeded.");
} else {
Log.d(TAG, "Sheet switching failed, errorCode: " + errorCode);
}
});
}
}
When A switches to a specific sheet in Excel, the switching is automatically synchronized to B. B receives the onRemoteSuperBoardSubViewSwitched
notification. B can refresh the local UI logic in the corresponding callback.
User A switches to the animated PowerPoint whiteboard.
// Operations by user A
ZegoSuperBoardView superBoardView = getSuperBoardView();
if (superBoardView != null) {
// Switch to the whiteboard.
superBoardView.switchSuperBoardSubView(subViewModel.uniqueID, errorCode -> {
if (errorCode == 0) {
Log.d(TAG, "subView switching succeeded.");
} else {
Log.d(TAG, "subView switching failed, errorCode: " + errorCode);
}
});
}
After switching to the animated PowerPoint whiteboard, you can use the step skipping or page turning API or the click tool to present the slides. For details, refer to Turn pages on a whiteboard.
After user A switches the whiteboard, the switching is automatically synchronized to user B. User B receives the onRemoteSuperBoardSubViewSwitched
notification. User B can refresh the local UI logic in the corresponding callback.
To synchronize the zooming effect among multiple parties, you must enable the zooming effect synchronization and responding functions on each party.
// The zooming effect needs to be synchronized between the local and peer parties.
ZegoSuperBoardManager.getInstance().enableSyncScale(true) ;// Synchronize the zooming effect to the other party.
ZegoSuperBoardManager.getInstance().enableResponseScale(true);// Respond to the zooming effect synchronized from the other party.
User A switches to the common whiteboard, uses the text tool to write on the whiteboard, and uses gestures to zoom in or out.
// Operations by user A.
// Switch to the target whiteboard.
ZegoSuperBoardView superBoardView = getSuperBoardView();
if (superBoardView != null) {
// Switch to the whiteboard.
superBoardView.switchSuperBoardSubView(subViewModel.uniqueID, errorCode -> {
if (errorCode == 0) {
// The default whiteboard tool is brush. To set other tool types, call setToolType.
// For example, set the tool type to text, click on the whiteboard where you want to display the text, and enter the text.
ZegoSuperBoardManager.getInstance().setToolType(ZegoSuperBoardTool.Pen);
Log.d(TAG, "subView switching succeeded.");
} else {
Log.d(TAG, "subView switching failed, errorCode: " + errorCode);
}
});
}
After user A switches the whiteboard, the switching is automatically synchronized to user B. User B receives the onRemoteSuperBoardSubViewSwitched
notification, which has been implemented in the preceding step.