AtomicXCore, enabling developers to quickly build multi-party audio/video conference rooms. The SDK follows a pure API architecture, giving you full control over UI customization while letting you focus on business logic and user experience.
RoomStore: Centralized room management, including scheduling, creating, joining rooms, and in-room calling.RoomParticipantStore: Participant management within a room, covering admin settings, host transfer, removing participants, device control, and more.RoomParticipantView: Video view for displaying participant streams within the room.dependencies {implementation 'io.trtc.uikit:atomicx-core:3.6.1.66'api "com.tencent.imsdk:imsdk-plus:8.7.7201"}
LoginStore.shared.login in your project to authenticate. This step is required before using any feature of AtomicXCore.LoginStore.shared.login only after your own user account login succeeds, to ensure clear and consistent login flow.import android.os.Bundleimport androidx.appcompat.app.AppCompatActivityimport io.trtc.tuikit.atomicxcore.api.login.LoginStoreimport io.trtc.tuikit.atomicxcore.api.CompletionHandlerimport android.util.Logclass MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)LoginStore.shared.login(this, // context1400000001, // Replace with your project's sdkAppID"test_001", // Replace with your project's userID"xxxxxxxxxxx", // Replace with your project's userSigobject : CompletionHandler {override fun onSuccess() {// Login succeededLog.d("Login", "login success");}override fun onFailure(code: Int, desc: String) {// Login failedLog.e("Login", "login failed, code: $code, error: $desc");}})}}
Parameter | Type | Description |
sdkAppID | Int32 | |
userID | String | Unique user identifier. Use only English letters, numbers, hyphens, and underscores. Avoid using simple IDs like 1 or 123 to prevent multi-device login conflicts. |
userSig | String | Authentication ticket for Tencent Cloud. For development: Use GenerateTestUserSig.genTestSig or the UserSig Assistant Tool for a temporary UserSig.For production: Always generate UserSig server-side to prevent secret key leaks. See Calculating UserSig on the Server. |

CreateRoomOptions to set the room name and password.RoomStore.createAndJoinRoom to perform the combined operation.import android.os.Bundleimport android.util.Logimport androidx.appcompat.app.AppCompatActivityimport io.trtc.tuikit.atomicxcore.api.CompletionHandlerimport io.trtc.tuikit.atomicxcore.api.room.CreateRoomOptionsimport io.trtc.tuikit.atomicxcore.api.room.RoomStoreimport io.trtc.tuikit.atomicxcore.api.room.RoomTypeclass RoomMainActivity : AppCompatActivity() {private val roomID = "test_room_001"private val roomType = RoomType.STANDARDoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)createAndJoinRoom()}private fun createAndJoinRoom() {// 1. Configure room initialization parametersval options = CreateRoomOptions()options.roomName = "My Discussion" // Room display nameoptions.password = "" // Room entry password (leave blank if not needed)// 2. Preset room permissions for all members (commonly used for formal meetings)options.isAllCameraDisabled = falseoptions.isAllMessageDisabled = falseoptions.isAllMicrophoneDisabled = falseoptions.isAllScreenShareDisabled = false// 3. Create and join room// If the room does not exist, it is created and joined automaticallyRoomStore.shared().createAndJoinRoom(roomID, roomType, options, object : CompletionHandler {override fun onSuccess() {// Room created and joined successfully. You can now subscribe to room status or open local camera/microphone.Log.d("Room", "Room created and joined successfully")}override fun onFailure(code: Int, desc: String) {// Room creation/join failed (possible permission, network, or parameter errors)Log.e("Room", "Failed to create and join room [Error code: $code]: $desc")}})}}
Parameter Name | Type | Required | Description |
roomID | String | Yes | Unique room identifier. Length: 0-48 bytes. Use only numbers, English letters (case-sensitive), underscores (_), hyphens (-). Avoid spaces and Chinese characters. |
roomType | RoomType | Yes | Room type: STANDARD: Standard room (default).WEBINAR: Large seminar room.Use STANDARD for most multi-party conferences. |
options | CreateRoomOptions | Yes | Room creation configuration object. For usage details, see CreateRoomOptions struct documentation. |
completion | CompletionHandler | No | Callback for room creation/join result. Returns error code and message on failure. |
Parameter Name | Type | Required | Description |
roomName | String | No | Room name (optional, defaults to empty). Length: 0-60 bytes. Supports English, Chinese, numbers, special characters. |
password | String | No | Room password (empty string means no password). Length: 0-32 bytes. Recommended: 4-8 digit numbers for easy mobile input. If set, users must enter password to join. Avoid storing sensitive info in plaintext. |
isAllMicrophoneDisabled | Boolean | No | Disable microphones for all members: True: disabled. False: allowed (default). |
isAllCameraDisabled | Boolean | No | Disable cameras for all: True: disabled. False: allowed (default). |
isAllScreenShareDisabled | Boolean | No | Disable screen sharing for all: True: disabled. False: allowed (default). |
isAllMessageDisabled | Boolean | No | Mute all chat messages: True: disabled. False: allowed (default). |
openLocalCamera and openLocalMicrophone from DeviceStore.import android.os.Bundleimport androidx.appcompat.app.AppCompatActivityimport io.trtc.tuikit.atomicxcore.api.device.DeviceStoreclass RoomMainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)openDevices()}private fun openDevices() {// Open front cameraDeviceStore.shared().openLocalCamera(true, completion = null)// Open microphoneDeviceStore.shared().openLocalMicrophone(completion = null)}}
Parameter Name | Type | Required | Description |
isFront | Boolean | Yes | Enable the front camera. true: Front camera. false: Rear camera. |
completion | CompletionHandler | No | Callback for camera open result. Returns error code and message if failed. |
endRoom from RoomStore. All participants are notified when the room ends.import android.os.Bundleimport android.util.Logimport androidx.appcompat.app.AppCompatActivityimport io.trtc.tuikit.atomicxcore.api.CompletionHandlerimport io.trtc.tuikit.atomicxcore.api.room.RoomStoreclass RoomMainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)endRoom()}private fun endRoom() {// Permanently end the current room. Usually only the host can perform this action.// All members are removed and audio/video capture is stopped.RoomStore.shared().endRoom(object : CompletionHandler {override fun onSuccess() {Log.d("Room", "Room ended successfully")}override fun onFailure(code: Int, desc: String) {Log.e("Room", "Failed to end room [Error code: $code]: $desc")}})}}

joinRoom from RoomStore to enter a room. Other users will receive a participant join notification.import android.os.Bundleimport android.util.Logimport androidx.appcompat.app.AppCompatActivityimport io.trtc.tuikit.atomicxcore.api.CompletionHandlerimport io.trtc.tuikit.atomicxcore.api.room.RoomStoreimport io.trtc.tuikit.atomicxcore.api.room.RoomTypeclass RoomMainActivity : AppCompatActivity() {private val roomID = "test_room_001"private val roomType = RoomType.STANDARDoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)joinRoom()}private fun joinRoom() {// Prepare join parametersval targetRoomID = this.roomIDval roomPassword = "" // If not set, use empty string or null// Join an existing room. This checks room existence, ban status, and password.RoomStore.shared().joinRoom(targetRoomID, roomType, roomPassword, object : CompletionHandler {override fun onSuccess() {Log.d("Room", "Joined room successfully")}override fun onFailure(code: Int, desc: String) {Log.e("Room", "Failed to join room [Error code: $code]: $desc")}})}}
Parameter Name | Type | Required | Description |
roomID | String | Yes | Unique room identifier. Length: 0-48 bytes. Use only numbers, English letters (case-sensitive), underscores (_), hyphens (-). Avoid spaces and Chinese characters. |
roomType | RoomType | Yes | Room type: STANDARD: Standard room (default).WEBINAR: Large seminar room.Use STANDARD for multi-party conferences. |
password | String | No | Room password (empty string means no password). Length: 0-32 bytes. Recommended: 4-8 digit numbers for easy input. If set, users must enter the password. Avoid storing sensitive info in plaintext. |
completion | CompletionHandler | No | Callback for join result. Returns error code and message if failed. |
leaveRoom from RoomStore. Other participants will be notified when someone leaves.import android.os.Bundleimport android.util.Logimport androidx.appcompat.app.AppCompatActivityimport io.trtc.tuikit.atomicxcore.api.CompletionHandlerimport io.trtc.tuikit.atomicxcore.api.room.RoomStoreclass RoomMainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)leaveRoom()}private fun leaveRoom() {// leaveRoom is for regular members or the host to leave the room.// Unlike endRoom, calling leaveRoom as host only removes you; the room remains.RoomStore.shared().leaveRoom(object : CompletionHandler {override fun onSuccess() {Log.d("Room", "Left room successfully")}override fun onFailure(code: Int, desc: String) {Log.e("Room", "Failed to leave room [Error code: $code]: $desc")}})}}
RoomParticipantView component in AtomicXCore SDK provides a complete solution for video rendering. It supports real-time display of both local camera feeds and remote participant streams, and is easy to integrate.
RoomParticipantView is the primary view for rendering participant video streams. For more flexible layouts, see TUIRoomKit, especially RoomMainView.kt.RoomParticipantStore.state.participantList for participant state changes.RoomParticipantView instances based on participant data and bind video logic.import android.os.Bundleimport android.widget.FrameLayoutimport androidx.appcompat.app.AppCompatActivityimport androidx.lifecycle.lifecycleScopeimport io.trtc.tuikit.atomicxcore.api.room.RoomParticipantimport io.trtc.tuikit.atomicxcore.api.room.RoomParticipantStoreimport io.trtc.tuikit.atomicxcore.api.view.RoomParticipantViewimport io.trtc.tuikit.atomicxcore.api.view.VideoStreamTypeimport kotlinx.coroutines.launchclass RoomMainActivity : AppCompatActivity() {private val roomID = "test_room_001"private lateinit var container: FrameLayoutprivate val cellSize by lazy { resources.displayMetrics.widthPixels / 3 }// RoomParticipantStore must be created for each room: RoomParticipantStore.create(roomID: String)private val participantStore = RoomParticipantStore.create(roomID)override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)container = FrameLayout(this)setContentView(container)subscribeParticipantState()participantStore.getParticipantList("", null)}private fun subscribeParticipantState() {lifecycleScope.launch {participantStore.state.participantList.collect { participants ->updateParticipantView(participants)}}}private fun updateParticipantView(list: List<RoomParticipant>) {container.removeAllViews()list.take(9).forEachIndexed { index, participant ->val view = RoomParticipantView(this@RoomMainActivity).apply {init(VideoStreamType.CAMERA, participant)}val params = FrameLayout.LayoutParams(cellSize, cellSize).apply {leftMargin = (index % 3) * cellSizetopMargin = (index / 3) * cellSize}view.setActive(true)container.addView(view, params)}}}
Parameter Name | Type | Required | Description |
streamType | VideoStreamType | Yes | Video stream type: CAMERA: Camera stream.SCREEN: Screen sharing stream. |
participant | RoomParticipant | Yes | Real-time participant object, includes identity, status, device permissions. |
Parameter Name | Type | Required | Description |
userID | String | Yes | Unique user identifier. |
userName | String | No | User nickname. |
avatarURL | String | No | URL of user's avatar. |
nameCard | String | No | User's name card/remark. Length: 0-32 bytes. Supports English, Chinese, numbers, special characters. |
role | ParticipantRole | No | Role in room: OWNER: Host.ADMIN: Admin.GENERAL_USER: Regular user (default) |
roomStatus | RoomParticipantStatus | No | Business status: SCHEDULED: Scheduled (default).IN_CALLING: Calling.CALL_TIMEOUT: Timeout.CALL_REJECTED: Rejected.IN_ROOM: In room . |
microphoneStatus | DeviceStatus | No | Microphone status: OFF: Off (default). ON: On. |
cameraStatus | DeviceStatus | No | Camera status: OFF: Off (default). ON: On. |
screenShareStatus | DeviceStatus | No | Screen sharing status: OFF: Off (default). ON: On. |
isMessageDisabled | Boolean | No | Muted status: True: disabled. False: enabled (default). |
metaData | MutableMap | No | Business custom extension data, synchronized with participant state. Limit: 0-60 bytes. Supports only JSON string. |
RoomStore.addRoomListener. Implement the RoomListener interface to handle events.import android.os.Bundleimport android.util.Logimport androidx.appcompat.app.AppCompatActivityimport io.trtc.tuikit.atomicxcore.api.room.RoomInfoimport io.trtc.tuikit.atomicxcore.api.room.RoomListenerimport io.trtc.tuikit.atomicxcore.api.room.RoomStoreclass RoomMainActivity : AppCompatActivity() {// RoomListener receives room lifecycle events: calling, dissolution, scheduling reminders, etc.private val roomListener = object : RoomListener() {override fun onRoomEnded(roomInfo: RoomInfo) {Log.d("Room", "Current room has ended")}// ... handle other RoomListener events ...}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)subscribeRoomEvents()}private fun subscribeRoomEvents() {RoomStore.shared().addRoomListener(roomListener)}override fun onDestroy() {super.onDestroy()// Remove listener to prevent memory leaksRoomStore.shared().removeRoomListener(roomListener)}}
Demo effect | ![]() |
Multi-User Room Feature | Feature Description | Implementation Guide |
Update Room Information | Host can update room details, such as name and password. | |
In-Meeting Calling | Host or admin can invite users who are not in the room to join. | |
Room Scheduling | Schedule rooms in advance, set start/end times, and add participants. | |
In-Room Member Management | Host can manage participants: assign admins, remove users, control individual audio/video. |
Store/Component | Feature Description | API Documentation |
RoomStore | Complete room lifecycle management: create & join, join, leave, end room, update/get room info, scheduling, invite members, listen for room events | |
RoomParticipantStore | Participant management: assign admin, transfer host, get participant list, remove from room, control devices, apply for device access | |
RoomParticipantView | Single participant video view: bind/update participant info, update stream type, set active state, etc. |

allowBackup attribute in their AndroidManifest.xml.allowBackup attribute from your project's AndroidManifest.xml or set it to false to disable backup/restore. Add tools:replace="android:allowBackup" to the application node to enforce your own setting. See the example below:
setActive: Make sure RoomParticipantView is visible and you called RoomParticipantView.setActive(true).cameraStatus of the bound RoomParticipant is ON.<uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.RECORD_AUDIO" />
import android.Manifestimport android.content.pm.PackageManagerimport android.os.Bundleimport android.util.Logimport androidx.appcompat.app.AppCompatActivityimport androidx.core.app.ActivityCompatimport androidx.core.content.ContextCompatimport io.trtc.tuikit.atomicxcore.api.device.DeviceStoreclass RoomMainActivity : AppCompatActivity() {private val PERMISSION_REQUEST_CODE = 1001override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)checkAndRequestPermissions()}private fun checkAndRequestPermissions() {val permissions = arrayOf(Manifest.permission.CAMERA,Manifest.permission.RECORD_AUDIO)val permissionsToRequest = permissions.filter {ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED}if (permissionsToRequest.isNotEmpty()) {ActivityCompat.requestPermissions(this,permissionsToRequest.toTypedArray(),PERMISSION_REQUEST_CODE)} else {// Permissions granted, can open devicesopenDevices()}}override fun onRequestPermissionsResult(requestCode: Int,permissions: Array<out String>,grantResults: IntArray) {super.onRequestPermissionsResult(requestCode, permissions, grantResults)if (requestCode == PERMISSION_REQUEST_CODE) {if (grantResults.all { it == PackageManager.PERMISSION_GRANTED }) {// All permissions granted, call openDevices()openDevices()} else {// Some permissions deniedLog.e("Permission", "Some permissions denied")}}}private fun openDevices() {// Open front cameraDeviceStore.shared().openLocalCamera(isFront = true, completion = null)// Open microphoneDeviceStore.shared().openLocalMicrophone(completion = null)}
FOREGROUND_SERVICE, FOREGROUND_SERVICE_CAMERA, and FOREGROUND_SERVICE_MICROPHONE permissions and service in AndroidManifest.xml.<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /><uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA" /><uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" /><serviceandroid:name=".MediaCaptureService"android:foregroundServiceType="camera|microphone" />
import android.app.NotificationChannelimport android.app.NotificationManagerimport android.app.Serviceimport android.content.Intentimport android.content.pm.ServiceInfoimport android.os.Bundleimport android.os.IBinderimport androidx.appcompat.app.AppCompatActivityimport androidx.core.app.NotificationCompatclass MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)startForegroundService(Intent(this, MediaCaptureService::class.java))}}class MediaCaptureService : Service() {override fun onCreate() {super.onCreate()// Create notification channelval channel = NotificationChannel("media", "Media Capture", NotificationManager.IMPORTANCE_LOW)getSystemService(NotificationManager::class.java).createNotificationChannel(channel)// Build notificationval notification = NotificationCompat.Builder(this, "media").setContentTitle("In Audio/Video Call").setSmallIcon(android.R.drawable.ic_menu_call).build()// Start foreground service and specify camera/microphone type (required for Android 14+)startForeground(1, notification,ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA or ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE)}override fun onBind(intent: Intent?): IBinder? = null}
Was this page helpful?
You can also Contact sales or Submit a Ticket for help.
Help us improve! Rate your documentation experience in 5 mins.
Feedback