Configurer le plug-in de bibliothèque Android Gradle pour KMP

Le plug-in Gradle com.android.kotlin.multiplatform.library est l'outil officiellement compatible pour ajouter une cible Android à un module de bibliothèque Kotlin Multiplatform (KMP). Il simplifie la configuration du projet, améliore les performances de compilation et offre une meilleure intégration à Android Studio.

L'approche précédente est désormais obsolète au profit du plug-in, également appelé plug-in Android-KMP. L'utilisation du plug-in com.android.library pour KMP ne sera plus prise en charge par JetBrains et ne bénéficiera plus des futures mises à jour et améliorations.

Pour appliquer ce plug-in, consultez la section Appliquer le plug-in Android-KMP. Si vous devez migrer à partir des anciennes API, consultez le guide de migration.

Principales caractéristiques et différences

Le plug-in Android-KMP est spécialement conçu pour les projets KMP et diffère du plug-in com.android.library standard sur plusieurs aspects clés :

  • Architecture à variante unique : le plug-in utilise une seule variante, ce qui supprime la prise en charge des types de produit et des types de compilation. La configuration est ainsi simplifiée et les performances de compilation améliorées.

  • Optimisé pour KMP : le plug-in est conçu pour les bibliothèques KMP. Il se concentre sur le code Kotlin partagé et l'interopérabilité, et ne prend pas en charge les compilations natives spécifiques à Android, AIDL et RenderScript.

  • Tests désactivés par défaut : les tests unitaires et les tests d'instrumentation (sur l'appareil) sont désactivés par défaut pour améliorer la vitesse de compilation. Vous pouvez les activer si nécessaire.

  • Pas d'extension Android de premier niveau : la configuration est gérée avec un bloc androidLibrary dans le DSL Gradle KMP, ce qui permet de maintenir une structure de projet KMP cohérente. Aucun blocage d'extension android de premier niveau n'est défini.

  • Compilation Java activée : la compilation Java est désactivée par défaut. Pour l'activer, utilisez withJava() dans le bloc androidLibrary. Cela permet d'améliorer les temps de compilation lorsque la compilation Java n'est pas nécessaire.

Avantages du plug-in de bibliothèque Android-KMP

Le plug-in Android-KMP offre les avantages suivants pour les projets KMP :

  • Amélioration des performances et de la stabilité de la compilation : elle est conçue pour optimiser la vitesse de compilation et améliorer la stabilité dans les projets KMP. L'accent mis sur les workflows KMP contribue à un processus de compilation plus efficace et fiable.

  • Intégration IDE améliorée : elle offre une meilleure saisie semi-automatique du code, une meilleure navigation, un meilleur débogage et une meilleure expérience globale pour les développeurs lorsqu'ils travaillent avec les bibliothèques KMP Android.

  • Configuration de projet simplifiée : le plug-in simplifie la configuration des projets KMP en supprimant les complexités spécifiques à Android, comme les variantes de compilation. Cela permet d'obtenir des fichiers de compilation plus clairs et plus faciles à gérer. Auparavant, l'utilisation du plug-in com.android.library dans un projet KMP pouvait créer des noms de source set déroutants, tels que androidAndroidTest. Cette convention de dénomination était moins intuitive pour les développeurs connaissant les structures de projet KMP standards.

Prérequis

Pour utiliser le plug-in com.android.kotlin.multiplatform.library, votre projet doit être configuré avec les versions minimales suivantes ou une version ultérieure :

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

Appliquer le plug-in Android-KMP à un module existant

Pour appliquer le plug-in Android-KMP à un module de bibliothèque KMP existant, procédez comme suit :

  1. Déclarez les plug-ins dans le catalogue de versions. Ouvrez le fichier TOML du catalogue de versions (généralement gradle/libs.versions.toml) et ajoutez la section des définitions de plug-in :

    # 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" }
    
  2. Appliquez la déclaration du plug-in dans le fichier de compilation racine. Ouvrez le fichier build.gradle.kts situé dans le répertoire racine de votre projet. Ajoutez les alias de plug-in au bloc plugins à l'aide de apply false. Cela rend les alias de plug-in disponibles pour tous les sous-projets sans appliquer la logique du plug-in au projet racine lui-même.

    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. Appliquez le plug-in dans un fichier de compilation de module de bibliothèque KMP. Ouvrez le fichier build.gradle.kts dans votre module de bibliothèque KMP et appliquez le plug-in en haut de votre fichier dans le bloc plugins :

    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. Configurez la cible Android KMP. Configurez le bloc Kotlin Multiplatform (kotlin) pour définir la cible Android. Dans le bloc kotlin, spécifiez la cible Android à l'aide de androidLibrary :

    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. Appliquez les modifications. Après avoir appliqué le plug-in et configuré le bloc kotlin, synchronisez votre projet Gradle pour appliquer les modifications.

Migrer depuis l'ancien plug-in

Ce guide vous aide à migrer de l'ancien plug-in com.android.library vers le plug-in com.android.kotlin.multiplatform.library.

1. Déclarer des dépendances

Une tâche courante consiste à déclarer des dépendances pour les ensembles de sources spécifiques à Android. Le nouveau plug-in exige que ces éléments soient placés explicitement dans le bloc sourceSets, contrairement au bloc dependencies général utilisé précédemment.

Android-KMP

