Configura el complemento de biblioteca de Android Gradle para KMP

El complemento de Gradle com.android.kotlin.multiplatform.library es la herramienta compatible oficialmente para agregar un destino de Android a un módulo de biblioteca de Kotlin Multiplatform (KMP). Simplifica la configuración del proyecto, mejora el rendimiento de la compilación y ofrece una mejor integración con Android Studio.

El enfoque anterior ahora está en desuso en favor del complemento, también conocido como el complemento de Android-KMP. JetBrains ya no admitirá el uso del complemento com.android.library para KMP, y este no se beneficiará de las futuras actualizaciones y mejoras.

Para aplicar este complemento, consulta la sección Aplica el complemento de Android-KMP. Si necesitas migrar desde las APIs heredadas, consulta la Guía de migración.

Funciones y diferencias clave

El complemento Android-KMP está diseñado específicamente para proyectos de KMP y difiere del complemento com.android.library estándar en varios aspectos clave:

  • Arquitectura de una sola variante: El complemento usa una sola variante, lo que quita la compatibilidad con las variantes de producto y los tipos de compilación, lo que simplifica la configuración y mejora el rendimiento de la compilación.

  • Optimizado para KMP: El complemento está diseñado para bibliotecas de KMP y se enfoca en el código Kotlin compartido y la interoperabilidad, y omite la compatibilidad con las compilaciones nativas específicas de Android, AIDL y RenderScript.

  • Pruebas inhabilitadas de forma predeterminada: Tanto las pruebas de unidades como las de dispositivos (instrumentación) están inhabilitadas de forma predeterminada para mejorar la velocidad de compilación. Puedes habilitarlos si es necesario.

  • Sin extensión de Android de nivel superior: La configuración se controla con un bloque androidLibrary dentro del DSL de KMP de Gradle, lo que mantiene una estructura de proyecto de KMP coherente. No hay un bloqueo de extensión de android de nivel superior.

  • Compilación de Java opcional: La compilación de Java está inhabilitada de forma predeterminada. Usa withJava() en el bloque androidLibrary para habilitarlo. Esto mejora los tiempos de compilación cuando no se necesita la compilación de Java.

Beneficios del complemento de la biblioteca de Android-KMP

El complemento de Android-KMP proporciona los siguientes beneficios para los proyectos de KMP:

  • Mejoras en el rendimiento y la estabilidad de la compilación: Se diseñó para optimizar las velocidades de compilación y mejorar la estabilidad en los proyectos de KMP. Su enfoque en los flujos de trabajo de KMP contribuye a un proceso de compilación más eficiente y confiable.

  • Integración mejorada del IDE: Proporciona mejores funciones de autocompletado de código, navegación, depuración y experiencia general del desarrollador cuando se trabaja con bibliotecas de KMP para Android.

  • Configuración simplificada del proyecto: El complemento simplifica la configuración de los proyectos de KMP, ya que quita las complejidades específicas de Android, como las variantes de compilación. Esto genera archivos de compilación más limpios y fáciles de mantener. Anteriormente, usar el complemento com.android.library en un proyecto de KMP podía crear nombres de conjuntos de fuentes confusos, como androidAndroidTest. Esta convención de nomenclatura era menos intuitiva para los desarrolladores familiarizados con las estructuras de proyectos de KMP estándar.

Requisitos previos

Para usar el complemento com.android.kotlin.multiplatform.library, tu proyecto debe configurarse con las siguientes versiones mínimas o superiores:

  • Complemento de Android para Gradle (AGP): 8.10.0
  • Complemento de Gradle para Kotlin (KGP): 2.0.0

Aplica el complemento Android-KMP a un módulo existente

Para aplicar el complemento Android-KMP a un módulo de biblioteca de KMP existente, sigue estos pasos:

  1. Declara complementos en el catálogo de versiones. Abre el archivo TOML del catálogo de versiones (generalmente gradle/libs.versions.toml) y agrega la sección de definiciones de complementos:

    # 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. Aplica la declaración del complemento en el archivo de compilación raíz. Abre el archivo build.gradle.kts ubicado en el directorio raíz de tu proyecto. Agrega los alias del complemento al bloque plugins con apply false. Esto hace que los alias del complemento estén disponibles para todos los subproyectos sin aplicar la lógica del complemento al proyecto raíz.

    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. Aplica el complemento en un archivo de compilación de módulo de biblioteca de KMP. Abre el archivo build.gradle.kts en tu módulo de biblioteca de KMP y aplica el complemento en la parte superior del archivo dentro del bloque 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. Configura el destino de KMP de Android. Configura el bloque Kotlin Multiplatform (kotlin) para definir el destino de Android. Dentro del bloque kotlin, especifica el destino de Android con 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. Aplica los cambios. Después de aplicar el complemento y configurar el bloque kotlin, sincroniza tu proyecto de Gradle para aplicar los cambios.

Migra desde el complemento heredado

Esta guía te ayuda a migrar del complemento heredado com.android.library al complemento com.android.kotlin.multiplatform.library.

1. Cómo declarar dependencias

Una tarea común es declarar dependencias para los conjuntos de fuentes específicos de Android. El nuevo complemento requiere que estos se coloquen de forma explícita dentro del bloque sourceSets, a diferencia del bloque dependencies general que se usaba anteriormente.

Android-KMP

