Save the date! Android Dev Summit is coming to Sunnyvale, CA on Oct 23-24, 2019.

Cómo agregar dependencias de compilación

El sistema de compilación de Gradle en Android Studio facilita la inclusión de archivos binarios u otros módulos de biblioteca externos en tu compilación como dependencias. Las dependencias se pueden ubicar en tu máquina o en un repositorio remoto y cualquier dependencia transitiva que se declare se incluye de manera automática. En esta página, se describe la manera de usar estas dependencias con tu proyecto de Android, incluidos detalles sobre configuraciones y complementos específicos del complemento de Android para Gradle. Para obtener una guía conceptual más detallada sobre las dependencias de Gradle , también debes consultar la guía de Gradle para la administración de dependencias. No obstante, debes recordar que tu proyecto de Android solo debe usar las configuraciones de dependencias definidas en esta página.

Tipos de dependencias

Para agregar una dependencia a tu proyecto, especifica una configuración de dependencias como implementation en el bloque dependencies de tu archivo build.gradle.

En el siguiente archivo build.gradle, por ejemplo, para un módulo de app se incluyen tres tipos diferentes de dependencias:

apply plugin: 'com.android.application'

android { ... }

dependencies {
    // Dependency on a local library module
    implementation project(":mylibrary")

    // Dependency on local binaries
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    // Dependency on a remote binary
    implementation 'com.example.android:app-magic:12.3'
}

Cada una de ellas requiere una clase diferente de dependencias de bibliotecas:

Dependencia de módulo de biblioteca local
implementation project(':mylibrary')