Le nouveau plug-in favorise une structure plus propre en regroupant les dépendances Android dans l'ensemble de sources androidMain. En plus de l'ensemble de sources principal, deux ensembles de sources de test sont créés à la demande : androidDeviceTest et androidHostTest (consultez Configurer les tests d'hôte et d'appareil pour en savoir plus).

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

Les ensembles de sources ont des compilations Kotlin correspondantes nommées main, deviceTest et hostTest. Les ensembles de sources et les compilations peuvent être configurés dans le script de compilation comme suit :

// build.gradle.kts

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

Ancien plug-in

Avec l'ancien plug-in, vous pouviez déclarer des dépendances spécifiques à Android dans le bloc de dépendances de premier niveau, ce qui pouvait parfois être déroutant dans un module multiplate-forme.

// 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. Activer les ressources Android

La prise en charge des ressources Android (dossiers res) n'est pas activée par défaut dans le nouveau plug-in afin d'optimiser les performances de compilation. Vous devez les activer pour pouvoir les utiliser. Cette modification permet de s'assurer que les projets ne nécessitant pas de ressources spécifiques à Android ne sont pas soumis à la surcharge de compilation associée.

Android-KMP

Vous devez activer explicitement le traitement des ressources Android. Les ressources doivent être placées dans 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

Ancien plug-in

Le traitement des ressources était activé par défaut. Vous pouvez immédiatement ajouter un répertoire res dans src/main et commencer à ajouter des éléments drawables, des valeurs, 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. Configurer les tests d'hôte et d'appareil

Une modification importante du nouveau plug-in est que les tests Android côté hôte (unitaires) et côté appareil (instrumentés) sont désactivés par défaut. Vous devez activer explicitement la création des ensembles de sources et des configurations de test, alors que l'ancien plug-in les créait automatiquement.

Ce modèle d'activation permet de vérifier que votre projet reste léger et n'inclut que la logique de compilation et les ensembles de sources que vous utilisez activement.

Android-KMP

Dans le nouveau plug-in, vous activez et configurez les tests dans le bloc kotlin.android. Cela rend la configuration plus explicite et évite de créer des composants de test inutilisés. L'ensemble de sources test devient androidHostTest et androidTest devient 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

Ancien plug-in

Avec le plug-in com.android.library, les ensembles de sources test et androidTest ont été créés par défaut. Vous configurez leur comportement dans le bloc android, généralement à l'aide du DSL testOptions.

// 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. Activer la compilation de la source Java

Si votre bibliothèque KMP doit compiler des sources Java pour sa cible Android, vous devez activer explicitement cette fonctionnalité avec le nouveau plug-in. Notez que cela permet la compilation des fichiers Java situés directement dans votre projet, et non pour ses dépendances. La méthode de définition de la version cible JVM du compilateur Java et Kotlin change également.

Android-KMP

Vous devez activer la compilation Java en appelant withJava(). La cible JVM est désormais configurée directement dans le bloc kotlin { androidLibrary {} } pour une configuration plus unifiée. La définition de jvmTarget ici s'applique à la compilation Kotlin et Java pour la cible Android.

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

Ancien plug-in

La compilation Java était activée par défaut. La cible JVM pour les sources Java et Kotlin a été définie dans le bloc Android à l'aide de 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. Interagir avec les variantes de compilation à l'aide de androidComponents

L'extension androidComponents est toujours disponible pour interagir avec les artefacts de compilation de manière programmatique. Bien que la majeure partie de l'API Variant reste la même, la nouvelle interface AndroidKotlinMultiplatformVariant est plus limitée, car le plug-in ne produit qu'une seule variante.

Par conséquent, les propriétés liées aux types de compilation et aux types de produit ne sont plus disponibles sur l'objet variant.

Android-KMP

Le bloc onVariants itère désormais sur une seule variante. Vous pouvez toujours accéder aux propriétés courantes telles que name et artifacts, mais pas à celles spécifiques au type de compilation.

// build.gradle.kts

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

Ancien plug-in

Avec plusieurs variantes, vous pouvez accéder à des propriétés spécifiques au type de compilation pour configurer des tâches.

// build.gradle.kts

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

6. Sélectionner des variantes de dépendances de bibliothèque Android

Votre bibliothèque KMP produit une seule variante pour Android. Toutefois, vous pouvez dépendre d'une bibliothèque Android standard (com.android.library) qui comporte plusieurs variantes (par exemple, free/paid types de produit). Il est souvent nécessaire de contrôler la façon dont votre projet sélectionne une variante à partir de cette dépendance.

Android-KMP

Le nouveau plug-in centralise et clarifie cette logique dans le bloc kotlin.android.localDependencySelection. Il est ainsi beaucoup plus clair de savoir quelles variantes de dépendances externes seront sélectionnées pour votre bibliothèque KMP à variante unique.

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

Ancien plug-in

Vous avez configuré des stratégies de sélection des dépendances dans les blocs buildTypes and productFlavors. Cela impliquait souvent d'utiliser missingDimensionStrategy pour fournir un type par défaut pour une dimension dont votre bibliothèque était dépourvue, ou matchingFallbacks dans un type spécifique pour définir un ordre de recherche.

Pour en savoir plus sur l'utilisation de l'API, consultez Résoudre les erreurs de correspondance.

Documentation de référence de l'API du plug-in

La surface de l'API du nouveau plug-in est différente de celle de com.android.library. Pour obtenir des informations détaillées sur le nouveau DSL et les nouvelles interfaces, consultez les références de l'API :