MediaSFU for Android
Build an Android-native MediaSFU room with Kotlin and Jetpack Compose. This is the Android publication of the MediaSFU Kotlin SDK. Use Kotlin Multiplatform only when you are sharing room code across Kotlin targets. A restricted credential can be used for isolated local development; complete the production credential boundary before sharing or releasing a Cloud-backed app.
Install
Add Maven Central and the Android artifact to your app module:
repositories {
mavenCentral()
}
dependencies {
implementation("com.mediasfu:mediasfu-sdk-android:1.0.5")
}
mediasfu-sdk-android brings in the MediaSFU mediasoup transport dependency required by the Android implementation. It is not the same thing as the low-level com.mediasfu:mediasoup-client package; install the room SDK unless you are deliberately building your own transport layer.
Add permissions
Add these declarations to AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
Request camera and microphone permissions at runtime before a participant enables them.
Copy/paste starter
The fastest starting point is the supplied Compose room:
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import com.mediasfu.sdk.ui.mediasfu.MediasfuConference
import com.mediasfu.sdk.ui.mediasfu.MediasfuGenericOptions
@Composable
fun ConferenceScreen() {
MediasfuConference(
options = MediasfuGenericOptions(
localLink = "https://your-approved-mediasfu-server.example"
)
)
}
The other room shapes are MediasfuGeneric, MediasfuWebinar, MediasfuBroadcast, and MediasfuChat. The specialized components are convenience wrappers over the same room runtime.
Make it your own
Use MediasfuGenericOptions to keep the room runtime while changing what users see:
import androidx.compose.runtime.Composable
import com.mediasfu.sdk.ui.mediasfu.MediasfuGeneric
import com.mediasfu.sdk.ui.mediasfu.MediasfuGenericOptions
@Composable
fun BrandedRoom() {
MediasfuGeneric(
options = MediasfuGenericOptions(
localLink = "https://your-approved-mediasfu-server.example",
returnUI = false,
customComponent = { state ->
Column {
Text("Participants: ${state.room.participants.size}")
Button(onClick = state::toggleAudio) { Text("Microphone") }
Button(onClick = state::toggleVideo) { Text("Camera") }
Button(onClick = state::toggleScreenShare) { Text("Share screen") }
Button(onClick = state::exitSession) { Text("Leave room") }
}
}
)
)
}
For smaller changes, supply customVideoCard, customAudioCard, or customMiniCard instead of replacing the whole workspace.
Secure room access
Do not place MediaSFU Cloud account credentials in an Android app. The direct Cloud create/join option types contain account fields, so keep that path on your authenticated backend. Your app should request room access from the backend and receive only the authorized session data it needs.
For an approved self-hosted MediaSFU server, pass its HTTPS address as localLink. Read secure backend proxy before connecting Cloud-backed rooms.
Before release
Use two real devices to verify local microphone and camera, remote audio/video, screen sharing, reconnect, leave, and host controls for the roles your product supports. Check the Kotlin API reference for generated API details.
Features your Android app owns
The Android SDK's supplied rooms include participant, chat, poll, waiting-room, breakout, whiteboard, recording-control, device, and media-control surfaces. Use those supplied controls first. The Android package does not publish a separate Android contract for these application and backend services:
- secure invite creation and redemption, durable bans, role policy, and host end-of-room business rules;
- semantic host end and host leave-without-ending from the current headless
controller;
disconnect()alone proves neither outcome; - reconnect decisions, cleanup of app-owned state, device-selection UI, and user-facing recovery messages;
- file sharing, recording storage or exports, SIP/PSTN, HLS/WHEP/WHIP, and AI-agent handoff;
- fully headless room control and custom media rendering. If you set
returnUI = false, your app must render the supplied room state and provide every control it needs.
This boundary is intentional: a MediaSFU room can be part of those products, but your application still owns the permissions, business rules, storage, consent, and user experience around them.