Android SDK
TgoRTC Android (Kotlin) SDK for real-time audio/video communication based on LiveKit.
Installation
Add the JitPack repository to your build.gradle.kts (Project):
allprojects {
repositories {
maven { url = uri("https://jitpack.io") }
}
}
Add the dependency in your build.gradle.kts (Module):
dependencies {
implementation("com.github.TgoRTC:TgoRTCSDK:1.0.0")
}
Dependencies
The SDK automatically includes the following core dependency:
io.livekit:livekit-android:2.23.1
Quick Start
1. Initialize SDK
import com.tgo.rtc.TgoRTC
import com.tgo.rtc.entity.TgoOptions
val options = TgoOptions().apply {
debug = true
mirror = false
}
TgoRTC.instance.init(applicationContext, options)
2. Create Room Info and Join
import com.tgo.rtc.entity.TgoRoomInfo
import com.tgo.rtc.entity.TgoRTCType
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
val scope = MainScope()
val roomInfo = TgoRoomInfo(
roomName = "room-name",
token = "your-token",
url = "http://your-server",
loginUID = "local-user-id",
creatorUID = "creator-user-id"
)
roomInfo.maxParticipants = 4
roomInfo.rtcType = TgoRTCType.VIDEO
roomInfo.timeout = 30
scope.launch {
TgoRTC.instance.roomManager.joinRoom(
roomInfo,
micEnabled = true,
cameraEnabled = true
)
}
3. Listen to Connection Status
import com.tgo.rtc.entity.TgoConnectStatus
val connectListener = { roomName: String, status: TgoConnectStatus, reason: String ->
println("Room $roomName: $status - $reason")
when (status) {
TgoConnectStatus.CONNECTING -> println("Connecting...")
TgoConnectStatus.CONNECTED -> println("Connected to room")
TgoConnectStatus.DISCONNECTED -> println("Disconnected from room")
}
}
TgoRTC.instance.roomManager.addConnectListener(connectListener)
TgoRTC.instance.roomManager.removeConnectListener(connectListener)
Note:
The current Android SDK does not expose separate RECONNECTING or RECONNECTED enum values.
RoomEvent.Reconnecting is currently reported as TgoConnectStatus.CONNECTING by TgoRoomManager.
4. Get Participants
val local = TgoRTC.instance.participantManager.getLocalParticipant()
val localOrNull = TgoRTC.instance.participantManager.getLocalParticipantOrNull()
val remotes = TgoRTC.instance.participantManager.getRemoteParticipants()
val joinedRemotes = TgoRTC.instance.participantManager.getJoinedRemoteParticipants()
val all = TgoRTC.instance.participantManager.getAllParticipants()
val joined = TgoRTC.instance.participantManager.getJoinedParticipants()
val joinedCount = TgoRTC.instance.participantManager.getJoinedParticipantCount()
TgoRTC.instance.participantManager.addNewParticipantListener { participant ->
println("New participant joined: ${participant.uid}")
}
5. Media Control and Events
Media control is only available for local participants.
import com.tgo.rtc.entity.TgoConnectionQuality
import com.tgo.rtc.entity.TgoVideoInfo
val participant = TgoRTC.instance.participantManager.getLocalParticipant()
scope.launch {
participant.setMicrophoneEnabled(true)
}
scope.launch {
participant.setCameraEnabled(true)
}
scope.launch {
participant.setScreenShareEnabled(true)
}
participant.switchCamera()
val micEnabled = participant.getMicrophoneEnabled()
val cameraEnabled = participant.getCameraEnabled()
val screenShareEnabled = participant.getScreenShareEnabled()
val cameraPosition = participant.getCameraPosition()
val isSpeaking = participant.getIsSpeaking()
val audioLevel = participant.getAudioLevel()
val createdAt = participant.getCreatedAt()
val isJoined = participant.isJoined()
val onMicChange: (Boolean) -> Unit = { enabled ->
println("Microphone: ${if (enabled) "on" else "off"}")
}
val onCameraChange: (Boolean) -> Unit = { enabled ->
println("Camera: ${if (enabled) "on" else "off"}")
}
val onScreenShareChange: (Boolean) -> Unit = { enabled ->
println("Screen share: ${if (enabled) "on" else "off"}")
}
val onSpeakingChange: (Boolean, Float) -> Unit = { speaking, level ->
println("Speaking: $speaking, Level: $level")
}
val onConnQualityChange: (TgoConnectionQuality) -> Unit = { quality ->
println("Connection quality: $quality")
}
val onJoined: () -> Unit = {
println("Participant joined")
}
val onLeave: () -> Unit = {
println("Participant left")
}
val onTrackPublished: () -> Unit = {
println("Track published")
}
val onTrackUnpublished: () -> Unit = {
println("Track unpublished")
}
val onVideoInfoChange: (TgoVideoInfo) -> Unit = { info ->
println("Video info: ${info.resolutionString}, ${info.bitrateString}")
}
participant.addMicrophoneStatusListener(onMicChange)
participant.addCameraStatusListener(onCameraChange)
participant.addScreenShareStatusListener(onScreenShareChange)
participant.addSpeakingListener(onSpeakingChange)
participant.addConnQualityListener(onConnQualityChange)
participant.addJoinedListener(onJoined)
participant.addLeaveListener(onLeave)
participant.addTrackPublishedListener(onTrackPublished)
participant.addTrackUnpublishedListener(onTrackUnpublished)
participant.addVideoInfoListener(onVideoInfoChange)
participant.removeMicrophoneStatusListener(onMicChange)
participant.removeCameraStatusListener(onCameraChange)
participant.removeScreenShareStatusListener(onScreenShareChange)
participant.removeSpeakingListener(onSpeakingChange)
participant.removeConnQualityListener(onConnQualityChange)
participant.removeJoinedListener(onJoined)
participant.removeLeaveListener(onLeave)
participant.removeTrackPublishedListener(onTrackPublished)
participant.removeTrackUnpublishedListener(onTrackUnpublished)
participant.removeVideoInfoListener(onVideoInfoChange)
6. Render Video Track
Add TgoVideoRenderer in your layout XML:
<com.tgo.rtc.track.TgoVideoRenderer
android:id="@+id/videoRenderer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Initialize in your Activity or Fragment:
import com.tgo.rtc.track.TgoRendererType
import com.tgo.rtc.track.TgoVideoRenderer
import com.tgo.rtc.track.TgoVideoScaleType
import io.livekit.android.room.track.Track
val renderer = findViewById<TgoVideoRenderer>(R.id.videoRenderer)
renderer.init()
renderer.setParticipant(participant)
renderer.setMirror(true)
renderer.setRendererType(TgoRendererType.TEXTURE_VIEW)
renderer.setScaleType(TgoVideoScaleType.FILL)
renderer.setTrackSource(Track.Source.CAMERA)
7. Audio Management
import com.tgo.rtc.entity.TgoAudioDevice
import com.tgo.rtc.entity.TgoAudioDeviceType
val devices = TgoRTC.instance.audioManager.getAudioOutputDevices()
val selected = TgoRTC.instance.audioManager.getSelectedDevice()
val deviceListener: (List<TgoAudioDevice>, TgoAudioDevice?) -> Unit = { available, current ->
println("Available devices: $available")
println("Current device: $current")
}
TgoRTC.instance.audioManager.addDeviceChangeListener(deviceListener)
selected?.let { TgoRTC.instance.audioManager.selectDevice(it) }
TgoRTC.instance.audioManager.selectDeviceByType(TgoAudioDeviceType.SPEAKER)
TgoRTC.instance.audioManager.toggleSpeakerphone()
TgoRTC.instance.audioManager.setSpeakerphoneOn(true)
val isSpeakerOn = TgoRTC.instance.audioManager.isSpeakerOn()
val hasBluetooth = TgoRTC.instance.audioManager.isBluetoothConnected()
val hasWiredHeadset = TgoRTC.instance.audioManager.isWiredHeadsetConnected()
val canSwitchSpeaker = TgoRTC.instance.audioManager.canSwitchSpeakerphone()
TgoRTC.instance.audioManager.removeDeviceChangeListener(deviceListener)
8. Leave Room
TgoRTC.instance.roomManager.leaveRoom()
API Reference
TgoRTC
| Property | Type | Description |
|---|---|---|
instance | TgoRTC | Singleton instance |
options | TgoOptions | SDK configuration |
roomManager | TgoRoomManager | Room management |
participantManager | TgoParticipantManager | Participant management |
audioManager | TgoAudioManager | Audio management |
TgoRoomManager
| Method | Description |
|---|---|
joinRoom(roomInfo, micEnabled, cameraEnabled) | Join a room (suspend) |
leaveRoom() | Leave current room |
addConnectListener(listener) | Add connection status listener |
removeConnectListener(listener) | Remove connection status listener |
addVideoInfoListener(listener) | Add video info listener |
removeVideoInfoListener(listener) | Remove video info listener |
isCalling() | Whether a call is active |
TgoParticipantManager
| Method | Description |
|---|---|
getLocalParticipantOrNull() | Get local participant, returns null if unavailable |
getLocalParticipant() | Get local participant |
getRemoteParticipants(includePending) | Get remote participants |
getAllParticipants(includePending) | Get all participants |
getJoinedParticipants() | Get joined participants |
getJoinedRemoteParticipants() | Get joined remote participants |
getJoinedParticipantCount() | Get joined participant count |
inviteParticipant(roomName, uids) | Invite participants by UID |
removePendingParticipants(roomName?, uids) | Remove pending participants who have not joined |
addNewParticipantListener(listener) | Listen for new participants |
removeNewParticipantListener(listener) | Remove new participant listener |
TgoParticipant
Media Control Methods (Local Only)
| Method | Description |
|---|---|
setMicrophoneEnabled(enabled) | Enable/disable microphone (suspend) |
setCameraEnabled(enabled) | Enable/disable camera (suspend) |
setScreenShareEnabled(enabled) | Enable/disable screen share (suspend) |
switchCamera() | Switch front/back camera |
Status Methods
| Method | Description |
|---|---|
getMicrophoneEnabled() | Get microphone status |
getCameraEnabled() | Get camera status |
getScreenShareEnabled() | Get screen share status |
getCameraPosition() | Get camera position (front/back) |
getAudioLevel() | Get current audio level (0.0 - 1.0) |
getIsSpeaking() | Check if currently speaking |
getVideoTrack(source) | Get video track |
getCreatedAt() | Get participant wrapper creation time |
isJoined() | Whether the participant has joined |
Event Listener Methods
| Method | Description |
|---|---|
addMicrophoneStatusListener(listener) | Listen for microphone status changes |
addCameraStatusListener(listener) | Listen for camera status changes |
addSpeakerStatusListener(listener) | Listen for speaker status changes |
addScreenShareStatusListener(listener) | Listen for screen share status changes |
addSpeakingListener(listener) | Listen for speaking status and volume |
addCameraPositionListener(listener) | Listen for camera position changes |
addConnQualityListener(listener) | Listen for connection quality changes |
addJoinedListener(listener) | Listen for participant join |
addLeaveListener(listener) | Listen for participant leave |
addTrackPublishedListener(listener) | Listen for track published events |
addTrackUnpublishedListener(listener) | Listen for track unpublished events |
addVideoInfoListener(listener) | Listen for video info changes |
remove...Listener(listener) | Remove corresponding listener |
Properties
| Property | Description |
|---|---|
uid | Participant UID |
isLocal | Whether this is the local participant |
TgoVideoRenderer (View)
| Method | Description |
|---|---|
init() | Initialize renderer |
init(room) | Initialize renderer with a specific Room |
setParticipant(participant) | Set participant to render |
setVideoTrack(track) | Set video track directly |
setMirror(mirror) | Set mirror mode |
setRendererType(type) | Set renderer type (SurfaceView/TextureView) |
setScaleType(type) | Set video scale type (FILL/FIT) |
setTrackSource(source) | Set track source (CAMERA/SCREEN_SHARE) |
release() | Release resources |
TgoAudioManager
| Method | Description |
|---|---|
addDeviceChangeListener(listener) | Listen for output device changes |
removeDeviceChangeListener(listener) | Remove device change listener |
getAudioOutputDevices() | Get available output devices |
getSelectedDevice() | Get currently selected output device |
selectDevice(device) | Select a specific output device |
selectDeviceByType(type) | Select an output device by type |
isWiredHeadsetConnected() | Whether a wired headset is connected |
isBluetoothConnected() | Whether a Bluetooth audio device is connected |
isSpeakerOn() | Whether speaker output is currently selected |
setSpeakerphoneOn(on) | Set speakerphone state |
toggleSpeakerphone() | Toggle speakerphone |
canSwitchSpeakerphone() | Whether speakerphone switching is supported |
Enums
TgoConnectStatus
enum class TgoConnectStatus {
CONNECTING,
CONNECTED,
DISCONNECTED
}
TgoRTCType
enum class TgoRTCType {
AUDIO,
VIDEO
}
TgoConnectionQuality
enum class TgoConnectionQuality {
UNKNOWN,
EXCELLENT,
GOOD,
POOR,
LOST
}
TgoCameraPosition
enum class TgoCameraPosition {
FRONT,
BACK
}
TgoRoomInfo Class
Configuration class for room connections.
| Property | Description |
|---|---|
roomName | Room name |
token | LiveKit token |
url | LiveKit server URL |
loginUID | Current user ID |
creatorUID | Room creator ID |
maxParticipants | Max participants (default 2) |
rtcType | Call type (default AUDIO) |
isP2P | Whether P2P mode is enabled (default true) |
uidList | Participant UID list |
timeout | Join timeout in seconds (default 30) |
Configuration Options
class TgoOptions {
var mirror: Boolean = false
var debug: Boolean = true
}
Platform Configuration
Permissions
Add the following permissions in AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
For Android 12 (API 31) and above, if using Bluetooth headphones, you also need:
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
Handling Pending Participants
The current Android SDK does not expose participant-level timeout callbacks like participant.addTimeoutListener(...).
Instead, TgoRoomManager checks pending participants based on roomInfo.timeout and removes expired entries through
TgoParticipantManager.removePendingParticipants(...).
If your business logic already knows which invited users did not answer, you can also remove them manually:
TgoRTC.instance.participantManager.removePendingParticipants(
roomName = roomInfo.roomName,
uids = listOf("user_b", "user_c")
)