Esto declara una dependencia en un Módulo de biblioteca de Android llamado "mylibrary" (este nombre debe coincidir con el de la biblioteca definido como un include: en tu archivo settings.gradle. Cuando creas una app, el sistema de compilación compila el módulo de biblioteca y empaqueta el contenido resultante en el APK.

Dependencia binaria local
implementation fileTree(dir: 'libs', include: ['*.jar'])

Gradle declara la dependencia de los archivos JAR dentro del directorio module_name/libs/ de tu proyecto (porque lee rutas relacionadas al archivo build.gradle).

De manera alternativa, puedes especificar archivos individuales de la siguiente manera:

implementation files('libs/foo.jar', 'libs/bar.jar')
Dependencia binaria remota
implementation 'com.example.android:app-magic:12.3'

Esto es realmente una versión abreviada de lo siguiente:

implementation group: 'com.example.android', name: 'app-magic', version: '12.3'

Esto declara una dependencia en la versión 12.3 de la biblioteca "app-magic", dentro del grupo del espacio de nombres "com.example.android".

Nota: Las dependencias remotas como esta exigen que declares los repositorios remotos correspondientes cuando Gradle debe buscar la biblioteca. Si la biblioteca todavía no existe localmente, Gradle la obtiene del sitio remoto cuando la compilación la exige (por ejemplo, cuando haces clic en Sync Project with Gradle Files o cuando ejecutas una compilación).

Configuraciones de dependencia

Dentro del bloque dependencies, puedes declarar una dependencia de biblioteca usando una de las diferentes configuracionesde dependencias (como implementation, que se muestra previamente). La configuración de cada dependencia proporciona a Gradle diferentes instrucciones sobre el modo de usar la dependencia. En la siguiente tabla, se describe cada una de las configuraciones que puedes usar para una dependencia en tu proyecto de Android. La tabla también compara estas configuraciones con las que quedaron obsoletas, como las de Android Gradle Plugin 3.0.0.

Configuración nueva Configuración obsoleta Comportamiento
implementation compile Gradle agrega la dependencia a la classpath de compilación y empaqueta la dependencia en el resultado de la compilación. Sin embargo, cuando tu modulo configura una dependencia del tipo implementation, le deja saber a Gradle que no quieres que el módulo filtre la dependencia a otros módulos en tiempo de compilación. Es decir, la dependencia se encuentra disponible para otros módulos solo en el tiempo de ejecución.

El uso de esta configuración de dependencia en lugar de api o compile (obsoleto) puede generar mejoras importantes en el tiempo de compilación, ya que reduce la cantidad de módulos que el sistema de compilación debe volver a compilar. Por ejemplo, si una dependencia implementation cambia su API, Gradle solo vuelve a compilar esa dependencia y los módulos que dependen directamente de él. La mayoría de los módulos de apps y de prueba deben usar esta configuración.

api compile Gradle agrega la dependencia a la classpath y al resultado de la compilación. Cuando un módulo incluye una dependencia api, le indica a Gradle que el módulo quiere exportar de forma transitiva esa dependencia a otros módulos, de modo que esté disponible para ellos en el tiempo de ejecución y compilación.

Este configuración se comporta como compile (que quedó obsoleto), pero debes utilizarlo con precaución y solo con las dependencias que necesites exportar transitivamente a los consumidores ascendentes. Eso ocurre porque, si una dependencia api cambia su API externa, Gradle vuelve a compilar todos los módulos que tienen acceso a esa dependencia en el tiempo de ejecución. Por lo tanto, contar con un gran número de dependencias api puede aumentar considerablemente el tiempo de compilación. A menos que quieras exponer la API de una dependencia en un módulo de prueba separado, los módulos de la biblioteca deben, en cambio, usar dependencias implementation.

compileOnly provided Gradle solo agrega la dependencia a la classpath de compilación (no se agrega al resultado de compilación). Esto resulta útil cuando creas un módulo de biblioteca de Android y necesitas la dependencia durante la compilación, pero es opcional en el tiempo de ejecución.

Es decir, si usas esta configuración, tu módulo de biblioteca debe incluir una condición de tiempo de ejecución para comprobar si la dependencia se encuentra disponible, y luego cambiar su comportamiento correctamente para que aún así funcione si no se proporciona. Esto ayuda a reducir el tamaño del APK final al no agregar las dependencias transitorias que no son críticas. Este configuración se comporta como provided (que ya es obsoleta).

runtimeOnly apk Gradle agrega la dependencia al resultado de compilación para su uso durante el tiempo de ejecución. Es decir, esta no se agrega a la classpath de compilación. Esta configuración se comporta como apk (que ya es obsoleta).
annotationProcessor compile Para agregar una dependencia de una biblioteca que es un procesador de anotaciones, debes añadirla a la classpath del procesador de anotaciones utilizando la configuración de annotationProcessor. Esto se debe a que el uso de esta configuración mejora el rendimiento de la compilación al separar el classpath de compilación del procesador de anotaciones. Si Gradle detecta procesadores de anotaciones en el classpath de compilación, desactivará la evasión de compilaciones, que impacta de forma negativa en el tiempo de compilación (Gradle 5.0 y versiones posteriores ignoran los procesadores de anotaciones encontrados en el classpath de compilación).

Android Gradle Plugin asume que una dependencia es un procesador de anotación si su archivo JARcontiene el siguiente archivo:
META-INF/services/javax.annotation.processing.Processor. Si el complemento detecta un procesador de anotaciones que está en el classpath de compilación, se producirá un error.

Las configuraciones anteriores se aplican al conjunto de orígenes principal de tu proyecto, que se aplica a todas las variantes de compilación. Si, en cambio, deseas declarar una dependencia solo para un conjunto de orígenes de una variante de compilación específica o un conjunto de orígenes de prueba, debes capitalizar el nombre de la configuración de dependencias y agregarle un prefijo con el nombre de la variante de compilación o el conjunto de orígenes de prueba.

Por ejemplo, para agregar una dependencia implementation a tu tipo de producto "free"(usando una dependencia binaria remota) el aspecto es el siguiente:

dependencies {
    freeImplementation 'com.google.firebase:firebase-ads:9.8.0'
}

Sin embargo, si deseas agregar una dependencia para una variante que combina un tipo de producto y un tipo de compilación, debes inicializar el nombre de la configuración en el bloque configurations. En el siguiente ejemplo, se agrega una dependencia runtimeOnly a tu variante de compilación "freeDebug" (usando una dependencia binaria local):

configurations {
    // Initializes a placeholder for the freeDebugRuntimeOnly dependency
    // configuration.
    freeDebugRuntimeOnly {}
}

dependencies {
    freeDebugRuntimeOnly fileTree(dir: 'libs', include: ['*.jar'])
}

En caso de agregar dependencias de implementation para tus pruebas locales e instrumentadas , el aspecto es el siguiente:

dependencies {
    // Adds a remote binary dependency only for local tests.
    testImplementation 'junit:junit:4.12'

    // Adds a remote binary dependency only for the instrumented test APK.
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

Sin embargo, algunas configuraciones no tienen sentido en esta situación. Por ejemplo, debido a que otros módulos no pueden depender de androidTest, verás la siguiente advertencia si utilizas la configuración de androidTestApi:

WARNING: Configuration 'androidTestApi' is obsolete and has been replaced with
'androidTestImplementation'.

Cómo agregar procesadores de anotaciones

Si agregas procesadores de anotaciones a tu classpath de compilación, verás un mensaje de error similar al siguiente:

Error: Annotation processors must be explicitly declared now.

Para resolver este error, agrega procesadores de anotaciones a tu proyecto configurando tu dependencia al usar annotationProcessor tal como se muestra a continuación:

dependencies {
    // Adds libraries defining annotations to only the compile classpath.
    compileOnly 'com.google.dagger:dagger:version-number'
    // Adds the annotation processor dependency to the annotation processor classpath.
    annotationProcessor 'com.google.dagger:dagger-compiler:version-number'
}

Nota: Android Gradle Plugin 3.0.0 y las versiones posteriores admiten el complemeto android-apt.

Cómo transmitir argumentos a procesadores de anotaciones

Si necesitas transmitir argumentos a un procesador de anotaciones, puedes hacerlo usando el AnnotationProcessorOptions bloqueo en la configuración de compilación de su módulo. Por ejemplo, si quieres transmitir tipos de datos primitivos como pares clave-valor, puede utilizar la propiedad argument, como se muestra a continuación:

android {
    ...
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                argument "key1", "value1"
                argument "key2", "value2"
            }
        }
    }
}

