In a KMP module that includes androidTarget(), how do you correctly add Android-only dependencies and Android instrumented/unit test dependencies, and what's distinctive about the Android source sets compared to other platforms?
answer
- androidTarget() backed by AGP
- androidMain for AndroidX deps
- androidUnitTest vs androidInstrumentedTest
- android { } for compileSdk/namespace
- Android adds build variants
basics
~10 sAdd Android libraries in androidMain.dependencies { }. Android has extra test source sets like androidUnitTest and androidInstrumentedTest. Android also brings build-variant source sets, unlike other KMP targets.
solid answer
~40 sWhen you declare androidTarget(), the plugin creates androidMain plus Android-specific test source sets: androidUnitTest (local JVM tests) and androidInstrumentedTest (device/emulator tests). Android-only libraries (AndroidX, etc.) go in androidMain.dependencies { } with the normal implementation/api configurations; test deps go in androidUnitTest.dependencies { } or androidInstrumentedTest.dependencies { }. What's distinctive is that the Android target is backed by the Android Gradle Plugin, so it also participates in build variants (debug/release, flavors) — you can have variant-aware source sets, and some legacy Android-specific configurations (like coreLibraryDesugaring) are still configured in the android { } block, not the KMP dependencies block. Older KMP used androidMain/androidTest naming; current Kotlin renamed to androidMain/androidUnitTest/androidInstrumentedTest to disambiguate. As with every target, androidMain inherits commonMain, and you keep multiplatform artifacts in commonMain while Android-only ones live in androidMain.
code
kotlin · 8 lineskotlin {
androidTarget()
sourceSets {
androidMain.dependencies { implementation("androidx.core:core-ktx:1.13.0") }
androidUnitTest.dependencies { implementation("junit:junit:4.13.2") }
androidInstrumentedTest.dependencies { implementation("androidx.test.ext:junit:1.2.1") }
}
}go deeper
Knows Android-only libraries go in androidMain.
Distinguishes androidMain from androidUnitTest/androidInstrumentedTest and keeps multiplatform deps in commonMain.
Explains the AGP backing, build-variant awareness, and the android { } vs dependencies { } split.
Manages variant-aware dependency strategy and migration from deprecated names across a large multi-module Android+KMP build.
## Android is a special target Unlike `jvm()` or `iosArm64()`, the KMP `androidTarget()` is backed by the **Android Gradle Plugin (AGP)**. That means the Android part of the module has build **variants** (debug/release, product flavors) and Android-specific configuration, on top of the normal KMP source-set model. ## The Android source sets Declaring `androidTarget()` creates: - `androidMain` — Android production code; depends on `commonMain`. - `androidUnitTest` — local unit tests run on the host JVM (formerly `androidTest`/`testDebug`-style naming). - `androidInstrumentedTest` — tests run on a device/emulator. (The current names `androidMain` / `androidUnitTest` / `androidInstrumentedTest` replaced older, ambiguous names; `androidTarget()` itself replaced the deprecated `android()`.) ```kotlin kotlin { androidTarget() sourceSets { commonMain.dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0") } androidMain.dependencies { implementation("androidx.core:core-ktx:1.13.0") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.0") } androidUnitTest.dependencies { implementation("junit:junit:4.13.2") } androidInstrumentedTest.dependencies { implementation("androidx.test.ext:junit:1.2.1") } } } android { namespace = "com.example.shared" compileSdk = 34 defaultConfig { minSdk = 24 } } ``` ## What's distinctive vs other targets - **Variant awareness:** the Android target can have variant-specific source sets and dependencies (debug-only, release-only). Pure-Kotlin targets (jvm, native, js) have no such notion. - **android { } block:** some things are configured there, not in `dependencies { }` — e.g. `compileSdk`, `namespace`, `coreLibraryDesugaring`, packaging options. - **Two test source sets:** local (`androidUnitTest`) vs instrumented (`androidInstrumentedTest`), reflecting Android's runtime split. Other targets typically have a single `xxxTest`. ## Placement rule, unchanged Multiplatform artifacts → `commonMain`; Android-only (AndroidX, Play services) → `androidMain`; Android test libs → the matching Android test source set. `androidMain` still inherits everything from `commonMain`, so Android code sees both.
- Where do you set compileSdk and namespace for a KMP module's Android target?In the android { } block provided by the Android Gradle Plugin, not in the kotlin sourceSets dependencies — those are AGP configuration, not KMP dependency declarations.
- Why does Android have two test source sets while jvm has one?Android distinguishes local host-JVM unit tests (androidUnitTest) from on-device instrumented tests (androidInstrumentedTest); a plain jvm target has no on-device runtime, so a single jvmTest suffices.
saying these in an interview costs you the question
- Putting AndroidX dependencies in commonMain
- Not knowing androidUnitTest vs androidInstrumentedTest exist
- Configuring compileSdk inside a dependencies block
- Using the deprecated android() instead of androidTarget()
- Assuming Android target behaves identically to jvm/native targets