Kotlin SDK
Build native Android video applications with Kotlin
Installation
Add BaxCloud SDK to your Android project
Add to build.gradle.kts (module level)
1dependencies {
2 implementation("com.baxcloud:client:1.0.0")
3}Android Configuration
Required permissions and runtime requests
Add to AndroidManifest.xml
1<uses-permission android:name="android.permission.CAMERA" />
2<uses-permission android:name="android.permission.RECORD_AUDIO" />
3<uses-permission android:name="android.permission.INTERNET" />Request Runtime Permissions
1import android.Manifest
2import android.content.pm.PackageManager
3import androidx.core.app.ActivityCompat
4import androidx.core.content.ContextCompat
5
6fun requestPermissions(activity: Activity) {
7 val permissions = arrayOf(
8 Manifest.permission.CAMERA,
9 Manifest.permission.RECORD_AUDIO
10 )
11
12 if (permissions.any {
13 ContextCompat.checkSelfPermission(activity, it)
14 != PackageManager.PERMISSION_GRANTED
15 }) {
16 ActivityCompat.requestPermissions(
17 activity,
18 permissions,
19 REQUEST_CODE
20 )
21 }
22}Quick Start
Get started with Kotlin SDK
1. Initialize Client
1import com.baxcloud.client.BaxCloudClient
2import com.baxcloud.client.BaxCloudConfig
3
4val client = BaxCloudClient(
5 context = applicationContext,
6 config = BaxCloudConfig(
7 projectId = "your-project-id",
8 apiKey = "your-api-key"
9 )
10)2. Connect to a Room
1import kotlinx.coroutines.launch
2import com.baxcloud.client.*
3
4lifecycleScope.launch {
5 try {
6 val room = client.connect(
7 BaxcloudRoomOptions(
8 roomName = "my-room",
9 participant = BaxcloudUser(
10 userId = "user-123",
11 name = "John Doe",
12 isHost = true
13 ),
14 liveType = BaxcloudLiveType.VIDEO_CALL
15 )
16 )
17
18 println("Connected to room: ${room.name}")
19 } catch (e: Exception) {
20 println("Connection failed: ${e.message}")
21 }
22}3. Render Video
1import androidx.compose.foundation.background
2import androidx.compose.foundation.layout.*
3import androidx.compose.foundation.lazy.grid.*
4import androidx.compose.material.icons.Icons
5import androidx.compose.material.icons.filled.MicOff
6import androidx.compose.material.icons.filled.Person
7import androidx.compose.material3.*
8import androidx.compose.runtime.Composable
9import androidx.compose.ui.Alignment
10import androidx.compose.ui.Modifier
11import androidx.compose.ui.graphics.Color
12import androidx.compose.ui.unit.dp
13import androidx.compose.ui.viewinterop.AndroidView
14import com.baxcloud.client.Room
15import org.webrtc.SurfaceViewRenderer
16
17@Composable
18fun VideoGrid(room: Room) {
19 val participants = room.participants.values.toList()
20
21 LazyVerticalGrid(
22 columns = GridCells.Fixed(2),
23 contentPadding = PaddingValues(8.dp),
24 horizontalArrangement = Arrangement.spacedBy(8.dp),
25 verticalArrangement = Arrangement.spacedBy(8.dp)
26 ) {
27 items(participants.size) { index ->
28 val participant = participants[index]
29 val isLocal = participant.identity == room.localParticipant?.identity
30
31 VideoParticipantItem(
32 participant = participant,
33 isLocal = isLocal
34 )
35 }
36 }
37}
38
39@Composable
40fun VideoParticipantItem(
41 participant: Participant,
42 isLocal: Boolean
43) {
44 Box(
45 modifier = Modifier
46 .aspectRatio(3f / 4f)
47 .background(Color.DarkGray)
48 ) {
49 // Video renderer
50 if (participant.videoTrack != null) {
51 AndroidView(
52 factory = { context ->
53 SurfaceViewRenderer(context).apply {
54 participant.videoTrack?.addSink(this)
55 }
56 },
57 modifier = Modifier.fillMaxSize()
58 )
59 } else {
60 // Placeholder when video is off
61 Icon(
62 imageVector = Icons.Default.Person,
63 contentDescription = "No video",
64 modifier = Modifier
65 .size(48.dp)
66 .align(Alignment.Center),
67 tint = Color.White.copy(alpha = 0.5f)
68 )
69 }
70
71 // Participant name overlay
72 Box(
73 modifier = Modifier
74 .align(Alignment.BottomStart)
75 .padding(8.dp)
76 .background(
77 Color.Black.copy(alpha = 0.5f),
78 shape = MaterialTheme.shapes.small
79 )
80 .padding(horizontal = 8.dp, vertical = 4.dp)
81 ) {
82 Row(
83 verticalAlignment = Alignment.CenterVertically,
84 horizontalArrangement = Arrangement.spacedBy(4.dp)
85 ) {
86 if (participant.isMuted) {
87 Icon(
88 imageVector = Icons.Default.MicOff,
89 contentDescription = "Muted",
90 modifier = Modifier.size(14.dp),
91 tint = Color.Red
92 )
93 }
94
95 Text(
96 text = "${participant.name}${if (isLocal) " (You)" else ""}",
97 style = MaterialTheme.typography.labelSmall,
98 color = Color.White
99 )
100 }
101 }
102 }
103}4. Disconnect
1client.disconnect()Usage Examples
Common implementation patterns
1class VideoCallActivity : AppCompatActivity() {
2 private lateinit var client: BaxCloudClient
3 private var room: Room? = null
4
5 override fun onCreate(savedInstanceState: Bundle?) {
6 super.onCreate(savedInstanceState)
7
8 // Request permissions first
9 requestPermissions()
10
11 client = BaxCloudClient(
12 context = this,
13 config = BaxCloudConfig(
14 projectId = "your-project-id",
15 apiKey = "your-api-key"
16 )
17 )
18
19 lifecycleScope.launch {
20 try {
21 room = client.connect(
22 BaxcloudRoomOptions(
23 roomName = "video-call-123",
24 participant = BaxcloudUser(
25 userId = "user-1",
26 name = "Alice",
27 isHost = true
28 ),
29 liveType = BaxcloudLiveType.VIDEO_CALL
30 )
31 )
32
33 println("Connected to room: ${room?.name}")
34 } catch (e: Exception) {
35 println("Connection failed: ${e.message}")
36 }
37 }
38 }
39
40 override fun onDestroy() {
41 super.onDestroy()
42 lifecycleScope.launch {
43 client.disconnect()
44 }
45 }
46}API Reference
Core classes and methods
BaxCloudClient
The main client class with coroutine support.
1// Connect
2val room = client.connect(options)
3
4// Enable camera/microphone
5client.enableCamera()
6client.enableMicrophone()
7
8// Disconnect
9client.disconnect()
10
11// Observe connection state (StateFlow)
12lifecycleScope.launch {
13 client.connectionState.collect { state ->
14 println("State: $state")
15 }
16}BaxCloudRoomController
Singleton controller for advanced room features.
1val controller = BaxCloudRoomController.instance
2controller.initialize(client, context)
3
4// Host controls
5controller.muteAll()
6controller.kickParticipant("user-2")
7
8// Chat
9controller.sendChatMessage("Hello!")
10
11// Event handlers
12controller.onChatMessage { message ->
13 println("${message.userName}: ${message.message}")
14}Recording
1// Start recording
2val recording = client.startRecording(
3 BaxcloudStartRecordingOptions(
4 roomName = "my-room",
5 fileType = "MP4"
6 )
7)
8
9// Stop recording
10client.stopRecording(recording.egressId)
11
12// List recordings
13val recordings = client.listRecordings(
14 BaxcloudListRecordingsOptions(
15 status = "COMPLETED",
16 page = 1,
17 limit = 10
18 )
19)Best Practices
Recommendations for Kotlin/Android development
Use Coroutines
All SDK methods are suspend functions. Use lifecycleScope or viewModelScope
Request Permissions
Always request permissions before connecting (Android 6.0+)
Handle Lifecycle
Disconnect in onDestroy() to clean up resources
Use StateFlow
Observe connectionState using StateFlow for reactive UI updates
Android-Specific Notes
Important considerations for Android development
ProGuard Rules
ProGuard rules are handled internally by the SDK. If using custom ProGuard configuration:
1-keep class com.baxcloud.client.** { *; }Picture-in-Picture
Available on Android 8.0+ (API 26+). Requires android:supportsPictureInPicture="true" in manifest
Background Handling
Handle app lifecycle changes. Consider disabling camera/mic when app goes to background