Sin embargo, cuando se utiliza el complemento de Android Gradle 3.2.0 o versiones posteriores, debes transmitir los argumentos del procesador que representen archivos o directorios utilizando la interfaz CommandLineArgumentProvider de Gradle.

El uso de CommandLineArgumentProvider te permite a ti o al autor del procesador de anotaciones mejorar la corrección y el rendimiento de compilaciones limpias en caché mediante la aplicación de anotaciones de tipo de propiedad incrementales en cada argumento.

Por ejemplo, la clase que aparece abajo implementa CommandLineArgumentProvider y anota cada argumento para el procesador. El ejemplo también utiliza la sintaxis de lenguaje de Groovy y se incluye directamente en el archivo build.gradle del módulo.

class MyArgsProvider implements CommandLineArgumentProvider {

    // Annotates each directory as either an input or output for the
    // annotation processor.
    @InputFiles
    // Using this annotation helps Gradle determine which part of the file path
    // should be considered during up-to-date checks.
    @PathSensitive(PathSensitivity.RELATIVE)
    FileCollection inputDir

    @OutputDirectory
    File outputDir

    // The class constructor sets the paths for the input and output directories.
    MyArgsProvider(FileCollection input, File output) {
        inputDir = input
        outputDir = output
    }

    // Specifies each directory as a command line argument for the processor.
    // The Android plugin uses this method to pass the arguments to the
    // annotation processor.
    @Override
    Iterable<String> asArguments() {
        // Use the form '-Akey[=value]' to pass your options to the Java compiler.
        ["-AinputDir=${inputDir.singleFile.absolutePath}",
         "-AoutputDir=${outputDir.absolutePath}"]
    }
}

android {...}

Después de crear una clase que implemente CommandLineArgumentProvider, debes inicializarla y transmitirla al complemento de Android usando la propiedad annotationProcessorOptions.compilerArgumentProvider, tal como se muestra a continuación.

// This is in your module's build.gradle file.
android {
    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                // Creates a new MyArgsProvider object, specifies the input and
                // output paths for the constructor, and passes the object
                // to the Android plugin.
                compilerArgumentProvider new MyArgsProvider(files("input/path"),
                                         new File("output/path"))
            }
        }
    }
}

Para obtener más información sobre cómo implementar CommandLineArgumentProvider mejora el rendimiento de compilación, consulta Cómo almacenar el caché proyectos de Java.

Cómo inhabilitar la comprobación de errores del procesador de anotaciones

Si tienes dependencias en el classpath de compilación que incluyen procesadores de anotaciones que no necesitas, puedes inhabilitar la comprobación de errores agregando lo siguiente a tu archivo build.gradle. Recuerda que los procesadores de anotaciones que agregues al classpath de compilación todavía no se agregan al classpath processor.

android {
    ...
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                includeCompileClasspath false
            }
        }
    }
}

Si tienes problemas después de migrar los procesadores de anotaciones de tu proyecto al processor classpath, puedes habilitar los procesadores de anotaciones en el classpath de compilación estableciendo includeCompileClasspath como true. Sin embargo, no se recomienda configurar esta propiedad como true, y la opción para hacerlo se quitará en una futura actualización del complemento de Android.

Cómo excluir dependecias transitivas

A medida que una app crece en alcance, puede contener un número de dependencias incluidas algunas directas y transitivas (bibliotecas de las que dependen las bibliotecas importadas de tu app). Para excluir las dependencias transitivas que ya no necesitas, usa la palabra clave exclude, tal como se indica a continuación:

