Skip to main content

Android Complete Starter

This is the complete Android starter used by the Android tutorials. It gives you one small Compose app with a clear picker for the five supported room experiences: a compact call, host dashboard, guest queue, classroom, and podcast. Copy every file below into a new Empty Activity Android Studio project, then follow the run steps.

Prerequisites

  • Android Studio with JDK 17 and an Android device or emulator running Android 7.0 (API 24) or newer.
  • A camera and microphone for a media test.
  • For a hosted or distributed app, your authenticated backend must approve room entry. Do not put a reusable MediaSFU account credential in the app.

Project files

settings.gradle.kts:

pluginManagement { repositories { google(); mavenCentral(); gradlePluginPortal() } }
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS); repositories { google(); mavenCentral() } }
rootProject.name = "MediaSFUStarter"
include(":app")

build.gradle.kts:

plugins {
id("com.android.application") version "8.6.1" apply false
kotlin("android") version "2.0.20" apply false
id("org.jetbrains.kotlin.plugin.compose") version "2.0.20" apply false
}

app/build.gradle.kts:

plugins {
id("com.android.application")
kotlin("android")
id("org.jetbrains.kotlin.plugin.compose")
}

android {
namespace = "com.example.mediasfustarter"
compileSdk = 35
defaultConfig { applicationId = "com.example.mediasfustarter"; minSdk = 24; targetSdk = 35; versionCode = 1; versionName = "1.0" }
}

dependencies {
implementation("com.mediasfu:mediasfu-sdk-android:1.0.5")
implementation(platform("androidx.compose:compose-bom:2024.09.01"))
implementation("androidx.activity:activity-compose:1.9.2")
implementation("androidx.compose.material3:material3")
}

app/src/main/AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<application android:theme="@android:style/Theme.Material.Light.NoActionBar" android:label="MediaSFU Starter">
<activity android:name=".MainActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

app/src/main/java/com/example/mediasfustarter/MainActivity.kt:

package com.example.mediasfustarter

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) = super.onCreate(savedInstanceState).also {
setContent {
MaterialTheme {
var scenario by remember { mutableStateOf(ProductScenario.COMPACT_CALL) }
Column {
ProductScenario.entries.forEach { choice ->
TextButton(onClick = { scenario = choice }) { Text(choice.label) }
}
ScenarioRoom(scenario)
}
}
}
}
}

app/src/main/java/com/example/mediasfustarter/ScenarioRoom.kt:

package com.example.mediasfustarter

import androidx.compose.runtime.Composable
import com.mediasfu.sdk.ui.mediasfu.MediasfuBroadcast
import com.mediasfu.sdk.ui.mediasfu.MediasfuConference
import com.mediasfu.sdk.ui.mediasfu.MediasfuGeneric
import com.mediasfu.sdk.ui.mediasfu.MediasfuGenericOptions
import com.mediasfu.sdk.ui.mediasfu.MediasfuWebinar

enum class ProductScenario(val label: String) {
COMPACT_CALL("Compact call"), HOST_DASHBOARD("Host dashboard"),
LIVE_GUEST_QUEUE("Live guest queue"), CLASSROOM_WORKSHOP("Classroom workshop"),
REMOTE_PODCAST("Remote podcast")
}

@Composable
fun ScenarioRoom(scenario: ProductScenario) {
val options = MediasfuGenericOptions(connectMediaSFU = true)
when (scenario) {
ProductScenario.COMPACT_CALL -> MediasfuGeneric(options)
ProductScenario.HOST_DASHBOARD, ProductScenario.CLASSROOM_WORKSHOP -> MediasfuConference(options)
ProductScenario.LIVE_GUEST_QUEUE -> MediasfuWebinar(options)
ProductScenario.REMOTE_PODCAST -> MediasfuBroadcast(options)
}
}

The supplied room asks for camera and microphone access when the person turns on a device. For a released app, connect its approved entry response from your backend instead of storing an account key in a mobile build. The complete secure room-entry guide shows that server boundary.

Run

.\gradlew.bat installDebug

Choose an experience, create or join a room on the supplied pre-join screen, and grant device access when asked.

What you should see

The compact call and conference rooms show the supplied pre-join and in-room controls. A second device or emulator can join with the meeting ID and verify participant entry, microphone, camera, remote media, and Leave.

Recovery

If a device does not start, open Android app settings and grant the requested permission, then try that device control again. If entry is refused, keep the person on the pre-join screen and request a fresh approved entry from the app backend.

Cleanup

Use the room's Leave control, then clear the app's selected-room state and any app-owned listeners or timers. A later join should receive a new backend approval.