Remote Collaboration SDK for Android
The Remote Collaboration Android SDK lets Android apps integrate audio/video meetings, call invitations, screen sharing, whiteboard, video pointing, AR annotation, cloud recording, and meeting file capabilities. It is intended for projects that need to build a custom remote collaboration experience inside their own app.
The SDK provides RTC and meeting APIs. It does not include a complete business UI. Account systems, contact lists, meeting entry points, incoming call pages, and in-meeting pages should be implemented by the integrating app.
1. Use Cases
- Start or join remote collaboration meetings from Android phone apps or Glass3 apps.
- Implement expert calls, member invitations, accept/reject flows, and busy-state handling.
- Control camera, microphone, speaker, local preview, and media streams during meetings.
- Use screen sharing, whiteboard, video pointing, video control, and AR annotation.
- Integrate cloud recording, meeting files, and log upload for audit trails and troubleshooting.
2. Integration Boundary
The Android SDK handles RTC and meeting capabilities. The business app still needs to provide:
- Current user ID, token, or business identity.
- Contact list, display name, avatar, and organization information.
- Meeting entry UI, incoming call UI, in-meeting UI, and error prompts.
- AppId, RTC service URL, meeting token, and environment configuration.
2.1 Preparation Checklist
Before integration, confirm the following items. Missing any of them can cause the SDK to be integrated successfully but fail during initialization, login, or joining a meeting.
| Item | Purpose | How to prepare |
|---|---|---|
| Remote collaboration enabled | Confirms that the company account can use remote collaboration. | Confirm with the Rokid project manager, sales, or delivery contact. |
| SDK version | Used in the Gradle dependency. | Use the version confirmed for the project. |
| Maven repository access | Used to download the Remote Collaboration SDK. | Make sure the development environment can access the Rokid Maven repository. |
appId | SDK initialization parameter that identifies the RTC app. | Assigned by Rokid. |
rtcUrl | SDK initialization parameter used for login, joining meetings, and configuration queries. | Provided by the project environment configuration. |
rtcWebsocketUrl / iceServers | Optional parameters for signaling and RTC network connection. | Use project-specific values when provided. |
Current user userId | Used for SDK login and meeting member identity. | Provided by the integrating app account system or backend service. |
Meeting token | Used when creating or joining a meeting. | Usually issued by the business backend or Rokid OpenAPI. |
| Runtime permissions | Required for camera, microphone, notification, screen sharing, and related capabilities. | Request dynamically before calling the corresponding capability. |
2.2 Account And Authentication
The Remote Collaboration Android SDK integration guide does not require the Platform OpenAPI API_KEY to be configured in the client. The client needs SDK initialization and meeting parameters such as appId, rtcUrl, current user userId, and meeting token. These values are usually provided by the Rokid project environment, the integrating app account system, or the business backend.
If the business backend also calls Platform OpenAPI to query meeting records, participants, meeting files, IM messages, or recordings, configure server-side authentication according to the Platform OpenAPI documentation. Keep the related secrets on the server side only. Do not put them into the Android app or deliver them to clients.
If you only need to query remote collaboration meeting records, participants, files, IM messages, or recordings, use Platform OpenAPI: Remote Collaboration.
3. Recommended Flow
- Add the Rokid Maven repository and Remote Collaboration SDK dependency.
- Declare network, camera, microphone, Bluetooth, foreground service, and related permissions in
AndroidManifest.xml. - Initialize the RTC engine during app startup.
- Log in to remote collaboration after the business user signs in.
- Create or join a meeting through the channel manager.
- Invite, accept, reject, or cancel invitations through the call manager.
- After joining a meeting, control media, sharing, whiteboard, video pointing, annotation, and recording through the channel object.
- Remove listeners when pages are destroyed, and log out or destroy the SDK when appropriate.
3.1 Minimal Verification Path
For the first integration pass, verify the minimum path first:
- Gradle can download the SDK dependency.
- The app declares and dynamically requests required permissions such as camera and microphone.
initsucceeds.login(userId)succeeds.- The app can create or join a test meeting.
- Microphone and camera can be enabled in the meeting, and member state callbacks are received.
4. Project Configuration
4.1 SDK Version
Example Remote Collaboration Android SDK version:
RTC_SDK_VERSION=6.0.1-20260610.105440-5Use the SDK version confirmed for your project during integration.
4.2 Add The Rokid Maven Repository
For Gradle 7.0 and above, configure the repository in the root settings.gradle:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
repositories {
google()
mavenCentral()
maven { url 'https://maven.rokid.com/repository/maven-public/' }
}
}For older Gradle versions, add the same repository to buildscript.repositories and allprojects.repositories in the root build.gradle.
4.3 Add The SDK Dependency
Add the dependency in the business app module build.gradle:
dependencies {
implementation "com.rokid.rtc:rtc:6.0.1-20260610.105440-5"
}4.4 Android Build Configuration
Recommended project configuration:
| Item | Recommended value |
|---|---|
compileSdkVersion | 34 |
targetSdkVersion | 34 |
minSdkVersion | 26 |
| Java / Kotlin JVM Target | 17 |
| ABI | armeabi-v7a, arm64-v8a |
Example:
android {
compileSdkVersion 34
defaultConfig {
minSdkVersion 26
targetSdkVersion 34
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '17'
}
}4.5 Manifest Permissions
Declare permissions in app/src/main/AndroidManifest.xml according to the capabilities used by the app.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />If screen sharing, foreground services, notifications, overlay windows, or file upload are used, add the corresponding permissions based on the target Android version:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />4.6 Runtime Permission Notes
- On Android 6.0 and above, sensitive permissions such as camera, microphone, and storage must be requested at runtime. Static
AndroidManifest.xmldeclarations are not enough. - On Android 12 and above, handle Bluetooth permissions and foreground service types explicitly.
- On Android 13 and above, request
POST_NOTIFICATIONSif notifications are used. - If screen sharing is used, follow the system MediaProjection authorization flow.
5. Core Entry Points
| Entry point | Description |
|---|---|
RKCooperation.getRtcEngine() | Initialization, login, logout, local devices, global video configuration, and log upload. |
RKCooperation.getChannelManager() | Create, join, query, record, and cache meeting channels. |
RKCooperation.getCallManager() | Invite, cancel, accept, reject, busy state, and incoming call listeners. |
RKChannel | Meeting channel object for leaving or ending meetings, member management, media stream control, channel messages, and meeting files. |
RKChannel.getChannelShare() | Sharing capabilities, including screen sharing, whiteboard, video pointing, video control, and AR annotation. |
RKCooperation.getRtcEngine().getLocalDevice() | Local camera, microphone, speaker, audio devices, and capture parameter control. |
6. Initialization And Login
6.1 Initialize The RTC Engine
Initialize the SDK once in the main application process, usually in Application.onCreate().
class App : Application() {
override fun onCreate() {
super.onCreate()
RKCooperation.getRtcEngine().init(
context = this,
appId = appId,
rtcUrl = rtcUrl
)
}
}API definition:
fun init(
context: Context,
appId: String,
rtcUrl: String,
rtcWebsocketUrl: String? = null,
iceServers: List<RKIceServer>? = null
)| Parameter | Required | Description |
|---|---|---|
context | Yes | Use Application or applicationContext to avoid holding an Activity context. |
appId | Yes | RTC application ID. |
rtcUrl | Yes | RTC service URL used for login, joining meetings, and configuration queries. |
rtcWebsocketUrl | No | RTC websocket URL. If omitted, it is determined by SDK or server configuration. |
iceServers | No | TURN/STUN configuration. If omitted, it is determined by SDK or server configuration. |
6.2 Optional Simulcast Configuration
Simulcast is recommended for multi-party meetings, grid layouts, weak-network optimization, and large/small stream switching.
RKCooperation.getChannelManager().enableSimulcast(enable = true)6.3 Login, State, And Logout
The app must log in before creating, joining, or answering a meeting.
val result = RKCooperation.getRtcEngine().login(
userId = userId,
forceRefreshToken = false
)Common state APIs:
val isLogin = RKCooperation.getRtcEngine().isLogin()
val currentUserId = RKCooperation.getRtcEngine().getUserId()Logout and destroy:
RKCooperation.getRtcEngine().logout()
RKCooperation.getRtcEngine().destroy()7. Meeting Channel Management
Meeting channels are managed by RKChannelManager. After creating or joining a meeting, the app receives an RKChannel object for in-meeting operations.
7.1 Create A Meeting
val channelParam = RKChannelParam().apply {
maxMembers = 16
frameRate = 24
maxResolution = Resolution.RESOLUTION_720
url = rtcUrl
token = joinToken
defaultSubscribeMediaType = RKSubscribeMediaType.Both
defaultStreamType = VideoSize.SIZE_SMALL
}
val result = RKCooperation.getChannelManager().createChannel(
channelId = null,
channelTitle = meetingTitle,
channelParam = channelParam
)7.2 Join A Meeting
val result = RKCooperation.getChannelManager().joinChannel(
channelId = channelId,
channelTitle = meetingTitle,
channelParam = channelParam,
timeoutSeconds = 20
)7.3 Query Meetings And Local Cache
val queryResult = RKCooperation.getChannelManager().queryChannel(channelId)
val channel = RKCooperation.getChannelManager().getChannel(channelId)7.4 Common RKChannelParam Fields
| Field | Description |
|---|---|
maxMembers | Maximum member count. A common default is 16. |
maxResolution | Maximum meeting resolution, such as RESOLUTION_360, RESOLUTION_720, or RESOLUTION_1080. |
url | RTC service URL for the current environment. |
token | Meeting token, usually issued by the business backend or Rokid OpenAPI. |
password | Channel password. If omitted, the server or SDK default policy is used. |
frameRate | Video frame rate. |
recordParam | Cloud recording parameter, used when recording is enabled while creating a meeting. |
bitrate | Maximum bitrate. Follow the underlying RTC implementation. |
inviteUserId | Target user ID carried as invitation context. |
defaultSubscribeMediaType | Default media subscription type, such as Both or Audio. |
defaultStreamType | Default stream size, such as VideoSize.SIZE_SMALL. |
8. Meeting Events And Members
private val channelListener = object : RKChannelListener {
override fun onUserJoinChannel(channelId: String, userId: String) {}
override fun onUserLeaveChannel(channelId: String, userId: String) {}
override fun onLeave(channelId: String, reason: Int) {}
override fun onError(channelId: String, errorCode: Int) {}
}
channel.addChannelListener(channelListener)
channel.removeChannelListener(channelListener)Common meeting operations:
channel.leave()
channel.stop()
channel.kickOutUser(userId)
val members = channel.getChannelParticipantList()9. Local And Remote Device Control
9.1 Local Device
val device = RKCooperation.getRtcEngine().getLocalDevice()
device.openCamera(CameraType.FRONT)
device.switchCamera()
device.closeCamera()
device.startAudio()
device.stopAudio()
device.enableSpeaker(true)
val devices = device.getAllAudioDevice()Capture configuration:
device.setCameraProperty(width = 1280, height = 720, frameRate = 24)
device.configScreenShareProperty(width = 1280, height = 720, frameRate = 24)In-meeting media upload control:
channel.enableUploadLocalAudioStream(true)
channel.enableUploadLocalVideoStream(true)
channel.enableAudioOutput(true)9.2 Remote Device Listener
private val remoteDeviceListener = object : RKRemoteDeviceListener {
override fun onUserUploadAudioChanged(userId: String?, enabled: Boolean) {}
override fun onUserUploadVideoChanged(userId: String?, enabled: Boolean) {}
override fun onUserVideoSizeChanged(userId: String?, videoSize: Int) {}
override fun onUserVolumeChange(userId: String?, status: Int) {}
}
channel.addRemoteDeviceListener(remoteDeviceListener)
channel.removeRemoteDeviceListener(remoteDeviceListener)10. Calls, Invitations, And Answering
val result = RKCooperation.getCallManager().invite(
channelId = channelId,
userIdList = arrayOf(targetUserId)
)
RKCooperation.getCallManager().cancel(channelId)
RKCooperation.getCallManager().reject(channelId)
RKCooperation.getCallManager().busy(channelId)Answer an incoming call:
RKCooperation.getCallManager().accept(
channelId = channelId,
defaultSubscribeMediaType = RKSubscribeMediaType.Both,
defaultStreamType = VideoSize.SIZE_SMALL,
onSuccess = {
// Enter the meeting page.
},
onFailed = {
// Handle failure.
},
timeoutSeconds = 10
)Incoming call listener:
private val incomingCallListener = object : RKIncomingCallListener {
override fun onReceiveCall(
channelId: String,
fromUserId: String,
createTime: Long,
channelTitle: String,
channelParam: RKChannelParam?
) {}
override fun onCallCanceled(channelId: String, fromUserId: String, createTime: Long) {}
}
RKCooperation.getCallManager().addIncomingCall(incomingCallListener)
RKCooperation.getCallManager().removeIncomingCall(incomingCallListener)11. Screen Sharing, Whiteboard, And AR Annotation
Sharing capabilities are exposed through RKChannel.getChannelShare().
val share = channel.getChannelShare()
val screenShareParam = ScreenShareParam(
10 * 1024,
24,
screenWidth * screenHeight
).apply {
width = screenWidth
height = screenHeight
}
share.startScreenShare(screenShareParam)
share.stopScreenShare()
share.getShareInfo()
share.addShareEventListener(shareListener)
share.removeShareEventListener(shareListener)Whiteboard:
share.startDoodle()
share.startDoodle(imageUrl)
val doodleView = share.getDoodleView()
share.stopDoodle()Video pointing, video control, and AR annotation:
share.inviteSharePointVideo(userId)
share.stopInviteSharePointVideo()
share.inviteShareVideoControl(userId)
share.stopInviteShareVideoControl()
share.inviteShareSlam(userId)
share.sendArSlamArrow(center, size, slamColor)
share.sendArSlamCircle(center, radius, slamColor)
share.sendArSlamPath(points, slamColor)
share.sendArSlamSticker(center, stickerType, slamColor)
share.sendArSlamImage(center, imageUrl, scale = 0.2f)
share.undoArSlam()
share.clearArSlam()12. Messages, Recording, Files, And Logs
Channel messages and custom properties:
channel.setCustomProperty(property)
val property = channel.getCustomProperty()
channel.sendChannelMessage(msg = message, toUserId = null)
channel.sendChannelMessage(msg = message, toUserId = targetUserId)
channel.sendChannelMessage(msg = message, toUserList = userIdList)
channel.addChannelMsgListener(channelMsgListener)Cloud recording:
RKCooperation.getChannelManager().setRecordStatusListener(recordStatusListener)
val startResult = RKCooperation.getChannelManager().startServerRecording(
channelId = channelId,
bucket = bucket,
fileName = fileName,
resolution = Resolution.RESOLUTION_720
)
val stopResult = RKCooperation.getChannelManager().stopServerRecording(
channelId = channelId,
save = true
)
val files = RKCooperation.getChannelManager().getServerRecordingFiles(channelId)Meeting file upload:
val result = channel.uploadMeetingFile(
localPath = localPath,
mimeType = mimeType,
fileName = fileName
)Video quality and network state:
channel.configVideoQuality(maxPublishBitrate = 2_000, maxDelay = 500)
channel.setVideoQualityListener(qualityListener)
val quality = channel.getUserNetworkQuality(userId)
val streamState = channel.getUserStreamState(userId)
RKCooperation.getRtcEngine().setVideoPublishBitrate(
bitrateMapping16to9,
bitrateMapping4to3
)Log upload:
val result = RKCooperation.getRtcEngine().uploadLog()13. Integration Notes
- Initialize the SDK once in the main application process.
- Do not create, join, or answer meetings before login succeeds.
- Pair every
addListenercall with the matchingremoveListenerwhen the page is destroyed or the workflow ends. - Use
RKChannel.getChannelShare()for in-meeting sharing capabilities. - Do not depend on internal SDK implementation classes. Use public interfaces such as
RKChannel,RKChannelShare, andRKCall. - Android 12 and above require explicit handling of
android:exported, Bluetooth permissions, and foreground service types. - Android 13 and above require
POST_NOTIFICATIONSif notifications are used. - If obfuscation or resource shrinking is enabled, verify login, joining, audio/video, calling, sharing, whiteboard, and file upload before release.