dependencies {
    implementation('some-library') {
        exclude group: 'com.example.imgtools', module: 'native'
    }
}

Cómo excluir dependecias transitivas de la configuración de pruebas

Si necesitas excluir ciertas dependencias transitivas de tus pruebas, es posible que el ejemplo de código que se muestra arriba no funcione según lo esperado. Esto se debe a que una configuración de prueba (p. ej., androidTestImplementation) extiende la configuración implementation del módulo. Es decir, siempre contiene dependencias implementation cuando Gradle resuelve la configuración.

Por lo tanto, para excluir dependencias transitivas de tus pruebas, debes hacerlo en el tiempo de ejecución, como se muestra a continuación:

android.testVariants.all { variant ->
    variant.getCompileConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp'
    variant.getRuntimeConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp'
}

Nota: Puedes seguir usando la palabra clave exclude en los bloques de dependencias, tal como se muestra en el ejemplo de código original de la sección Cómo excluir dependencias a fin de omitir dependencias transitivas que son específicas de la configuración de pruebas y que no están incluidas en otras configuraciones.

Cómo usar la administración de dependencias con detección de variantes

En la versión 3.0.0 del complemento de Android se incluye un nuevo mecanismo de dependencias que establece coincidencias entre variantes de forma automática cuando se consume una biblioteca. Esto significa que la variante debug de una app consume automáticamente la variante debug de una biblioteca, y así sucesivamente. También funciona cuando se usan tipos; la variante freeDebug de una app consumirá la variante freeDebug de una biblioteca.

Para que el complemento coincida precisamente con las variantes, debes proporcionar coincidencias de resguardo para instancias en las que una coincidencia directa no sea posible. Considera el caso de que tu app configura un tipo de compilación llamado "staging", pero una de las dependencias de su biblioteca no lo hace. Cuando el complemento intente compilar la versión "staging" de tu app, no podrá determinar la versión de la biblioteca que deberá usar, y verás un mensaje de error similar al siguiente:

Error:Failed to resolve: Could not resolve project :mylibrary.
Required by:
    project :app

Cómo resolver error de compilaciones relacionados con las coincidencias de variantes

El complemento incluye elementos DSL para ayudarte a controlar la manera en la que Gradle debe resolver situaciones en las cuales no es posible establecer una coincidencia directa de variantes entre una app y una dependencia. Consulta la siguiente tabla para determinar la propiedad de DSL que debes usar a fin de resolver determinados errores de compilación relacionados con el establecimiento de coincidencias de dependencias con reconocimiento de variantes.

Causa del error de compilaciónResolución

Tu app incluye un tipo de compilación que no figura en una dependencia de la biblioteca.

Por ejemplo, tu app incluye el tipo de compilación “staging”, pero una dependencia incluye solo los tipos de compilación “debug” y “release”.

Ten en cuenta que no habrá problema si una dependencia de la biblioteca incluye un tipo de compilación que tu app no tiene. Eso ocurre porque el complemento simplemente nunca solicita el tipo de compilación a la dependencia.

Usa matchingFallbacks para especificar coincidencias alternativas para un tipo de compilación específico, como se muestra a continuación:

// In the app's build.gradle file.
android {
    buildTypes {
        debug {}
        release {}
        staging {
            // Specifies a sorted list of fallback build types that the
            // plugin should try to use when a dependency does not include a
            // "staging" build type. You may specify as many fallbacks as you
            // like, and the plugin selects the first build type that's
            // available in the dependency.
            matchingFallbacks = ['debug', 'qa', 'release']
        }
    }
}

Para una dimensión de tipos determinada que existe tanto en la app como en la dependencia de la biblioteca, tu app incluye tipos que no figuran en la biblioteca.

Por ejemplo, tanto tu app como las dependencias de su biblioteca incluyen una dimensión de tipos “tier”. No obstante, la dimensión “tier” de la app incluye los tipos “free” y “paid”, pero una dependencia solo incluye los tipos “demo” y “paid” para la misma dimensión.

Ten en cuenta que, en el caso de una dimensión de tipos determinada que existe en la app y en las dependencias de su biblioteca, no habrá problema cuando una biblioteca incluya un tipo de producto que no se encuentre en tu app. Eso ocurre porque el complemento simplemente nunca solicita ese tipo a la dependencia.

Usa matchingFallbacks a fin de especificar coincidencias alternativas para el tipo de producto “free” de la app, como se muestra a continuación:

