Configurare il plug-in Android Gradle Library per KMP

Il plug-in Gradle com.android.kotlin.multiplatform.library è lo strumento ufficialmente supportato per aggiungere un target Android a un modulo della libreria Kotlin Multiplatform (KMP). Semplifica la configurazione del progetto, migliora le prestazioni di build e offre una migliore integrazione con Android Studio.

L'approccio precedente è ora deprecato a favore del plug-in, noto anche come plug-in Android-KMP. L'utilizzo del plug-in com.android.library per KMP non sarà più supportato da JetBrains e non beneficerà di futuri aggiornamenti e miglioramenti.

Per applicare questo plug-in, consulta la sezione Applica il plug-in Android-KMP. Se devi eseguire la migrazione dalle API legacy, consulta la guida alla migrazione.

Funzionalità e differenze principali

Il plug-in Android-KMP è progettato appositamente per i progetti KMP e si differenzia dal plug-in com.android.library standard per diversi aspetti chiave:

  • Architettura a singola variante:il plug-in utilizza una singola variante, rimuovendo il supporto per le varianti di prodotto e i tipi di build, il che semplifica la configurazione e migliora il rendimento della build.

  • Ottimizzato per KMP:il plug-in è progettato per le librerie KMP, con particolare attenzione al codice Kotlin condiviso e all'interoperabilità, omettendo il supporto per build native specifiche per Android, AIDL e RenderScript.

  • Test disattivati per impostazione predefinita: sia i test delle unità sia quelli del dispositivo (strumentazione) sono disattivati per impostazione predefinita per migliorare la velocità di compilazione. Puoi attivarli se necessario.

  • Nessuna estensione Android di primo livello:la configurazione viene gestita con un blocco androidLibrary all'interno di Gradle KMP DSL, mantenendo una struttura di progetto KMP coerente. Non è presente alcun blocco dell'estensione android di primo livello.

  • Compilazione Java con attivazione: la compilazione Java è disattivata per impostazione predefinita. Utilizza withJava() nel blocco androidLibrary per abilitarlo. In questo modo i tempi di compilazione migliorano quando non è necessaria la compilazione Java.

Vantaggi del plug-in della libreria Android-KMP

Il plug-in Android-KMP offre i seguenti vantaggi per i progetti KMP:

  • Prestazioni e stabilità della build migliorate: è progettato per velocità di build ottimizzate e stabilità migliorata all'interno dei progetti KMP. L'attenzione ai flussi di lavoro KMP contribuisce a un processo di compilazione più efficiente e affidabile.

  • Integrazione IDE avanzata:offre un migliore completamento del codice, navigazione, debug ed esperienza complessiva degli sviluppatori quando si lavora con le librerie KMP Android.

  • Configurazione semplificata del progetto: il plug-in semplifica la configurazione per i progetti KMP rimuovendo le complessità specifiche di Android, come le varianti di build. In questo modo, i file di build saranno più puliti e più facili da gestire. In precedenza, l'utilizzo del plug-in com.android.library nel progetto KMP poteva creare nomi di set di origine confusi, ad esempio androidAndroidTest. Questa convenzione di denominazione era meno intuitiva per gli sviluppatori che conoscono le strutture standard dei progetti KMP.

Prerequisiti

Per utilizzare il plug-in com.android.kotlin.multiplatform.library, il progetto deve essere configurato con le seguenti versioni minime o successive:

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

Applica il plug-in Android-KMP a un modulo esistente

Per applicare il plug-in Android-KMP a un modulo della libreria KMP esistente, segui questi passaggi:

  1. Dichiarare i plug-in nel catalogo delle versioni. Apri il file TOML del catalogo delle versioni (di solito gradle/libs.versions.toml) e aggiungi la sezione delle definizioni dei 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. Applica la dichiarazione del plug-in nel file di build principale. Apri il file build.gradle.kts che si trova nella directory principale del progetto. Aggiungi gli alias del plug-in al blocco plugins utilizzando apply false. In questo modo, gli alias del plug-in sono disponibili per tutti i progetti secondari senza applicare la logica del plug-in al progetto principale stesso.

    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
    }

    Trendy

    // 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. Applica il plug-in in un file di build del modulo della libreria KMP. Apri il file build.gradle.kts nel modulo della libreria KMP e applica il plug-in nella parte superiore del file all'interno del blocco plugins:

    Kotlin

    // Module-specific build.gradle.kts file
    
    plugins {
       alias(libs.plugins.kotlin.multiplatform)
    
       // Add the following
       alias(libs.plugins.android.kotlin.multiplatform.library)
    }

    Trendy

    // Module-specific build.gradle file
    
    plugins {
       alias(libs.plugins.kotlin.multiplatform)
    
       // Add the following
       alias(libs.plugins.android.kotlin.multiplatform.library)
    }
  4. Configura la destinazione KMP di Android. Configura il blocco Kotlin Multiplatform (kotlin) per definire il target Android. All'interno del blocco kotlin, specifica il target Android utilizzando 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.) ...
    }

    Trendy

    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. Applica modifiche. Dopo aver applicato il plug-in e configurato il blocco kotlin, sincronizza il progetto Gradle per applicare le modifiche.

Eseguire la migrazione dal plug-in precedente

Questa guida ti aiuta a eseguire la migrazione dal plug-in com.android.library legacy al plug-in com.android.kotlin.multiplatform.library.

1. Dichiarazione delle dipendenze

Un'attività comune è la dichiarazione delle dipendenze per i set di origini specifici per Android. Il nuovo plug-in richiede che questi elementi vengano inseriti esplicitamente all'interno del blocco sourceSets, a differenza del blocco dependencies generale utilizzato in precedenza.

