What You'll Learn
This article explains Android App Bundle (AAB format, Play Feature Delivery, dynamic modules, conditional delivery, size optimization).
What is App Bundle
// build.gradle.kts (app)
android {
bundle {
language {
enableSplit = true // Split language resources
}
density {
enableSplit = true // Split screen density
}
abi {
enableSplit = true // Split CPU architecture
}
}
}
Google Play optimizes APK per device. Average 20% size reduction.
Play Feature Delivery
// Dynamic feature module: build.gradle.kts
plugins {
id("com.android.dynamic-feature")
}
android {
namespace = "com.example.feature.camera"
}
dependencies {
implementation(project(":app"))
}
<!-- feature/camera/src/main/AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:dist="http://schemas.android.com/apk/distribution">
<dist:module
dist:instant="false"
dist:title="@string/title_camera">
<dist:delivery>
<dist:on-demand />
</dist:delivery>
</dist:module>
</manifest>
Installing Dynamic Modules
class DynamicFeatureManager @Inject constructor(
@ApplicationContext private val context: Context
) {
private val splitInstallManager = SplitInstallManagerFactory.create(context)
fun installModule(
moduleName: String,
onProgress: (Int) -> Unit,
onSuccess: () -> Unit,
onFailure: (Exception) -> Unit
) {
val request = SplitInstallRequest.newBuilder()
.addModule(moduleName)
.build()
splitInstallManager.startInstall(request)
.addOnSuccessListener { sessionId ->
splitInstallManager.registerListener { state ->
when (state.status()) {
SplitInstallSessionStatus.INSTALLED -> onSuccess()
SplitInstallSessionStatus.DOWNLOADING -> {
val progress = (state.bytesDownloaded() * 100 / state.totalBytesToDownload()).toInt()
onProgress(progress)
}
SplitInstallSessionStatus.FAILED -> {
onFailure(Exception("Install failed: ${state.errorCode()}"))
}
else -> {}
}
}
}
.addOnFailureListener { onFailure(it) }
}
fun isModuleInstalled(moduleName: String): Boolean {
return splitInstallManager.installedModules.contains(moduleName)
}
}
Compose UI
@Composable
fun DynamicFeatureScreen(
featureManager: DynamicFeatureManager,
moduleName: String,
installedContent: @Composable () -> Unit
) {
var installState by remember { mutableStateOf(
if (featureManager.isModuleInstalled(moduleName)) InstallState.Installed
else InstallState.NotInstalled
)}
var progress by remember { mutableIntStateOf(0) }
when (installState) {
InstallState.NotInstalled -> {
Column(
Modifier.fillMaxSize().padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text("This feature requires additional download")
Spacer(Modifier.height(16.dp))
Button(onClick = {
installState = InstallState.Installing
featureManager.installModule(
moduleName,
onProgress = { progress = it },
onSuccess = { installState = InstallState.Installed },
onFailure = { installState = InstallState.NotInstalled }
)
}) { Text("Download") }
}
}
InstallState.Installing -> {
Column(
Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
CircularProgressIndicator()
Spacer(Modifier.height(8.dp))
Text("Downloading: $progress%")
LinearProgressIndicator(progress = { progress / 100f })
}
}
InstallState.Installed -> installedContent()
}
}
enum class InstallState { NotInstalled, Installing, Installed }
Summary
| Feature | Implementation |
|---|---|
| APK splitting | bundle { enableSplit = true } |
| On-demand delivery | <dist:on-demand /> |
| Install management | SplitInstallManager |
| Progress tracking | SplitInstallSessionStatus |
- Use AAB format for device-optimized APK delivery
- Dynamic modules reduce initial download size
-
SplitInstallManagermanages module installation - Conditional delivery supports country/API-level targeting
8 production-ready Android app templates (App Bundle optimized) are available.
Browse templates → Gumroad
Related articles:
- R8/ProGuard
- Release checklist
- Google Play publishing
Ready-Made Android App Templates
8 production-ready Android app templates with Jetpack Compose, MVVM, Hilt, and Material 3.
Browse templates → Gumroad
Top comments (0)