// In the app's build.gradle file.
android {
    defaultConfig{
    // Do not configure matchingFallbacks in the defaultConfig block.
    // Instead, you must specify fallbacks for a given product flavor in the
    // productFlavors block, as shown below.
  }
    flavorDimensions 'tier'
    productFlavors {
        paid {
            dimension 'tier'
            // Because the dependency already includes a "paid" flavor in its
            // "tier" dimension, you don't need to provide a list of fallbacks
            // for the "paid" flavor.
        }
        free {
            dimension 'tier'
            // Specifies a sorted list of fallback flavors that the plugin
            // should try to use when a dependency's matching dimension does
            // not include a "free" flavor. You may specify as many
            // fallbacks as you like, and the plugin selects the first flavor
            // that's available in the dependency's "tier" dimension.
            matchingFallbacks = ['demo', 'trial']
        }
    }
}

Una dependencia de biblioteca incluye una dimensión de tipos que no figura en tu app.

Por ejemplo, una dependencia de biblioteca incluye tipos para una dimensión "minApi" pero tu app incluye tipos únicamente para la dimensión “tier”. Por lo tanto, cuando desees compilar la versión “freeDebug” de tu app, el complemento no sabrá si debe usar la versión “minApi23Debug” o “minApi18Debug” de la dependencia.

Ten en cuenta que no habrá problema cuando tu app incluya una dimensión de tipos que no figure en una dependencia de biblioteca. Esto ocurre porque el complemento establece coincidencias únicamente entre tipos de las dimensiones que existen en la dependencia. Por ejemplo, si una dependencia no incluyera una dimensión para ABI, la versión “freeX86Debug” de tu app simplemente usaría la versión “freeDebug” de la dependencia.

Usa missingDimensionStrategy en el bloque defaultConfig para especificar el tipo predeterminado que el complemento debe seleccionar de cada dimensión faltante, como se muestra en el siguiente ejemplo. También puedes anular tus selecciones en el bloque productFlavors, de modo que cada tipo pueda especificar una estrategia de establecimiento de coincidencias diferente para una dimensión faltante.

// In the app's build.gradle file.
android {
    defaultConfig{
    // Specifies a sorted list of flavors that the plugin should try to use from
    // a given dimension. The following tells the plugin that, when encountering
    // a dependency that includes a "minApi" dimension, it should select the
    // "minApi18" flavor. You can include additional flavor names to provide a
    // sorted list of fallbacks for the dimension.
    missingDimensionStrategy 'minApi', 'minApi18', 'minApi23'
    // You should specify a missingDimensionStrategy property for each
    // dimension that exists in a local dependency but not in your app.
    missingDimensionStrategy 'abi', 'x86', 'arm64'
    }
    flavorDimensions 'tier'
    productFlavors {
        free {
            dimension 'tier'
            // You can override the default selection at the product flavor
            // level by configuring another missingDimensionStrategy property
            // for the "minApi" dimension.
            missingDimensionStrategy 'minApi', 'minApi23', 'minApi18'
        }
        paid {}
    }
}

Cómo configurar dependencias para apps de Wear OS

Configurar dependencias para un módulo de Wear OS es similar a hacerlo para cualquier otro módulo. Es decir, utilizan las mismas configuraciones de dependencias, como implementation y compileOnly.

Los módulos de Wear también admiten la administración de dependencias basadas en variantes. Como resultado, si tu módulo de app base depende de un módulo de Wear, cada variante del módulo base consumirá la variante correspondiente del módulo de Wear. Si estás compilando una app simple con una dependencia en un solo módulo de Wear, donde el módulo configura las mismas variantes que tu módulo base, debes especificar la configuración de wearApp en el archivo build.gradle de tu módulo base, tal que se muestra a continuación:

dependencies {
    // If the main and Wear app modules have the same variants,
    // variant-aware dependency management automatically matches
    // variants of the main app module with that of the wear module.
    wearApp project(':wearable')
}

Si tienes varios módulos de Wear y quieres especificar un tipo de módulo diferente por tipo de app, puedes hacerlo utilizando la configuración de flavorWearApp , tal como se muestra a continuación (sin embargo, no puedes incluir otras dependencias que usen la configuración de wearApp):

dependencies {
    paidWearApp project(':wear1')
    demoWearApp project(':wear1')
    freeWearApp project(':wear2')
}

Repositorios remotos

Cuando tu dependencia no es otra cosa que una biblioteca o un árbol de archivos local, Gradle busca los archivos en cualquiera de los repositorios en línea que se especifican en el bloque repositories de tu archivo build.gradle. El orden en el que especificas cada repositorio determina el orden en el que Gradle busca por dependencia del proyecto. Por ejemplo, si una dependencia está disponible en los repositorios A y B, y especificas la lista A primero, Gradle descargará la dependencia de ese repositorio.

De forma predeterminada, los nuevos proyectos de Android Studio especifican el repositorio Maven de Google y JCenter como ubicaciones de repositorios en el archivo build.gradle de nivel superior, tal como se muestra a continuación:

allprojects {
    repositories {
        google()
        jcenter()
    }
}

Si deseas algo del repositorio central de Maven, agrega mavenCentral(). Para un repositorio local, usa mavenLocal():

allprojects {
    repositories {
        google()
        jcenter()
        mavenCentral()
        mavenLocal()
    }
}

También puedes declarar repositorios Maven o Ivy específicos de la siguiente manera:

allprojects {
    repositories {
        maven {
            url "https://repo.example.com/maven2"
        }
        maven {
            url "file://local/repo/"
        }
        ivy {
            url "https://repo.example.com/ivy"
        }
    }
}

Para obtener más información, consulta la guía de repositorios de Gradle.

El repositorio de Maven de Google

Las versiones más recientes de las siguientes bibliotecas de Android se encuentran disponibles en el repositorio de Maven de Google.

Puedes ver todas las alteraciones en el índice del repositorio de Maven de Google (consulta, a continuación, la sección sobre acceso programático).

Para agregar una de etas bibliotecas a tu compilación, incluye el repositorio de Maven de Google en tu archivo build.gradle de nivel superior:

allprojects {
    repositories {
        google()

        // If you're using a version of Gradle lower than 4.1, you must instead use:
        // maven {
        //     url 'https://maven.google.com'
        // }
        // An alternative URL is 'https://dl.google.com/dl/android/maven2/'
    }
}

Luego, agrega la biblioteca deseada al bloque dependencies de tu módulo. Por ejemplo, la biblioteca appcompat tiene el siguiente aspecto:

dependencies {
    implementation 'com.android.support:appcompat-v7:28.0.0'
}

Sin embargo, si intentas usar una versión previa de las bibliotecas antes mencionadas y falla tu dependencia, no se encuentra disponible en el repositorio de Maven y, en su lugar, debes obtener la biblioteca del repositorio sin conexión.

Acceso mediante programación

Para acceder mediante programación a las alteraciones de Maven de Google, puedes obtener una lista XML de grupos de alteraciones desde maven.google.com/master-index.xml. Para cualquier grupo, puedes ver los nombres y las versiones de bibliotecas en:

maven.google.com/group_path/group-index.xml

Por ejemplo, las bibliotecas en el grupo android.arch.lifecycle se indican en maven.google.com/android/arch/lifecycle/group-index.xml.

También puedes descargar los archivos POM y JAR en:

maven.google.com/group_path/library/version /library-version.ext

Por ejemplo: maven.google.com/android/arch/lifecycle/compiler/1.0.0/compiler-1. 0.0.pom.

Repositorio sin conexión de SDK Manager

Para bibliotecas que no se encuentran disponibles en el repositorio de Maven de Google (por lo general versiones de bibliotecas anteriores), debes descargar el paquete Google Repository sin conexión desde el SDK Manager.

Luego, puedes agregar estas bibliotecas a tu bloque dependencies como lo haces habitualmente.

Las bibliotecas sin conexión se guardan en android_sdk/extras/.

Orden de dependencia

El orden en el que se ubican tus dependencias indica la prioridad para cada una: la primera biblioteca tiene mayor prioridad que la segunda, la segunda tiene mayor prioridad que la tercera y así sucesivamente. Este orden es importante en caso de que se combinen los recursos o los elementos de manifiesto en tu app desde las bibliotecas.

Por ejemplo, si en tu proyecto se declara lo siguiente:

  • La dependencia en LIB_A y LIB_B (en ese orden).
  • LIB_A depende de LIB_C y LIB_D (en ese orden).
  • LIB_B también depende de LIB_C.

Luego, el orden de la dependencia única será el siguiente:

  1. LIB_A
  2. LIB_D
  3. LIB_B
  4. LIB_C

Esto garantiza que LIB_A y LIB_B puedan anular LIB_C, y que LIB_D tenga mayor prioridad que LIB_B porque LIB_A (que depende de él) tiene más prioridad que LIB_B.

Para obtener más información sobre la manera en que se combinan los manifiestos de diferentes fuentes o dependencias del proyecto, consulta Cómo combinar diferentes archivos de manifiesto.

Cómo ver el árbol de dependencias