Android-KMP

Il nuovo plug-in promuove una struttura più pulita raggruppando le dipendenze Android all'interno del set di origine androidMain. Oltre al set di origini principale, esistono due set di origini di test, che vengono creati su richiesta: androidDeviceTest e androidHostTest (per ulteriori informazioni, consulta la sezione Configurazione dei test di host e dispositivo).

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

I set di origine hanno compilazioni Kotlin corrispondenti denominate main, deviceTest e hostTest. I set di origini e le compilazioni possono essere configurati nello script di build nel seguente modo:

// build.gradle.kts

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

Plug-in legacy

Con il vecchio plug-in, potevi dichiarare dipendenze specifiche per Android nel blocco delle dipendenze di primo livello, il che a volte poteva creare confusione in un modulo multipiattaforma.

// 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. Attivare le risorse Android

Il supporto per le risorse Android (cartelle res) non è attivato per impostazione predefinita nel nuovo plug-in per ottimizzare le prestazioni di build. Per utilizzarli, devi attivarli. Questa modifica contribuisce a garantire che i progetti che non richiedono risorse specifiche per Android non siano appesantiti dal sovraccarico di build associato.

Android-KMP

Devi abilitare esplicitamente l'elaborazione delle risorse Android. Le risorse devono essere inserite 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

Plug-in legacy

Il trattamento delle risorse è stato attivato per impostazione predefinita. Potresti aggiungere immediatamente una directory res in src/main e iniziare ad aggiungere risorse disegnabili, valori e così via in formato XML.

// 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. Configurazione dei test di host e dispositivo

Una modifica significativa nel nuovo plug-in è che i test lato host (unità) e lato dispositivo (strumentati) di Android sono disattivati per impostazione predefinita. Devi attivare esplicitamente la creazione di set e configurazioni di origini di test, mentre il vecchio plug-in li creava automaticamente.

Questo modello di attivazione contribuisce a verificare che il progetto rimanga snello e includa solo la logica di build e i set di origini che utilizzi attivamente.

Android-KMP

Nel nuovo plug-in, puoi attivare e configurare i test all'interno del blocco kotlin.android. In questo modo la configurazione è più esplicita ed evita la creazione di componenti di test inutilizzati. Il set di origine test diventa androidHostTest e androidTest diventa 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

Plug-in legacy

Con il plug-in com.android.library, i set di origini test e androidTest sono stati creati per impostazione predefinita. Il loro comportamento viene configurato all'interno del blocco android, in genere utilizzando il linguaggio specifico del dominio 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. Abilita la compilazione dell'origine Java

Se la tua libreria KMP deve compilare origini Java per il target Android, devi abilitare esplicitamente questa funzionalità con il nuovo plug-in. Tieni presente che questo consente la compilazione per i file Java che si trovano direttamente all'interno del progetto, non per le sue dipendenze. Cambia anche il metodo per impostare la versione di destinazione della JVM del compilatore Java e Kotlin.

Android-KMP

Devi attivare la compilazione Java chiamando withJava(). La destinazione JVM ora è configurata direttamente all'interno del blocco kotlin { androidLibrary {} } per una configurazione più unificata. L'impostazione jvmTarget qui si applica sia alla compilazione Kotlin sia a quella Java per il target 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

Plug-in legacy

La compilazione Java era attiva per impostazione predefinita. La JVM di destinazione per le origini Java e Kotlin è stata impostata nel blocco android utilizzando 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. Interagire con le varianti di build utilizzando androidComponents

L'estensione androidComponents è ancora disponibile per interagire con gli artefatti di build in modo programmatico. Sebbene gran parte dell'API Variant rimanga invariata, l'interfaccia AndroidKotlinMultiplatformVariant è più limitata perché il plug-in produce una sola variante.

Di conseguenza, le proprietà correlate ai tipi di build e alle varianti di prodotto non sono più disponibili nell'oggetto variante.

Android-KMP

Il blocco onVariants ora scorre una singola variante. Puoi comunque accedere a proprietà comuni come name e artifacts, ma non a quelle specifiche per il tipo di build.

// build.gradle.kts

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

Plug-in legacy

Con più varianti, puoi accedere a proprietà specifiche del tipo di build per configurare le attività.

// build.gradle.kts

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

6. Seleziona le varianti delle dipendenze della libreria Android

La libreria KMP produce una sola variante per Android. Tuttavia, potresti dipendere da una libreria Android standard (com.android.library) che ha più varianti (ad es. free/paid versioni prodotto). Controllare il modo in cui il progetto seleziona una variante da questa dipendenza è un requisito comune.

Android-KMP

Il nuovo plug-in centralizza e chiarisce questa logica all'interno del blocco kotlin.android.localDependencySelection. In questo modo è molto più chiaro quali varianti delle dipendenze esterne verranno selezionate per la tua libreria KMP a variante singola.

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

Plug-in legacy

Hai configurato le strategie di selezione delle dipendenze all'interno dei blocchi buildTypes and productFlavors. Spesso si trattava di utilizzare missingDimensionStrategy per fornire una variante predefinita per una dimensione non presente nella libreria o matchingFallbacks all'interno di una variante specifica per definire un ordine di ricerca.

Per informazioni più dettagliate sull'utilizzo dell'API, consulta la sezione Risolvere gli errori di corrispondenza.

Riferimento API plug-in

Il nuovo plug-in ha una superficie API diversa da com.android.library. Per informazioni dettagliate sul nuovo DSL e sulle nuove interfacce, consulta i riferimenti API: