The com.android.kotlin.multiplatform.library
Gradle plugin is the officially
supported tool for adding an Android target to a Kotlin Multiplatform (KMP)
library module. It simplifies project configuration, improves
build performance, and offers better integration with Android Studio.
The previous approach is now deprecated in favor of the plugin, also referred to
as the Android-KMP plugin. Continuing to use the com.android.library
plugin for KMP will no longer be supported by JetBrains and won't benefit from
future updates and improvements.
To apply this plugin, refer to the Apply the Android-KMP plugin section. If you need to migrate from the legacy APIs, check the Migration Guide.
Key features and differences
The Android-KMP plugin is tailored specifically for KMP projects and differs
from the standard com.android.library
plugin in several key aspects:
Single variant architecture: The plugin uses a single variant, removing support for product flavors and build types, which simplifies configuration and enhances build performance.
Optimized for KMP: The plugin is designed for KMP libraries, focusing on shared Kotlin code and interoperability, omitting support for Android-specific native builds, AIDL, and RenderScript.
Tests disabled by default: Both unit and device (instrumentation) tests are disabled by default to enhance build speed. You can enable them if required.
No top-Level Android extension: Configuration is handled with an
androidLibrary
block within the Gradle KMP DSL, maintaining a consistent KMP project structure. There's no top-levelandroid
extension block.Opt-in Java compilation: Java compilation is disabled by default. Use
withJava()
in theandroidLibrary
block to enable it. This improves build times when Java compilation is not needed.
Benefits of the Android-KMP library plugin
The Android-KMP plugin provides the following benefits for KMP projects:
Improved build performance and stability: It's engineered for optimized build speeds and enhanced stability within KMP projects. It's focus on KMP workflows contribute to a more efficient and reliable build process.
Enhanced IDE integration: It provides better code completion, navigation, debugging, and overall developer experience when working with KMP Android libraries.
Simplified project configuration: The plugin simplifies configuration for KMP projects by removing Android-specific complexities like build variants. This leads to cleaner and more maintainable build files. Previously, using the
com.android.library
plugin in KMP project could create confusing source set names, such asandroidAndroidTest
. This naming convention was less intuitive for developers familiar with standard KMP project structures.
Prerequisites
To use the com.android.kotlin.multiplatform.library
plugin, your project must
be configured with the following minimum versions or higher:
- Android Gradle Plugin (AGP): 8.10.0
- Kotlin Gradle Plugin (KGP): 2.0.0
Apply the Android-KMP plugin to an existing module
To apply the Android-KMP plugin to an existing KMP library module, follow these steps:
Declare plugins in version catalog. Open the version catalog TOML file (usually
gradle/libs.versions.toml
) and add the plugin definitions section:# To check the version number of the latest Kotlin release, go to # https://kotlinlang.org/docs/releases.html [versions] androidGradlePlugin = "8.13.0" kotlin = "KOTLIN_VERSION" [plugins] kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } android-kotlin-multiplatform-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "androidGradlePlugin" }
Apply the plugin declaration in root build file. Open the
build.gradle.kts
file located in the root directory of your project. Add the plugin aliases to theplugins
block usingapply false
. This makes the plugin aliases available to all subprojects without applying the plugin logic to the root project itself.Kotlin
// Root build.gradle.kts file plugins { alias(libs.plugins.kotlin.multiplatform) apply false // Add the following alias(libs.plugins.android.kotlin.multiplatform.library) apply false }
Groovy
// Root build.gradle file plugins { alias(libs.plugins.kotlin.multiplatform) apply false // Add the following alias(libs.plugins.android.kotlin.multiplatform.library) apply false }
Apply the plugin in a KMP library module build file. Open the
build.gradle.kts
file in your KMP library module and apply the plugin at the top of your file within theplugins
block:Kotlin
// Module-specific build.gradle.kts file plugins { alias(libs.plugins.kotlin.multiplatform) // Add the following alias(libs.plugins.android.kotlin.multiplatform.library) }
Groovy
// Module-specific build.gradle file plugins { alias(libs.plugins.kotlin.multiplatform) // Add the following alias(libs.plugins.android.kotlin.multiplatform.library) }
Configure Android KMP target. Configure the Kotlin Multiplatform block (
kotlin
) to define the Android target. Within thekotlin
block, specify the Android target usingandroidLibrary
:Kotlin
kotlin { androidLibrary { namespace = "com.example.kmpfirstlib" compileSdk = 33 minSdk = 24 withJava() // enable java compilation support withHostTestBuilder {}.configure {} withDeviceTestBuilder { sourceSetTreeName = "test" } compilations.configureEach { compilerOptions.configure { jvmTarget.set( org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 ) } } } sourceSets { androidMain { dependencies { // Add Android-specific dependencies here } } getByName("androidHostTest") { dependencies { } } getByName("androidDeviceTest") { dependencies { } } } // ... other targets (JVM, iOS, etc.) ... }
Groovy
kotlin { androidLibrary { namespace = "com.example.kmpfirstlib" compileSdk = 33 minSdk = 24 withJava() // enable java compilation support withHostTestBuilder {}.configure {} withDeviceTestBuilder { it.sourceSetTreeName = "test" } compilations.configureEach { compilerOptions.options.jvmTarget.set( org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 ) } } sourceSets { androidMain { dependencies { } } androidHostTest { dependencies { } } androidDeviceTest { dependencies { } } } // ... other targets (JVM, iOS, etc.) ... }
Apply changes. After applying the plugin and configuring the
kotlin
block, sync your Gradle project to apply the changes.
Migrate from the legacy plugin
This guide helps you migrate from the legacy com.android.library
plugin to the
com.android.kotlin.multiplatform.library
plugin.
1. Declaring Dependencies
A common task is declaring dependencies for Android-specific source sets. The
new plugin requires these to be explicitly placed within the sourceSets
block,
unlike the general dependencies
block used previously.
Android-KMP
The new plugin promotes a cleaner structure by grouping Android dependencies
within the androidMain
source set. In addition to the main source set,
there are two test source sets, which are created on demand:
androidDeviceTest
and androidHostTest
(check the configuring host and
device tests for more information).
// build.gradle.kts
kotlin {
android {}
//... other targets
sourceSets {
commonMain.dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")
}
// Dependencies are now scoped to the specific Android source set
androidMain.dependencies {
implementation("androidx.appcompat:appcompat:1.7.0")
implementation("com.google.android.material:material:1.11.0")
}
}
}
The source sets have corresponding Kotlin
compilations named main
, deviceTest
,
and hostTest
. The source sets and compilations can be configured in the
build script like so:
// build.gradle.kts
kotlin {
androidLibrary {
compilations.getByName("deviceTest") {
kotlinOptions.languageVersion = "2.0"
}
}
}
Legacy Plugin
With the old plugin, you could declare Android-specific dependencies in the top-level dependencies block, which could sometimes be confusing in a multiplatform module.
// build.gradle.kts
kotlin {
androidTarget()
//... other targets
}
// Dependencies for all source sets were often mixed in one block
dependencies {
// Common dependencies
commonMainImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")
// Android-specific dependencies
implementation("androidx.appcompat:appcompat:1.7.0")
implementation("com.google.android.material:material:1.11.0")
}
2. Enabling Android Resources
Support for Android Resources (res
folders) is not enabled by default in the
new plugin to optimize build performance. You must opt-in to use them. This
change helps ensure that projects not requiring Android-specific resources are
not burdened by the associated build overhead.
Android-KMP
You must explicitly enable Android resource processing. The resources should
be placed in src/androidMain/res
.
// build.gradle.kts
kotlin {
android {
// ...
// Enable Android resource processing
androidResources {
enable = true
}
}
}
// Project Structure
// └── src
// └── androidMain
// └── res
// ├── values
// │ └── strings.xml
// └── drawable
// └── icon.xml
Legacy Plugin
Resource processing was enabled by default. You could immediately add a
res
directory in src/main
and start adding XML drawables, values, etc.
// build.gradle.kts
android {
namespace = "com.example.library"
compileSdk = 34
// No extra configuration was needed to enable resources.
}
// Project Structure
// └── src
// └── main
// └── res
// ├── values
// │ └── strings.xml
// └── drawable
// └── icon.xml
3. Configuring Host and Device Tests
A significant change in the new plugin is that Android host-side (unit) and device-side (instrumented) tests are disabled by default. You must explicitly opt-in to create the test source sets and configurations, whereas the old plugin created them automatically.
This opt-in model helps verify that your project remains lean and only includes the build logic and source sets that you actively use.
Android-KMP
In the new plugin, you enable and configure tests inside the
kotlin.android
block. This makes the setup more explicit and avoids
creating unused test components. The test
source set becomes
androidHostTest
, and androidTest
becomes androidDeviceTest
.
// build.gradle.kts
kotlin {
android {
// ...
// Opt-in to enable and configure host-side (unit) tests
withHostTest {
isIncludeAndroidResources = true
}
// Opt-in to enable and configure device-side (instrumented) tests
withDeviceTest {
instrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
execution = "ANDROIDX_TEST_ORCHESTRATOR"
}
}
}
// Project Structure (After Opt-in)
// └── src
// ├── androidHostTest
// └── androidDeviceTest
Legacy Plugin
With the com.android.library
plugin, the test
and androidTest
source
sets were created by default. You would configure their behavior inside the
android
block, typically using the testOptions
DSL.
// build.gradle.kts
android {
defaultConfig {
// Runner was configured in defaultConfig
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
testOptions {
// Configure unit tests (for the 'test' source set)
unitTests.isIncludeAndroidResources = true
// Configure device tests (for the 'androidTest' source set)
execution = "ANDROIDX_TEST_ORCHESTRATOR"
}
}
// Project Structure (Defaults)
// └── src
// ├── test
// └── androidTest
4. Enable Java source compilation
If your KMP library needs to compile Java sources for its Android target, you must explicitly enable this functionality with the new plugin. Note that this enables compilation for Java files located directly within your project, not for its dependencies. The method for setting the Java and Kotlin compiler's JVM target version also changes.
Android-KMP
You must opt-in to Java compilation by calling withJava()
. The JVM target
is now configured directly inside the kotlin { androidLibrary {} }
block
for a more unified setup. Setting jvmTarget
here applies to both Kotlin
and Java compilation for the Android target.
// build.gradle.kts
kotlin {
android {
// Opt-in to enable Java source compilation
withJava()
// Configure the JVM target for both Kotlin and Java sources
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8)
}
}
// ...
}
// Project Structure:
// └── src
// └── androidMain
// ├── kotlin
// │ └── com/example/MyKotlinClass.kt
// └── java
// └── com.example/MyJavaClass.java
Legacy Plugin
Java compilation was enabled by default. The JVM target for both Java and Kotlin sources was set in the android block using compileOptions.
// build.gradle.kts
android {
// ...
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
kotlin {
androidTarget {
compilations.all {
kotlinOptions.jvmTarget = "1.8"
}
}
}
5. Interact with build variants using androidComponents
The androidComponents
extension is still available for interacting with build
artifacts programmatically. While much of the Variant
API remains the same,
the new AndroidKotlinMultiplatformVariant
interface is more limited because
the plugin only produces a single variant.
Consequently, properties related to build types and product flavors are no longer available on the variant object.
Android-KMP
The onVariants
block now iterates over a single variant. You can still
access common properties like name
and artifacts
, but not
build-type-specific ones.
// build.gradle.kts
androidComponents {
onVariants { variant ->
val artifacts = variant.artifacts
}
}
Legacy Plugin
With multiple variants, you could access build-type-specific properties to configure tasks.
// build.gradle.kts
androidComponents {
onVariants(selector().withBuildType("release")) { variant ->
// ...
}
}
6. Select variants of Android library dependencies
Your KMP library produces a single variant for Android. However, you might
depend on a standard Android library (com.android.library
) that has multiple
variants (e.g., free/paid
product flavors). Controlling how your project
selects a variant from that dependency is a common requirement.
Android-KMP
The new plugin centralizes and clarifies this logic within the
kotlin.android.localDependencySelection
block. This makes it much clearer
which variants of external dependencies will be selected for your
single-variant KMP library.
// build.gradle.kts
kotlin {
android {
localDependencySelection {
// For dependencies with multiple build types, select 'debug' first, and 'release' in case 'debug' is missing
selectBuildTypeFrom.set(listOf("debug", "release"))
// For dependencies with a 'type' flavor dimension...
productFlavorDimension("type") {
// ...select the 'typeone' flavor.
selectFrom.set(listOf("typeone"))
}
}
}
}
Legacy Plugin
You configured dependency selection strategies inside the buildTypes and
productFlavors
blocks. This often involved using missingDimensionStrategy
to provide a default flavor for a dimension that your library didn't have,
or matchingFallbacks
within a specific flavor to define a search order.
Refer to Resolve Matching Errors for more detailed information on the API usage.
Plugin API reference
The new plugin has a different API surface than com.android.library
. For
detailed information on the new DSL and interfaces, see the API references:
KotlinMultiplatformAndroidLibraryExtension
KotlinMultiplatformAndroidLibraryTarget
KotlinMultiplatformAndroidDeviceTest
KotlinMultiplatformAndroidHostTest
KotlinMultiplatformAndroidVariant
Recommended for you
- Note: link text is displayed when JavaScript is off
- Set up your environment
- Add KMP module to a project