Algunas dependencias directas pueden tener dependencias propias. Estas se denominan dependencias transitivas. Gradle reúne automáticamente cada dependencia transitiva y la agrega, evitando así que las declares manualmente. Para visualizar las dependencias transitivas y directas de tu proyecto, el complemento de Android para Gradle proporciona una tarea de Gradle que puede generar un árbol de dependencias para cada variante de compilación y conjunto de orígenes de prueba.

Para ejecutar la tarea, proceda de la siguiente manera:

  1. Selecciona View > Tool Windows > Gradle (o haz clic en Gradle en la barra de la ventana de herramientas).
  2. Expande AppName > Tasks > android y haz doble clic en androidDependencies. Después de que Gradle ejecute la tarea, la ventana Run se abrirá para mostrar el resultado.

En el siguiente ejemplo de resultado se muestra el árbol de dependencias para la variante de compilación de depuración y se incluye la dependencia del módulo local y la dependencia remota del ejemplo anterior.

Executing tasks: [androidDependencies]
:app:androidDependencies
debug
/**
 * Both the library module dependency and remote binary dependency are listed
 * with their transitive dependencies.
 */
+--- MyApp:mylibrary:unspecified
|    \--- com.android.support:appcompat-v7:28.0.0
|         +--- com.android.support:animated-vector-drawable:28.0.0
|         |    \--- com.android.support:support-vector-drawable:28.0.0
|         |         \--- com.android.support:support-v4:28.0.0
|         |              \--- LOCAL: internal_impl-28.0.0.jar
|         +--- com.android.support:support-v4:28.0.0
|         |    \--- LOCAL: internal_impl-28.0.0.jar
|         \--- com.android.support:support-vector-drawable:28.0.0
|              \--- com.android.support:support-v4:28.0.0
|                   \--- LOCAL: internal_impl-28.0.0.jar
\--- com.android.support:appcompat-v7:28.0.0
     +--- com.android.support:animated-vector-drawable:28.0.0
     |    \--- com.android.support:support-vector-drawable:28.0.0
     |         \--- com.android.support:support-v4:28.0.0
     |              \--- LOCAL: internal_impl-28.0.0.jar
     +--- com.android.support:support-v4:28.0.0
     |    \--- LOCAL: internal_impl-28.0.0.jar
     \--- com.android.support:support-vector-drawable:28.0.0
          \--- com.android.support:support-v4:28.0.0
               \--- LOCAL: internal_impl-28.0.0.jar
...

Para obtener más información sobre cómo administrar dependencias en Gradle, consulta Aspectos básicos de la administración de dependencias en la Guía del usuario de Gradle.

Cómo solucionar errores de resolución de dependencias

Cuando agregas varias dependencias a tu proyecto de app, esas dependencias directas y transitivas pueden entrar en conflicto. Android Gradle Plugin intenta resolver estos conflictos, aunque algunos podrían provocar errores de tiempo de ejecución o compilación.

Para determinar las dependencias que conducen a errores, inspecciona el árbol de dependencias de tu app y busca dependencias que aparezcan más de una vez o que tengan versiones en conflicto.

Si no puedes identificar fácilmente la dependencia duplicada, intenta usar la IU de Android Studio para buscar dependencias que incluyan la clase duplicada, de la siguiente manera:

  1. Selecciona Navigate > Class en la barra de menú.
  2. En el diálogo emergente de búsqueda, asegúrate de marcar la casilla junto a Include non-project items.
  3. Escribe el nombre de la clase que aparece en el error de compilación.
  4. Inspecciona los resultados de las dependencias que incluyen la clase.

Las siguientes secciones describen los diferentes tipos de errores de resolución de dependencias que puedes encontrar y cómo solucionarlos.

Cómo solucionar errores de clases duplicadas

Si una clase aparece más de una vez en el classpath de tiempo de ejecución, verás un error similar al siguiente:

Program type already present com.example.MyClass

Generalmente, este error sucede debido a una de las siguientes circunstancias:

  • Una dependencia binaria incluye una biblioteca que tu app también incluye como dependencia directa. Por ejemplo, tu app declara una dependencia directa en las bibliotecas A y B, pero la A ya incluye la B en su archivo binario.
    • Para resolver este problema, quita la biblioteca B como una dependencia directa.
  • Tu app tiene una dependencia binaria local y una dependencia binaria remota en la misma biblioteca.
    • Para resolver este problema, quita una de las dependencias binarias.

Cómo solucionar conflictos entre classpaths

Cuando Gradle resuelve la compilación classpath, primero resuelve el classpathclase runtime y usa el resultado para determinar qué versiones de las dependencias deben agregarse al classpath de compilación. En otras palabras, el classpath de tiempo de ejecución determina los números de versión necesarios para dependencias idénticas en classpaths downstream.

El classpath de tiempo de ejecución de tu app también determina los números de versión que Gradle require a fin de hacer coincidir las dependencias en el classpath de tiempo de ejecución para el APK de prueba de tu app. La jerarquía de los classpaths se describe en la figura 1.

Figura 1. Los números de versión de dependencias que aparecen en varios classpaths deben coincidir según esta jerarquía.

Si aparecen versiones conflictivas de la misma dependencia en varios classpaths, podrías ver un error similar al siguiente:

Conflict with dependency 'com.example.library:some-lib:2.0' in project 'my-library'.
Resolved versions for runtime classpath (1.0) and compile classpath (2.0) differ.

Es posible que veas este conflicto si, por ejemplo, tu app incluye una versión de la dependencia usando la configuración de dependencias implementationy un módulo de biblioteca incluye una versión diferente de la dependencia usando la configuración runtimeOnly. Para solucionar este problema, haz lo siguiente:

  • Incluye la versión deseada de la dependencia como una dependencia de api del módulo de tu biblioteca. Es decir, solo el módulo de tu biblioteca declara la dependencia, pero el módulo de la app también tendrá acceso a su API, de forma transitiva.
  • Alternativamente, puedes declarar la dependencia en ambos módulos, pero asegúrate de que cada uno utilice la misma versión de dependencia. Consider configurar propiedades para todo el proyecto a fin de garantizar que las versiones de cada dependencia permanezcan consistentes a lo largo de todo el proyecto.

Cómo aplicar la lógica de compilación personalizada

Esta sección describe los temas avanzados que son útiles cuando quieres entender el complemento de Android Gradle o escribir el tuyo propio.

Cómo publicar dependencias de variantes a la lógica personalizada

Una biblioteca puede tener funcionalidades que otros proyectos o subproyectos podrían querer utilizar. Publicar una biblioteca es el proceso por el cual la biblioteca es se pone a disposición de sus consumidores. Las bibliotecas pueden controlar a qué dependencias tiene acceso sus consumidores durante el tiempo de compilación y ejecución.

Existen dos configuraciones separadas que contienen las dependencias transitivas de cada classpath que deben usar los clientes para consumir la biblioteca tal como se describe a continuación:

  • variant_nameApiElements: Esta configuración contiene las dependencias transitivas que están disponibles para los consumidores durante el tiempo de compilación.
  • variant_nameRuntimeElements: Esta configuración contiene las dependencias transitivas que están disponibles para los consumidores durante el tiempo de ejecución.

Para obtener más información sobre las relaciones entre las diferentes configuraciones, consulta Las configuraciones del complemento de la biblioteca Java.

Cómo migrar estrategias de resolución de dependencias personalizadas

Un proyecto puede incluir una dependencia de dos versiones diferentes de la misma biblioteca, lo que podría conducir a conflictos. Por ejemplo, si tu proyecto depende de la versión 1 del módulo A y de la versión 2 del módulo B, y el módulo A depende transitivamente de la versión 3 del módulo B, surgirá un conflicto de versiones de dependencia.

Para resolver este conflicto, Android Gradle Plugin utiliza la siguiente estrategia de resolución de dependencias: cuando el complemento detecta que diferentes versiones del mismo módulo están en el gráfico de dependencias, de forma predeterminada, elige el que tenga el número de versión más alto.

Sin embargo, es posible que esta estrategia no siempre funcione como lo deseas. Para personalizar la estrategia de resolución de dependencias, utiliza las siguientes configuraciones a fin de resolver dependencias específicas de una variante que sean necesarias para tu tarea:

  • variant_nameCompileClasspath: Esta configuration contiene la estrategia de resolución para un classpath de compilación de variantes específico.
  • variant_nameRuntimeClasspath: Esta configuration contiene la estrategia de resolución para un classpath de tiempo de ejecución de variantes específico.

Android Gradle Plugin incluye getters que puedes usar para acceder a los objetos de configuración de cada variante. Por lo tanto, puedes utilizar la API de variante para la resolución de dependencias tal como se muestra en el siguiente ejemplo:

android {
    applicationVariants.all { variant ->
        // Return compile configuration objects of a variant.
        variant.getCompileConfiguration().resolutionStrategy {
        // Use Gradle's ResolutionStrategy API
        // to customize how this variant resolves dependencies.
            ...
        }
        // Return runtime configuration objects of a variant.
        variant.getRuntimeConfiguration().resolutionStrategy {
            ...
        }
        // Return annotation processor configuration of a variant.
        variant.getAnnotationProcessorConfiguration().resolutionStrategy {
            ...
        }
    }
}