Android-Gradle-Bibliotheks-Plug-in für KMP einrichten

Das com.android.kotlin.multiplatform.library-Gradle-Plug-in ist das offiziell unterstützte Tool zum Hinzufügen eines Android-Ziels zu einem Bibliotheksmodul für Kotlin Multiplatform (KMP). Sie vereinfacht die Projektkonfiguration, verbessert die Build-Leistung und bietet eine bessere Integration in Android Studio.

Der bisherige Ansatz wird jetzt zugunsten des Plug-ins, auch Android-KMP-Plug-in genannt, eingestellt. Die weitere Verwendung des com.android.library-Plug-ins für KMP wird von JetBrains nicht mehr unterstützt und profitiert nicht von zukünftigen Updates und Verbesserungen.

Informationen zum Anwenden dieses Plug-ins finden Sie im Abschnitt Android-KMP-Plug-in anwenden. Wenn Sie von den Legacy-APIs migrieren müssen, lesen Sie die Migrationsanleitung.

Wichtige Funktionen und Unterschiede

Das Android-KMP-Plugin ist speziell auf KMP-Projekte zugeschnitten und unterscheidet sich in mehreren wichtigen Punkten vom Standard-com.android.library-Plugin:

  • Architektur mit einer einzelnen Variante:Das Plug‑in verwendet eine einzelne Variante. Dadurch wird die Unterstützung für Produktvarianten und Build-Typen entfernt, was die Konfiguration vereinfacht und die Build-Leistung verbessert.

  • Für KMP optimiert:Das Plug-in ist für KMP-Bibliotheken konzipiert und konzentriert sich auf gemeinsamen Kotlin-Code und Interoperabilität. Es bietet keine Unterstützung für Android-spezifische native Builds, AIDL und RenderScript.

  • Tests standardmäßig deaktiviert:Sowohl Unit- als auch Gerätetests (Instrumentierungstests) sind standardmäßig deaktiviert, um die Build-Geschwindigkeit zu erhöhen. Sie können sie bei Bedarf aktivieren.

  • Keine Android-Erweiterung auf oberster Ebene:Die Konfiguration erfolgt mit einem androidLibrary-Block in der Gradle KMP DSL, wodurch eine konsistente KMP-Projektstruktur beibehalten wird. Es gibt keinen Block für die Erweiterung android auf oberster Ebene.

  • Java-Kompilierung mit Opt-in:Die Java-Kompilierung ist standardmäßig deaktiviert. Verwenden Sie withJava() im Block androidLibrary, um die Funktion zu aktivieren. Dadurch werden die Build-Zeiten verkürzt, wenn keine Java-Kompilierung erforderlich ist.

Vorteile des Android-KMP-Bibliotheks-Plug-ins

Das Android-KMP-Plug-in bietet die folgenden Vorteile für KMP-Projekte:

  • Verbesserte Build-Leistung und ‑Stabilität:Es wurde für optimierte Build-Geschwindigkeiten und verbesserte Stabilität in KMP-Projekten entwickelt. Der Fokus auf KMP-Workflows trägt zu einem effizienteren und zuverlässigeren Build-Prozess bei.

  • Verbesserte IDE-Integration:Bessere Vervollständigung von Code, Navigation, Fehlerbehebung und allgemeine Entwicklungsumgebung bei der Arbeit mit KMP-Android-Bibliotheken.

  • Vereinfachte Projektkonfiguration:Das Plug-in vereinfacht die Konfiguration für KMP-Projekte, indem es Android-spezifische Komplexitäten wie Build-Varianten entfernt. Das führt zu übersichtlicheren und besser wartbaren Build-Dateien. Bisher konnten durch die Verwendung des com.android.library-Plug-ins in KMP-Projekten verwirrende Quellsetnamen wie androidAndroidTest entstehen. Diese Namenskonvention war für Entwickler, die mit den Standardprojektstrukturen von KMP vertraut sind, weniger intuitiv.

Voraussetzungen

Damit Sie das com.android.kotlin.multiplatform.library-Plug-in verwenden können, muss Ihr Projekt mit den folgenden Mindestversionen oder höher konfiguriert sein:

  • Android-Gradle-Plug-in (AGP): 8.10.0
  • Kotlin Gradle-Plug-in (KGP): 2.0.0

Android-KMP-Plug-in auf ein vorhandenes Modul anwenden