El nuevo complemento promueve una estructura más limpia agrupando las dependencias de Android dentro del conjunto de orígenes androidMain. Además del conjunto de fuentes principal, hay dos conjuntos de fuentes de prueba que se crean a pedido: androidDeviceTest y androidHostTest (consulta la configuración de pruebas de host y dispositivo para obtener más información).

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

Los conjuntos de fuentes tienen compilaciones de Kotlin correspondientes llamadas main, deviceTest y hostTest. Los conjuntos de fuentes y las compilaciones se pueden configurar en la secuencia de comandos de compilación de la siguiente manera:

// build.gradle.kts

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

Complemento heredado

Con el complemento anterior, podías declarar dependencias específicas de Android en el bloque de dependencias de nivel superior, lo que a veces podía ser confuso en un módulo multiplataforma.

// 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. Cómo habilitar recursos de Android

La compatibilidad con los recursos de Android (carpetas res) no está habilitada de forma predeterminada en el nuevo complemento para optimizar el rendimiento de la compilación. Debes habilitar la opción para usarlos. Este cambio ayuda a garantizar que los proyectos que no requieren recursos específicos de Android no se vean afectados por la sobrecarga de compilación asociada.

Android-KMP

Debes habilitar explícitamente el procesamiento de recursos de Android. Los recursos se deben colocar en 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

Complemento heredado

El procesamiento de recursos se habilitó de forma predeterminada. Podrías agregar de inmediato un directorio res en src/main y comenzar a agregar elementos de diseño, valores, etcétera, en 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. Cómo configurar pruebas de host y dispositivo

Un cambio significativo en el nuevo complemento es que las pruebas de Android del host (unidades) y del dispositivo (instrumentadas) están inhabilitadas de forma predeterminada. Debes habilitar explícitamente la creación de los conjuntos de orígenes y las configuraciones de prueba, mientras que el complemento anterior los creaba automáticamente.

Este modelo de aceptación ayuda a verificar que tu proyecto siga siendo eficiente y solo incluya la lógica de compilación y los conjuntos de fuentes que usas de forma activa.

Android-KMP

En el nuevo complemento, puedes habilitar y configurar pruebas dentro del bloque kotlin.android. Esto hace que la configuración sea más explícita y evita la creación de componentes de prueba sin usar. El conjunto de fuentes test se convierte en androidHostTest, y androidTest se convierte en 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

Complemento heredado

Con el complemento com.android.library, los conjuntos de fuentes test y androidTest se crearon de forma predeterminada. Configurarías su comportamiento dentro del bloque android, por lo general, con el DSL de 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. Habilita la compilación de código fuente Java

Si tu biblioteca de KMP necesita compilar fuentes de Java para su destino de Android, debes habilitar explícitamente esta funcionalidad con el nuevo complemento. Ten en cuenta que esto habilita la compilación de los archivos Java ubicados directamente dentro de tu proyecto, no para sus dependencias. También cambia el método para establecer la versión de destino de la JVM del compilador de Java y Kotlin.

Android-KMP

Debes habilitar la compilación de Java llamando a withJava(). El destino de JVM ahora se configura directamente dentro del bloque kotlin { androidLibrary {} } para una configuración más unificada. El parámetro de configuración jvmTarget aquí se aplica a la compilación de Kotlin y Java para el destino de 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

Complemento heredado

La compilación de Java estaba habilitada de forma predeterminada. El destino de JVM para las fuentes de Java y Kotlin se estableció en el bloque de Android con 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úa con las variantes de compilación usando androidComponents

La extensión androidComponents sigue disponible para interactuar con artefactos de compilación de forma programática. Si bien gran parte de la API de Variant sigue siendo la misma, la nueva interfaz de AndroidKotlinMultiplatformVariant es más limitada porque el complemento solo produce una variante.

En consecuencia, las propiedades relacionadas con los tipos de compilación y las variantes de producto ya no están disponibles en el objeto de variante.

Android-KMP

El bloque onVariants ahora itera sobre una sola variante. Aún puedes acceder a propiedades comunes, como name y artifacts, pero no a las específicas del tipo de compilación.

// build.gradle.kts

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

Complemento heredado

Con varias variantes, puedes acceder a propiedades específicas del tipo de compilación para configurar tareas.

// build.gradle.kts

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

6. Selecciona variantes de dependencias de bibliotecas de Android

Tu biblioteca de KMP produce una sola variante para Android. Sin embargo, es posible que dependas de una biblioteca estándar de Android (com.android.library) que tenga varias variantes (p.ej., free/paid variantes de productos). Controlar cómo tu proyecto selecciona una variante de esa dependencia es un requisito común.

Android-KMP

El nuevo complemento centraliza y aclara esta lógica dentro del bloque kotlin.android.localDependencySelection. Esto deja mucho más claro qué variantes de dependencias externas se seleccionarán para tu biblioteca de KMP de una sola variante.

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

Complemento heredado

Configuraste estrategias de selección de dependencias dentro de los bloques buildTypes and productFlavors. Esto a menudo implicaba usar missingDimensionStrategy para proporcionar un tipo predeterminado para una dimensión que tu biblioteca no tenía, o matchingFallbacks dentro de un tipo específico para definir un orden de búsqueda.

Consulta Cómo resolver errores de coincidencia para obtener información más detallada sobre el uso de la API.

Referencia de la API del complemento

El nuevo complemento tiene una superficie de API diferente a la de com.android.library. Para obtener información detallada sobre el nuevo DSL y las interfaces, consulta las referencias de la API: