LiveListStore and LiveSeatStore.Core Concept | Type | Core Responsibilities & Description |
LiveListStore | abstract class | createLive(): Start live stream as host.endLive(): End live stream as host.joinLive(): Audience joins live room.leaveLive(): Leave live room. |
LiveInfo | data class | liveID: Unique room identifier.seatLayoutTemplateID: Layout template ID (e.g., 600 for dynamic grid). |
LiveSeatStore | abstract class | Core seat management class. Manages all seat information and seat-related operations in the room. Provides a real-time seat list data stream via liveSeatState.seatList. |
LiveSeatState | data class | Represents the current state of all seats. seatList: a StateFlow containing the real-time seat list.speakingUsers: users currently speaking and their volume. |
SeatInfo | data class | Data model for a single seat. The seat list (seatList) emitted by LiveSeatStore is a list of SeatInfo objects. Key fields: index: seat position.isLocked: whether the seat is locked.userInfo: user information for the seat. If the seat is empty, this field is empty. |
SeatUserInfo | data class | Detailed data model for the user occupying a seat. When a user successfully takes a seat, the userInfo field in SeatInfo is populated. Key fields: userID: unique user ID.userName: user nickname.avatarURL: user avatar URL.microphoneStatus: microphone status (on/off).cameraStatus: camera status (on/off). |
SDKAppID: Application identifier (required). Tencent Cloud uses SDKAppId for billing and details.SDKSecretKey: Application secret key, used to initialize the configuration file with secret information.
implementation 'com.tencent.atomicx:atomicxcore:latest' to your build.gradle file, then perform a Gradle Sync.dependencies {implementation 'io.trtc.uikit:atomicx-core:latest.release'api "io.trtc.uikit:rtc_room_engine:3.4.0.1306"api "io.trtc.uikit:atomicx-core:3.4.0.1307"api "com.tencent.liteav:LiteAVSDK_Professional:12.8.0.19279"api "com.tencent.imsdk:imsdk-plus:8.7.7201"// Other dependencies...}
LoginStore.shared.login in your project to complete authentication. This is required before using any functionality of AtomicXCore.LoginStore.shared.login after your app's own user authentication is successful to ensure clear and consistent login logic.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 SDKAppID"test_001", // Replace with your UserID"xxxxxxxxxxx", // Replace with your UserSigobject : CompletionHandler {override fun onSuccess() {// Handle login successLog.d("Login", "login success")}override fun onFailure(code: Int, desc: String) {// Handle login failureLog.e("Login", "login failed, code: $code, error: $desc")}})}}
Parameter | Type | Description |
sdkAppID | Int | |
userID | String | The unique ID for the current user. Must contain only English letters, numbers, hyphens, and underscores. |
userSig | String | A ticket for Tencent Cloud authentication. Please note: Development Environment: You can use the local GenerateTestUserSig.genTestSig function to generate a UserSig or generate a temporary UserSig via the UserSig Generation Tool.Production Environment: To prevent key leakage, you must use a server-side method to generate UserSig. For details, see Generating UserSig on the Server. For more information, see How to Calculate and Use UserSig. |
StoreActivity, create a LiveSeatStore instance. Observe changes in liveSeatState.seatList to get real-time mic seat data and update your UI.import android.os.Bundleimport android.util.Logimport androidx.appcompat.app.AppCompatActivityimport io.trtc.tuikit.atomicxcore.api.device.DeviceStoreimport io.trtc.tuikit.atomicxcore.api.live.LiveListStoreimport io.trtc.tuikit.atomicxcore.api.live.LiveSeatStoreimport kotlinx.coroutines.CoroutineScopeimport kotlinx.coroutines.Dispatchersimport kotlinx.coroutines.launch// YourHostActivity represents your Host Activityclass YourHostActivity : AppCompatActivity() {private lateinit var liveListStore: LiveListStoreprivate lateinit var liveSeatStore: LiveSeatStoreprivate lateinit var deviceStore: DeviceStoreprivate val liveID = "test_voice_room_001"override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_host) // Assume you have your own layout// 1. Initialize StoresliveListStore = LiveListStore.shared()liveSeatStore = LiveSeatStore.create(liveID)deviceStore = DeviceStore.shared()// 2. Listen for mic seat list changesobserveSeatList()}private fun observeSeatList() {// Listen for seatList changes and update your mic seat UICoroutineScope(Dispatchers.Main).launch {liveSeatStore.liveSeatState.seatList.collect { seatInfoList ->// Render your mic seat UI here based on seatInfoList// Example: updateMicSeatView(seatInfoList)Log.d("HostActivity", "Seat list updated: ${seatInfoList.size} seats")}}}}
openLocalMicrophone method from DeviceStore:import androidx.appcompat.app.AppCompatActivityimport io.trtc.tuikit.atomicxcore.api.device.DeviceStoreclass YourHostActivity : AppCompatActivity() {// ... Other code ...private fun openDevices() {// 1. Turn on the microphoneDeviceStore.shared().openLocalMicrophone(completion = null)}}
createLive method of LiveListStore:import android.os.Bundleimport android.util.Logimport androidx.appcompat.app.AppCompatActivityimport io.trtc.tuikit.atomicxcore.api.live.LiveInfoimport io.trtc.tuikit.atomicxcore.api.live.LiveInfoCompletionHandlerimport io.trtc.tuikit.atomicxcore.api.live.TakeSeatModeclass YourHostActivity : AppCompatActivity() {// ... Other code ...override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// ... Other code ...// Start voice chatstartLive()}private fun startLive() {val liveInfo = LiveInfo().apply {// 1. Set room idliveID = this@YourHostActivity.liveID// 2. Set room nameliveName = "test voice room"// 3. Configure as a voice chat room (enable mic seats)isSeatEnabled = true// 4. Host takes mic by defaultkeepOwnerOnSeat = true// 5. Set mic seat layout template (e.g., 70 for a 10-seat template)seatLayoutTemplateID = 70// 6. Set mic-taking mode, e.g., apply to take micseatMode = TakeSeatMode.APPLY// 7. Set maximum number of mic seatsmaxSeatCount = 10}// 8. Call createLive to start the streamliveListStore.createLive(liveInfo, object : LiveInfoCompletionHandler {override fun onFailure(code: Int, desc: String) {Log.e("Live", "Response startLive onError: $desc")}override fun onSuccess(liveInfo: LiveInfo) {Log.d("Live", "Response startLive onSuccess")// After successful creation, the Host is on the mic by default, now you can call unmuteMicrophoneliveSeatStore.unmuteMicrophone(null)}})}}
Parameter Name | Type | Required | Description |
liveID | String | Required | Unique identifier for the live room |
liveName | String | Optional | Title of the live room |
notice | String | Optional | Announcement information for the live room |
isMessageDisable | Boolean | Optional | Mute status ( true: muted, false: not muted) |
isPublicVisible | Boolean | Optional | Public visibility ( true: visible, false: hidden) |
isSeatEnabled | Boolean | Optional | Enable mic seat feature ( true: enabled, false: disabled) |
keepOwnerOnSeat | Boolean | Optional | Keep host on mic seat |
maxSeatCount | Int | Required | Maximum number of mic seats |
seatMode | Optional | Mic seat mode ( FREE: free to take seat, APPLY: apply to take seat) | |
seatLayoutTemplateID | Int | Required | Mic seat layout template ID |
coverURL | String | Optional | Cover image URL for the live room |
backgroundURL | String | Optional | Background image URL for the live room |
categoryList | List<Int> | Optional | Category tag list for the live room |
activityStatus | Int | Optional | Live activity status |
LiveSeatStore instance to observe changes in liveSeatState.seatList and update your UI in real time. In your Activity (such as YourAnchorActivity or YourAudienceActivity), observe the data as follows:import android.os.Bundleimport android.util.Logimport androidx.appcompat.app.AppCompatActivityimport kotlinx.coroutines.CoroutineScopeimport kotlinx.coroutines.Dispatchersimport kotlinx.coroutines.launchclass YourHostActivity : AppCompatActivity() {// ... Other code ...override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// ... Other code ...// Listen for seatList changesobserveSeatList()}private fun observeSeatList() {// Listen for seatList changes and update your mic seat UICoroutineScope(Dispatchers.Main).launch {liveSeatStore.liveSeatState.seatList.collect { seatInfoList ->// seatInfoList is the latest mic seat list (List<SeatInfo>), render your mic seat UI here based on seatInfoListLog.d("HostActivity", "Seat list updated: ${seatInfoList.size} seats")}}}}
endLive method of LiveListStore. The SDK will handle stopping the stream and destroying the room.import android.util.Logimport androidx.appcompat.app.AppCompatActivityimport com.tencent.cloud.tuikit.engine.extension.TUILiveListManagerimport io.trtc.tuikit.atomicxcore.api.live.StopLiveCompletionHandlerclass YourHostActivity : AppCompatActivity() {// ... Other code ...// End voice chatprivate fun stopLive() {liveListStore.endLive(object : StopLiveCompletionHandler {override fun onSuccess(statisticsData: TUILiveListManager.LiveStatisticsData) {Log.d("Live", "endLive success, duration: ${statisticsData.liveDuration}")}override fun onFailure(code: Int, desc: String) {Log.e("Live", "endLive error: $desc")}})}// Ensure this is also called when the Activity is destroyedoverride fun onDestroy() {super.onDestroy()stopLive()Log.d("Live", "YourHostActivity onDestroy")}}
Activity, create a LiveSeatStore instance and observe changes in liveSeatState.seatList to update the mic seat UI.import io.trtc.tuikit.atomicxcore.api.live.LiveListStoreimport io.trtc.tuikit.atomicxcore.api.live.LiveSeatStoreimport android.os.Bundleimport androidx.appcompat.app.AppCompatActivityimport kotlinx.coroutines.CoroutineScopeimport kotlinx.coroutines.Dispatchersimport kotlinx.coroutines.launchimport android.util.Log// YourAudienceActivity represents your Audience Activityclass YourAudienceActivity : AppCompatActivity() {private lateinit var liveListStore: LiveListStoreprivate lateinit var liveSeatStore: LiveSeatStoreprivate val liveID = "test_voice_room_001" // Ensure liveID matches the Host'soverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_audience) // Assume you have your own layout// 1. Initialize StoresliveListStore = LiveListStore.shared()liveSeatStore = LiveSeatStore.create(liveID)// 2. Listen for mic seat list changesobserveSeatList()}private fun observeSeatList() {// 3. Listen for seatList changes and update your mic seat UICoroutineScope(Dispatchers.Main).launch {liveSeatStore.liveSeatState.seatList.collect { seatInfoList ->// Render your mic seat UI here based on seatInfoList// Example: updateMicSeatView(seatInfoList)Log.d("AudienceActivity", "Seat list updated: ${seatInfoList.size} seats")}}}}
joinLive method of LiveListStore:import android.os.Bundleimport androidx.appcompat.app.AppCompatActivityimport android.util.Logimport io.trtc.tuikit.atomicxcore.api.live.LiveInfoimport io.trtc.tuikit.atomicxcore.api.live.LiveInfoCompletionHandler// YourAudienceActivity represents your Audience Activityclass YourAudienceActivity : AppCompatActivity() {// ... Other code ...override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_audience) // Assume you have your own layout// ... Other code ...// Enter voice chat roomjoinLive()}private fun joinLive() {// 1. Call joinLive to enter the voice chat roomliveListStore.joinLive(liveID, object : LiveInfoCompletionHandler {override fun onSuccess(liveInfo: LiveInfo) {Log.d("Live", "joinLive success")}override fun onFailure(code: Int, desc: String) {Log.e("Live", "joinLive error: $desc")}})}}
leaveLive method of LiveListStore:import android.util.Logimport androidx.appcompat.app.AppCompatActivityimport io.trtc.tuikit.atomicxcore.api.CompletionHandler// YourAudienceActivity represents your Audience Activityclass YourAudienceActivity : AppCompatActivity() {// ... Other code ...private fun leaveLive() {liveListStore.leaveLive(object : CompletionHandler {override fun onSuccess() {Log.d("Live", "leaveLive success")}override fun onFailure(code: Int, desc: String) {Log.e("Live", "leaveLive error: $desc")}})}// Ensure this is also called when the Activity is destroyedoverride fun onDestroy() {super.onDestroy()leaveLive()Log.d("Live", "YourAudienceActivity onDestroy")}}

LiveSeatStore provides a speakingUsers data stream for this purpose.
YourAnchorActivity, observe changes in speakingUsers and update the UI to reflect the speaking status:import android.os.Bundleimport android.util.Logimport androidx.appcompat.app.AppCompatActivityimport kotlinx.coroutines.CoroutineScopeimport kotlinx.coroutines.Dispatchersimport kotlinx.coroutines.launch// In YourHostActivity or YourAudienceActivityclass YourHostActivity : AppCompatActivity() {// ... (omitting other code) ...override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// ... (omitting other code) ...// Listen for speakingUsers changesobserveSpeakingUsersState()}private fun observeSpeakingUsersState() {// Listen for speakingUsers changes and update the "currently speaking" statusCoroutineScope(Dispatchers.Main).launch {liveSeatStore.liveSeatState.speakingUsers.collect { speakingUserSet ->// Pass the set of "currently speaking" user IDs to the UI, update UI stateLog.d("HostActivity", "Speaking users updated: ${speakingUserSet.size} users")}}}}
metaData feature of LiveListStore supports this use case.updateLiveMetaData API. AtomicXCore synchronizes these changes in real time to all participants. LiveListState.currentLive and listen for changes in metaData. When a relevant key is updated, parse its value and update your business logic.import io.trtc.tuikit.atomicxcore.api.LiveListStoreimport io.trtc.tuikit.atomicxcore.api.CompletionHandlerimport com.google.gson.Gsonimport io.trtc.tuikit.atomicxcore.api.MetaDataCompletionHandlerimport io.trtc.tuikit.atomicxcore.api.LiveListStore// 1. Define a background music model (using data class)data class MusicModel(val musicId: String,val musicName: String)// 2. Host side: Add a method to push background music in your Host business logicfun updateBackgroundMusic(music: MusicModel) {val gson = Gson()val jsonString = gson.toJson(music) ?: ""// The metaData to be updatedval metaData = hashMapOf("music_info" to jsonString)// Update metaDataLiveListStore.shared().updateLiveMetaData(metaData,object : CompletionHandler {override fun onSuccess() {print("Background music ${music.musicName} pushed successfully")}override fun onFailure(code: Int, desc: String) {print("Failed to push background music: $desc")}})}// 3. Audience side: Add a method to listen for background music changes in your Audience business logicprivate fun subscribeToDataUpdates() {CoroutineScope(Dispatchers.Main).launch {LiveListStore.shared().liveState.currentLive.map { it.metaData }.collect {val musicInfo = it["music_info"]// Refresh business state, e.g., play new background music}}}
Feature | Feature Description | Feature Stores | Implementation Guide |
Enable Audience to Take Mic Seat | Audience can apply to take a mic seat and interact with the host in real time. | ||
Host Cross-Room Connection & PK | Hosts from different rooms can connect for interaction or PK. | ||
Add Barrage Chat | Members in the room can send and receive real-time text messages. | ||
Build Gift System | Audience can send virtual gifts to hosts to increase engagement and fun. |
Store/Component | Feature Description | API Documentation |
LiveListStore | Manages the full lifecycle of live rooms: create, join, leave, destroy rooms; query room list; modify live info (name, announcement, etc.); listen to live status (such as being kicked out, ended). | |
LiveSeatStore | Core mic seat management: manage mic seat list, user status, seat operations (take seat, leave seat, kick, lock, toggle microphone/camera, etc.), listen to mic seat events. | |
DeviceStore | Audio/video device control: microphone (toggle/volume), camera (toggle/switch/quality), screen sharing, real-time device status monitoring. | |
CoGuestStore | Audience co-host management: co-host application/invitation/approval/rejection, member permission control (microphone/camera), status synchronization. | |
CoHostStore | Host cross-room connection: supports multiple layout templates (dynamic grid, etc.), initiate/accept/reject connection, manage co-host interaction. | |
BattleStore | Host PK battle: initiate PK (set duration/opponent), manage PK status (start/end), synchronize scores, listen to battle results. | |
GiftStore | Gift interaction: get gift list, send/receive gifts, listen to gift events (including sender and gift details). | |
BarrageStore | Bullet chat feature: send text/custom barrage, maintain barrage list, real-time barrage status monitoring. | |
LikeStore | Like interaction: send likes, listen to like events, synchronize total like count. | |
LiveAudienceStore | Audience management: get real-time audience list (ID/name/avatar), count audience number, listen to audience join/leave events. | |
AudioEffectStore | Audio effects: voice changer (child/male), reverb (KTV, etc.), ear monitor adjustment, real-time effect switching. |
DeviceStore.shared().openLocalMicrophone(null) to enable the microphone.LiveSeatStore instance with the same liveID before calling createLive or joinLive (LiveSeatStore.create(liveID)).liveSeatStore.liveSeatState.seatList data stream.createLive (host) or joinLive (audience) was successfully called (check the onSuccess callback).ååFeedback