So wenden Sie das Android-KMP-Plug-in auf ein vorhandenes KMP-Bibliotheksmodul an:

  1. Plug-ins im Versionskatalog deklarieren: Öffnen Sie die TOML-Datei des Versionskatalogs (normalerweise gradle/libs.versions.toml) und fügen Sie den Abschnitt mit den Plug-in-Definitionen hinzu:

    # To check the version number of the latest Kotlin release, go to
    # https://kotlinlang.org/docs/releases.html
    
    [versions]
    androidGradlePlugin = "8.12.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" }
    
  2. Plug-in-Deklaration in der Root-Build-Datei anwenden Öffnen Sie die Datei build.gradle.kts im Stammverzeichnis Ihres Projekts. Fügen Sie die Plug-in-Aliasse dem plugins-Block mit apply false hinzu. Dadurch sind die Plug-in-Aliase für alle Unterprojekte verfügbar, ohne dass die Plug-in-Logik auf das Stammprojekt selbst angewendet wird.

    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
    }
  3. Wenden Sie das Plug-in in der Build-Datei eines KMP-Bibliotheksmoduls an. Öffnen Sie die Datei build.gradle.kts in Ihrem KMP-Bibliotheksmodul und wenden Sie das Plug-in oben in der Datei im Block plugins an:

    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)
    }
  4. Android-KMP-Ziel konfigurieren Konfigurieren Sie den Kotlin Multiplatform-Block (kotlin), um das Android-Ziel zu definieren. Geben Sie im Block kotlin das Android-Ziel mit androidLibrary an:

    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.) ...
    }
  5. Änderungen übernehmen Nachdem Sie das Plug-in angewendet und den kotlin-Block konfiguriert haben, synchronisieren Sie Ihr Gradle-Projekt, um die Änderungen zu übernehmen.

Vom alten Plug-in migrieren

Dieser Leitfaden hilft Ihnen bei der Migration vom alten com.android.library-Plug-in zum com.android.kotlin.multiplatform.library-Plug-in.

1. Abhängigkeiten deklarieren

Eine häufige Aufgabe ist das Deklarieren von Abhängigkeiten für Android-spezifische Quellsets. Beim neuen Plug‑in müssen diese explizit im sourceSets-Block platziert werden, im Gegensatz zum allgemeinen dependencies-Block, der zuvor verwendet wurde.

Android-KMP

Das neue Plug-in sorgt für eine übersichtlichere Struktur, indem Android-Abhängigkeiten in der androidMain-Quellgruppe zusammengefasst werden. Zusätzlich zum Hauptquellenset gibt es zwei Testquellensets, die bei Bedarf erstellt werden: androidDeviceTest und androidHostTest. Weitere Informationen finden Sie unter Host- und Gerätetests konfigurieren.

// 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")
        }
    }
}

Die Quellsätze haben entsprechende Kotlin-Kompilierungen mit den Namen main, deviceTest und hostTest. Die Quellsätze und Kompilierungen können im Build-Skript so konfiguriert werden:

// build.gradle.kts

kotlin {
    androidLibrary {
        compilations.getByName("deviceTest") {
            kotlinOptions.languageVersion = "2.0"
        }
    }
}

Legacy-Plug-in

Mit dem alten Plug-in konnten Sie Android-spezifische Abhängigkeiten im Abhängigkeitsblock auf oberster Ebene deklarieren, was in einem Multiplattformmodul manchmal verwirrend sein konnte.

// 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. Android-Ressourcen aktivieren

Die Unterstützung für Android-Ressourcen (res-Ordner) ist im neuen Plugin nicht standardmäßig aktiviert, um die Build-Leistung zu optimieren. Sie müssen sie aktivieren, um sie nutzen zu können. Durch diese Änderung wird sichergestellt, dass Projekte, für die keine Android-spezifischen Ressourcen erforderlich sind, nicht durch den damit verbundenen Build-Overhead belastet werden.

Android-KMP

Sie müssen die Verarbeitung von Android-Ressourcen explizit aktivieren. Die Ressourcen sollten in src/androidMain/res platziert werden.

// build.gradle.kts

kotlin {
  android {
    // ...
    // Enable Android resource processing
    androidResources {
      enable = true
    }
  }
}

// Project Structure
// └── src
//     └── androidMain
//         └── res
//             ├── values
//             │   └── strings.xml
//             └── drawable
//                 └── icon.xml

Legacy-Plug-in

Die Ressourcenverarbeitung war standardmäßig aktiviert. Sie können sofort ein res-Verzeichnis in src/main hinzufügen und mit dem Hinzufügen von XML-Drawables, -Werten usw. beginnen.

// 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. Host- und Gerätetests konfigurieren

Eine wichtige Änderung im neuen Plug-in ist, dass Android-Host-seitige (Unit-) und geräteseitige (instrumentierte) Tests standardmäßig deaktiviert sind. Sie müssen die Testquellsätze und ‑konfigurationen explizit aktivieren, während sie vom alten Plug-in automatisch erstellt wurden.

