File: app/build.gradle.kts
Module: :app (Android application)
Purpose: Configures the Android app module for a KMM project using XML-based UI (no Compose). Wires the app to the shared KMM module, sets up build types, Java/Kotlin toolchains, and AndroidX dependencies.
| Plugin ID | Why it’s here |
|---|---|
com.android.application |
Declares this module is an Android application (packaging an APK/AAB). |
org.jetbrains.kotlin.android |
Enables Kotlin on Android with AndroidX extensions. |
(optional) kotlin-parcelize |
If your models use @Parcelize for passing between activities/fragments. |
(optional) com.google.gms.google-services |
If using Firebase/Google services. |
| Setting | Example / Guidance |
|---|---|
namespace |
com.example.magictoyboxgenericmobile – required by AGP 8+. |
compileSdk |
34 (or project-wide constant). |
defaultConfig.applicationId |
Package ID of the app (usually same as namespace). |
defaultConfig.minSdk |
24 (Android 7.0) or higher as needed. |
defaultConfig.targetSdk |
34 to meet Play policy. |
defaultConfig.versionCode |
Integer build number, increments per release. |
defaultConfig.versionName |
Human-readable version (e.g. 1.0.0). |
testInstrumentationRunner |
androidx.test.runner.AndroidJUnitRunner. |
vectorDrawables.useSupportLibrary |
true if supporting API < 21 and using vector drawables. |
buildTypes.debug |
Add applicationIdSuffix = ".debug" & versionNameSuffix = "-debug". |
buildTypes.release |
Enable proguard/shrinker; add signing config for release builds. |
compileOptions |
Java 17 source/target for AGP 8+. |
kotlinOptions.jvmTarget |
"17". |
buildFeatures.viewBinding |
true (since you’re using XML, not Compose). |
buildFeatures.compose |
false (explicitly off to avoid Compose deps). |
packaging.resources.excludes |
Exclude common duplicate META-INF files. |
implementation(project(":shared")):app.Core & AndroidX
androidx.core:core-ktxandroidx.appcompat:appcompatcom.google.android.material:materialandroidx.constraintlayout:constraintlayoutandroidx.activity:activity-ktxandroidx.fragment:fragment-ktxandroidx.lifecycle:lifecycle-runtime-ktxandroidx.lifecycle:lifecycle-viewmodel-ktxNetworking (as used in your project)
com.squareup.retrofit2:retrofitcom.squareup.retrofit2:converter-gsoncom.squareup.okhttp3:okhttpcom.squareup.okhttp3:logging-interceptorCoroutines
org.jetbrains.kotlinx:kotlinx-coroutines-androidLogging
com.jakewharton.timber:timber (optional; or use your Logging.kt façade only)Testing
testImplementation("junit:junit")androidTestImplementation("androidx.test.ext:junit")androidTestImplementation("androidx.test.espresso:espresso-core")io.mockk:mockk-android, kotlinx-coroutines-testIf you use a version catalog (
libs.versions.toml), replace the literals withlibs.*aliases.
| Check | Command | Expectation |
|---|---|---|
| Sync | Gradle Sync | No plugin/dependency resolution errors. |
| Build (debug) | ./gradlew :app:assembleDebug |
APK builds successfully. |
| Unit tests | ./gradlew :app:testDebugUnitTest |
All unit tests pass. |
| Instrumented tests | ./gradlew :app:connectedDebugAndroidTest |
Espresso tests run on device/emulator. |
| Dependency tree | ./gradlew :app:dependencies |
Verify resolved versions/conflicts. |
app/build.gradle.ktsplugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
// id("kotlin-parcelize") // if you use @Parcelize
// id("com.google.gms.google-services") // if Firebase/Play services are used
}
android {
namespace = "com.example.magictoyboxgenericmobile"
compileSdk = 34
defaultConfig {
applicationId = "com.example.magictoyboxgenericmobile"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
}
buildTypes {
debug {
applicationIdSuffix = ".debug"
versionNameSuffix = "-debug"
isDebuggable = true
}
release {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
// signingConfig = signingConfigs.getByName("release") // configure in signingConfigs
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
freeCompilerArgs += listOf(
"-Xjvm-default=all",
"-opt-in=kotlin.RequiresOptIn"
)
}
buildFeatures {
viewBinding = true
dataBinding = false
compose = false
}
packaging {
resources {
excludes += setOf(
"META-INF/AL2.0",
"META-INF/LGPL2.1",
"META-INF/licenses/**",
"META-INF/DEPENDENCIES"
)
}
}
}
dependencies {
implementation(project(":shared"))
// AndroidX core UI
implementation("androidx.core:core-ktx:1.13.1")
implementation("androidx.appcompat:appcompat:1.7.0")
implementation("com.google.android.material:material:1.12.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.activity:activity-ktx:1.9.2")
implementation("androidx.fragment:fragment-ktx:1.8.2")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.4")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.4")
// Coroutines
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
// Networking
implementation("com.squareup.retrofit2:retrofit:2.11.0")
implementation("com.squareup.retrofit2:converter-gson:2.11.0")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
// Logging (optional)
implementation("com.jakewharton.timber:timber:5.0.1")
// Testing
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.2.1")
androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
}
namespace is a compile concept; applicationId is the runtime/package identity.packaging.resources.excludes to avoid duplicate resource merge errors.compose = false to avoid bringing in Compose BOM.vectorDrawables.useSupportLibrary = true for consistent rendering.android {
signingConfigs {
create("release") {
storeFile = file(System.getenv("KEYSTORE_PATH") ?: "../keystores/release.keystore")
storePassword = System.getenv("KEYSTORE_PASSWORD")
keyAlias = System.getenv("KEY_ALIAS")
keyPassword = System.getenv("KEY_PASSWORD")
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
}
}
}
libs.versions.toml) for consistency.dev, staging, prod) for environment-specific config.navigation-fragment-ktx / navigation-ui-ktx deps.