Dieses Opt-in-Modell trägt dazu bei, dass Ihr Projekt schlank bleibt und nur die Build-Logik und Quellsätze enthält, die Sie aktiv verwenden.

Android-KMP

Im neuen Plugin aktivieren und konfigurieren Sie Tests im kotlin.android-Block. Dadurch wird die Einrichtung expliziter und es werden keine ungenutzten Testkomponenten erstellt. Die Quellgruppe test wird zu androidHostTest und androidTest zu 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-Plug-in

Mit dem com.android.library-Plug‑in wurden die Quellsets test und androidTest standardmäßig erstellt. Sie konfigurieren das Verhalten im android-Block, in der Regel mit der 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. Java-Quellcode-Kompilierung aktivieren

Wenn für das Android-Ziel Ihrer KMP-Bibliothek Java-Quellen kompiliert werden müssen, müssen Sie diese Funktion mit dem neuen Plug-in explizit aktivieren. Dadurch wird die Kompilierung für Java-Dateien aktiviert, die sich direkt in Ihrem Projekt befinden, nicht für die zugehörigen Abhängigkeiten. Auch die Methode zum Festlegen der JVM-Zielversion des Java- und Kotlin-Compilers ändert sich.

Android-KMP

Sie müssen die Java-Kompilierung durch Aufrufen von withJava() aktivieren. Das JVM-Ziel wird jetzt direkt im kotlin { androidLibrary {} }-Block konfiguriert, um die Einrichtung zu vereinheitlichen. Die Einstellung von jvmTarget hier gilt sowohl für die Kotlin- als auch für die Java-Kompilierung für das Android-Ziel.

// 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-Plug-in

Die Java-Kompilierung war standardmäßig aktiviert. Das JVM-Ziel für Java- und Kotlin-Quellen wurde im android-Block mit compileOptions festgelegt.

// build.gradle.kts

android {
  // ...
  compileOptions {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
  }
}

kotlin {
  androidTarget {
    compilations.all {
      kotlinOptions.jvmTarget = "1.8"
    }
  }
}

5. Mit Build-Varianten über androidComponents interagieren

Die androidComponents-Erweiterung ist weiterhin verfügbar, um programmgesteuert mit Build-Artefakten zu interagieren. Die Variant API bleibt weitgehend unverändert, die neue AndroidKotlinMultiplatformVariant-Schnittstelle ist jedoch eingeschränkter, da das Plug-in nur eine Variante erzeugt.

Daher sind Properties, die sich auf Build-Typen und Produktvarianten beziehen, nicht mehr für das Variant-Objekt verfügbar.

Android-KMP

Der onVariants-Block wird jetzt für eine einzelne Variante durchlaufen. Sie können weiterhin auf allgemeine Eigenschaften wie name und artifacts zugreifen, aber keine buildtypspezifischen Eigenschaften verwenden.

// build.gradle.kts

androidComponents {
  onVariants { variant ->
      val artifacts = variant.artifacts
  }
}

Legacy-Plug-in

Mit mehreren Varianten konnten Sie auf build-typspezifische Eigenschaften zugreifen, um Aufgaben zu konfigurieren.

// build.gradle.kts

androidComponents {
  onVariants(selector().withBuildType("release")) { variant ->
    // ...
  }
}

6. Varianten von Android-Bibliotheksabhängigkeiten auswählen

Ihre KMP-Bibliothek erzeugt eine einzelne Variante für Android. Möglicherweise sind Sie jedoch von einer Standard-Android-Bibliothek (com.android.library) mit mehreren Varianten abhängig, z.B. free/paid Produktvarianten). Es ist häufig erforderlich, zu steuern, wie in Ihrem Projekt eine Variante aus dieser Abhängigkeit ausgewählt wird.

Android-KMP

Das neue Plugin zentralisiert und verdeutlicht diese Logik im kotlin.android.localDependencySelection-Block. So ist viel klarer, welche Varianten externer Abhängigkeiten für Ihre KMP-Bibliothek mit einer Variante ausgewählt werden.

// 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-Plug-in

Sie haben Strategien zur Auswahl von Abhängigkeiten in den buildTypes and productFlavors-Blöcken konfiguriert. Dazu musste häufig missingDimensionStrategy verwendet werden, um einen Standard-Flavor für eine Dimension bereitzustellen, die in Ihrer Bibliothek nicht vorhanden war, oder matchingFallbacks innerhalb eines bestimmten Flavors, um eine Suchreihenfolge zu definieren.

Weitere Informationen zur API-Nutzung finden Sie unter Abgleichsfehler beheben.

Plugin API-Referenz

Das neue Plug-in hat eine andere API-Oberfläche als com.android.library. Ausführliche Informationen zur neuen DSL und zu den neuen Schnittstellen finden Sie in den API-Referenzen: