The Android Developer Challenge is back! Submit your idea before December 2.

Cómo agregar dependencias de creación

El sistema de compilación de Gradle en Android Studio facilita la inclusión de objetos binarios externos o de otros módulos de biblioteca a tu compilación como dependencias. Las dependencias pueden ubicarse en tu máquina o en un repositorio remoto, y cualquier dependencia transitiva que estas declaren se incluirá automáticamente. En esta página, se describe cómo usar las dependencias con tu proyecto de Android, incluidos los detalles sobre los comportamientos y las opciones de configuración que son específicos del complemento de Android para Gradle. A fin de obtener una guía conceptual más detallada sobre las dependencias de Gradle, también deberías consultar la Guía de Gradle para la administración de dependencias. No obstante, recuerda que tu proyecto de Android solo debe usar las opciones de configuración de dependencias definidas en esta página.

Tipos de dependencias

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

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

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 del módulo de biblioteca local
implementation project(':mylibrary')

De esta manera, se declara un módulo de biblioteca de Android llamado "mylibrary" (este nombre debe coincidir con el nombre de biblioteca definido con include: en tu archivo settings.gradle). Cuando compilas tu app, el sistema de compilación crea el módulo de biblioteca y empaqueta el contenido compilado resultante en el APK.

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

Gradle declara dependencias en archivos JAR dentro del directorio module_name/libs/ de tu proyecto (porque Gradle lee las rutas de acceso relacionadas con el archivo build.gradle).

Como 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'

En realidad, esta es una versión abreviada de lo siguiente:

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

De esta manera, se declara una dependencia en la versión 12.3 de la biblioteca "app-magic", dentro del grupo de espacios de nombres "com.example.android".

Nota: Las dependencias remotas como esta requieren que declares los repositorios remotos adecuados en los que Gradle debería buscar la biblioteca. Si la biblioteca no existe localmente, Gradle la obtendrá del sitio remoto cuando la compilación la requiera (por ejemplo, cuando haces clic en Sync Project with Gradle Files  o ejecutas una compilación).

Opciones de configuración de dependencias

Dentro del bloque dependencies, puedes declarar una dependencia de biblioteca usando una de las diferentes opciones de configuración de dependencias (como implementation, que se muestra más arriba). La configuración de cada dependencia le proporciona a Gradle diferentes instrucciones sobre cómo usarla. En la siguiente tabla, se describe cada una de las configuraciones que puedes usar para una dependencia en tu proyecto de Android. Además, se comparan estas opciones de configuración con las que dejaron de estar disponibles a partir de la versión 3.0.0 del complemento de Android para Gradle.

Configuración nueva Configuración no disponible Comportamiento
implementation compile Gradle agrega la dependencia a la ruta de clase de la compilación y la empaqueta en el resultado de la compilación. Sin embargo, cuando tu módulo configura una dependencia implementation, se le informa a Gradle que no quieres que el módulo filtre la dependencia a otros módulos en el momento de la compilación. Es decir, la dependencia estará disponible para otros módulos únicamente durante el tiempo de ejecución.

El uso de esta configuración de dependencia, en lugar de api o compile (no disponible), puede reducir significativamente el tiempo de compilación, ya que disminuye la cantidad de módulos que el sistema debe volver a compilar. Por ejemplo, si una dependencia implementation cambia su API, Gradle solo volverá a compilar esa dependencia y los módulos que dependen de esta directamente. La mayoría de los módulos de prueba y de apps deben usar esta configuración.

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

Esta configuración tiene el mismo comportamiento que compile (que dejó de estar disponible), pero deberías usarla con cuidado y únicamente con las dependencias que necesitas exportar de forma transitiva a otros consumidores ascendentes, ya que si una dependencia api cambia su API externa, Gradle volverá a compilar todos los módulos que tengan acceso a esa dependencia en el tiempo de compilación. Por lo tanto, tener una gran cantidad de dependencias api puede aumentar significativamente el tiempo de compilación. A menos que quieras exponer una API de dependencia en un módulo separado, los módulos de biblioteca deberían usar dependencias implementation.

compileOnly provided Gradle solo agrega la dependencia a la ruta de clase de la compilación (pero no al resultado de la compilación), lo que resulta útil cuando creas un módulo de Android y necesitas la dependencia durante la compilación. Sin embargo, tenerla presente durante el tiempo de ejecución es opcional.

Si usas esta configuración, entonces tu módulo de biblioteca debe incluir una condición de tiempo de ejecución para comprobar si la dependencia está disponible y, luego, cambiar de manera fluida su comportamiento a fin de que pueda funcionar en caso de que esta no se proporcione. De este modo, se reduce el tamaño del APK final, ya que no se agregan dependencias transitivas que no sean fundamentales. Esta configuración tiene el mismo comportamiento que provided (que dejó de estar disponible).

runtimeOnly apk Gradle solo agrega la dependencia al resultado de la compilación para usar durante el tiempo de ejecución. Es decir, esta no se agrega a la ruta de clase de compilación. Esta configuración tiene el mismo comportamiento que apk (que dejó de estar disponible).
annotationProcessor compile Si quieres agregar una dependencia en una biblioteca que es un procesador de anotaciones, debes hacerlo en la ruta de clase del procesador de anotaciones mediante la configuración annotationProcessor, ya que de esta manera se mejora el rendimiento de la compilación porque se separa la ruta de clase de la compilación de la ruta de clase del procesador de anotaciones. Si Gradle encuentra procesadores de anotaciones en la ruta de clase de la compilación, desactivará la elusión de compilación, lo que afectará negativamente el tiempo de compilación (a partir de la versión 5.0 de Gradle, se ignoran los procesadores de anotaciones que se encuentran en la ruta de clase de la compilación).

El complemento de Android para Gradle asume que una dependencia es un procesador de anotaciones si su archivo JAR contiene el siguiente archivo:
META-INF/services/javax.annotation.processing.Processor. Si el complemento detecta un procesador de anotaciones que está en la ruta de clase de la compilación, se producirá un error de compilación.
lintChecks Usa esta configuración para incluir comprobaciones de Lint que quieras que Gradle ejecute al compilar tu proyecto.

Nota: Si usas la versión 3.4.0 del complemento de Android para Gradle o una versión posterior, esta configuración de dependencia ya no empaqueta las comprobaciones de Lint en tus proyectos de la biblioteca de Android. Para incluir dependencias de comprobaciones de Lint en tus bibliotecas AAR, usa la configuración lintPublish que se describe a continuación.

lintPublish Usa esta configuración en los proyectos de la biblioteca de Android a fin de incluir comprobaciones de Lint que quieras que Gradle compile en un archivo lint.jar y empaquete en tu AAR. De esta manera, los proyectos que consumen tu AAR también aplicarán esas comprobaciones de Lint. Si anteriormente usabas la configuración de dependencia lintChecks para incluir comprobaciones de Lint en el AAR publicado, deberás migrar esas dependencias a fin de usar la configuración lintPublish en su lugar.

    dependencies {
      // Executes lint checks from the ':checks' project
      // at build time.
      lintChecks project(':checks')
      // Compiles lint checks from the ':checks-to-publish'
      // into a lint.jar file and publishes it to your
      // Android library.
      lintPublish project(':checks-to-publish')
    }

Las configuraciones que se muestran más arriba aplican dependencias a todas las variantes de compilación. Sin embargo, si quieres declarar una dependencia para un solo conjunto de fuentes de variantes de compilación específico o un conjunto de fuentes de prueba, deberás escribir con mayúscula el nombre de la configuración y agregarle el nombre del conjunto de fuentes de prueba o de variantes de compilación como prefijo.

Por ejemplo, si quieres agregar una dependencia implementation a tu tipo de producto "gratuito" únicamente (por medio de una dependencia binaria remota), tendrá el siguiente aspecto:

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 con un tipo de compilación, entonces deberás 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" (mediante una dependencia binaria local):

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

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

Las dependencias implementation que agregues en las pruebas instrumentadas y las locales tendrán el siguiente aspecto:

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 opciones de configuración no son útiles en esta situación. Por ejemplo, como otros módulos no pueden depender de androidTest, verás la siguiente advertencia si usas la configuración androidTestApi:

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

Cómo agregar procesadores de anotaciones

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

    Error: Annotation processors must be explicitly declared now.
    

Para corregir este error, agrega procesadores de anotaciones a tu proyecto mediante la configuración de tu dependencia con annotationProcessor, 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: El complemento de Android para Gradle 3.0.0 y sus versiones posteriores ya no admiten el complemento android-apt.

Cómo pasar argumentos a procesadores de anotaciones

Si necesitas pasar argumentos a un procesador de anotaciones, puedes hacerlo mediante el bloque AnnotationProcessorOptions en la configuración de compilación de tu módulo. Por ejemplo, si quieres pasar tipos de datos primitivos como pares clave-valor, puedes usar la propiedad argument, como se muestra a continuación:

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

Sin embargo, cuando uses el complemento de Android para Gradle 3.2.0 o versiones posteriores, necesitarás pasar argumentos de procesadores que representen archivos o directorios por medio de la interfaz CommandLineArgumentProvider de Gradle.

El uso de CommandLineArgumentProvider te permite a ti o al autor del procesador de anotaciones mejorar la precisión y el rendimiento de las compilaciones incrementales y las que borraron su caché aplicando anotaciones del tipo de propiedad de compilación incremental a cada argumento.

Por ejemplo, la clase que se muestra a continuación implementa CommandLineArgumentProvider y anota cada argumento para el procesador. En este ejemplo, también se usa la sintaxis del lenguaje 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 {...}
    

Una vez que crees una clase que implemente CommandLineArgumentProvider, deberás inicializarla y transferirla al complemento de Android por medio de la propiedad annotationProcessorOptions.compilerArgumentProvider, 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 la implementación de CommandLineArgumentProvider ayuda a mejorar el rendimiento de la compilación, lee Cómo almacenar proyectos de Java en caché.

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

Si tienes dependencias en la ruta de clase de la 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. Ten en cuenta que los procesadores de anotaciones que agregues a la ruta de clase de la compilación aún no se agregarán a la ruta de clase del procesador.

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

Si experimentas problemas luego de migrar los procesadores de anotaciones de tu proyecto a la ruta de clase del procesador, puedes habilitar los procesadores de anotaciones en la ruta de clase de la compilación mediante la configuración de includeCompileClasspath en true. Sin embargo, no se recomienda configurar esta propiedad en true y la opción para hacerlo se quitará en una actualización futura del complemento de Android.

Cómo excluir dependencias transitivas

A medida que crece el alcance de una app, esta puede contener varias dependencias, incluidas las dependencias directas y las transitivas (bibliotecas de las que dependen las bibliotecas importadas de tu app). Para excluir dependencias transitivas que ya no necesitas, puedes usar la palabra clave exclude como se indica a continuación:

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

Cómo excluir dependencias transitivas de las configuraciones de pruebas

Si necesitas excluir dependencias transitivas específicas de tus pruebas, es posible que el ejemplo de código que se muestra más arriba no funcione como se espera porque una configuración de prueba (p. ej., androidTestImplementation) extiende la configuración implementation del módulo. Es decir, esta siempre contiene dependencias implementation cuando Gradle determina la configuración.

Entonces, si quieres excluir dependencias transitivas de tus pruebas, deberás 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: De igual manera, puedes usar la palabra clave exclude en el bloque de dependencias como se muestra en el ejemplo de código original de la sección Cómo excluir dependencias a fin de omitir las dependencias transitivas que son específicas de la configuración de pruebas y que no se incluyen en otras opciones de configuración.

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

A partir de la versión 3.0.0 del complemento de Android, se incluyó un nuevo mecanismo de dependencias que coincide automáticamente con las variantes cuando se consume una biblioteca, lo que significa que la variante debug de una app consumirá automáticamente la variable 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 la biblioteca).

A fin de que el complemento coincida de manera precisa con las variantes, deberás proporcionar coincidencias alternativas para las instancias en las que no son posibles las coincidencias directas. Considera el caso en el que tu app configura un tipo de compilación llamado "staging", pero una de sus dependencias de biblioteca no lo hace. Cuando el complemento intente compilar la versión "staging" de tu app, este no sabrá qué versión de la biblioteca 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 corregir errores de compilación relacionados con la coincidencia de variantes

El complemento incluye elementos SDL para ayudarte a controlar la manera en que Gradle debería resolver las situaciones en las que una coincidencia directa de variantes entre una app y una dependencia no es posible. Consulta la siguiente tabla a fin de determinar qué propiedad DSL deberías usar para corregir determinados errores de compilación relacionados con la coincidencia de dependencias con reconocimiento de variantes.

Causa del error de compilaciónResolución

Tu app incluye un tipo de compilación que una dependencia de biblioteca no contiene.

Por ejemplo, tu app incluye un tipo de compilación "staging" (etapa de pruebas), pero una dependencia solo contiene un tipo de compilación "debug" (depuración) y "release" (lanzamiento).

Ten en cuenta que no se produce este error cuando una dependencia de biblioteca incluye un tipo de compilación que tu app no contiene, ya que el complemento nunca le solicitará ese tipo de compilación a la dependencia.

Usa matchingFallbacks a fin de 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']
            }
        }
    }
    

En el caso de una dimensión de tipo específica que existe tanto en la app como en su dependencia de biblioteca, tu app incluye tipos que la biblioteca no contiene.

Por ejemplo, tanto tu app como sus dependencias de biblioteca incluyen una dimensión de tipo "tier" (nivel). Sin embargo, esta dimensión "tier" (nivel) en la app incluye los tipos "free" (gratuito) y "paid" (pagado), pero la dependencia solo incluye los tipos "demo" (demostración) y "paid" (pagado) para la misma dimensión.

Ten en cuenta que, en el caso de una dimensión de tipo específica que existe en la app y en sus dependencias de biblioteca, no se genera un problema cuando una biblioteca incluye un tipo de producto que la app no contiene, ya que el complemento nunca le solicitará ese tipo a la dependencia.

Usa matchingFallbacks para especificar coincidencias alternativas para el tipo de producto "free" (gratuito) 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 tu app no contiene.

Por ejemplo, una dependencia de biblioteca incluye tipos para una dimensión "minApi", pero tu app solo incluye tipos para la dimensión "tier (nivel). Por lo tanto, cuando quieras compilar la versión "freeDebug" de tu app, el complemento no sabrá si usar la versión "minApi23Debug" o "minApi18Debug" de tu dependencia.

Ten en cuenta que no se genera un problema cuando tu app incluye una dimensión de tipo que una dependencia de biblioteca no contiene, ya que el complemento solo coincide con los tipos de las dimensiones que existen en la dependencia. Por ejemplo, si una dependencia no incluye una dimensión para las ABI, la versión "freeX86Debug" de tu app simplemente usará la versión "freeDebug" de la dependencia.

Usa missingDimensionStrategy en el bloque defaultConfig para especificar el tipo predeterminado que el complemento debería seleccionar de cada una de las dimensiones faltantes, como se muestra en el siguiente ejemplo. También puedes anular las opciones que seleccionaste en el bloque productFlavors de manera que cada tipo especifique una estrategia de coincidencia 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 de apps para Wear OS

La configuración de dependencias para un módulo de Wear OS es similar a la de cualquier otro módulo. Es decir, se usan las mismas opciones de configuración de dependencias, como implementation y compileOnly.

Los módulos de Wear también admiten la administración de dependencias con reconocimiento de variantes. Por lo tanto, si el módulo de tu app base tiene una dependencia en un módulo de Wear, cada variante del módulo base consumirá la variante del módulo de Wear con la que coincida. Si compilas una app simple con una dependencia en un solo módulo de Wear, en donde el módulo configura las mismas variantes que tu módulo base, deberás especificar la configuración wearApp en el archivo build.gradle de tu módulo base, como 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 uno diferente para cada tipo de app, puedes hacerlo mediante la configuración flavorWearApp, de la siguiente manera (no obstante, no podrás incluir otras dependencias que usen la configuración wearApp):

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

Repositorios remotos

Cuando tu dependencia no es una dependencia local ni un árbol de archivos, Gradle busca los archivos en cualquier repositorio en línea que se especifique en el bloque repositories de tu archivo build.gradle. El orden en el que se enumera cada repositorio determina el orden en el que Gradle los busca para cada dependencia del proyecto. Por ejemplo, si una dependencia está disponible tanto desde el repositorio A como del B, y enumeras primero el A, Gradle descargará la dependencia del repositorio A.

De manera predeterminada, los nuevos proyectos de Android Studio especifican el repositorio Maven de Google y JCenter como ubicaciones de repositorios en el archivo build.gradle principal de tu proyecto, como se muestra a continuación:

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

Si deseas usar el repositorio central de Maven, debes agregar mavenCentral(); de lo contrario, agrega mavenLocal() para usar el repositorio local:

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.

Repositorio Maven de Google

Las versiones más recientes de las siguientes bibliotecas de Android están disponibles en el repositorio Maven de Google:

Puedes ver todos los artefactos disponibles en el índice del repositorio Maven de Google (consulta a continuación acceso programático).

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

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 anterior de las bibliotecas que se mencionan más arriba y se produce una falla en tu dependencia, significa que el repositorio Maven no está disponible y, en su lugar, deberás obtener la biblioteca del repositorio sin conexión.

Acceso programático

Para acceder a los artefactos Maven de Google de forma programática, puedes obtener una lista en formato XML de los grupos de artefactos en 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 enumeran en maven.google.com/android/arch/lifecycle/group-index.xml.

También puedes descargar los archivos POM y JAR en el siguiente vínculo:

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

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

Repositorio sin conexión del Administrador de SDK

En el caso de las bibliotecas que no están disponibles en el repositorio Maven de Google (por lo general, las versiones anteriores de bibliotecas), deberás descargar el paquete del repositorio de Google sin conexión del Administrador de SDK.

Luego, podrás agregar estas bibliotecas a tu bloque dependencies como lo haces normalmente.

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

Orden de las dependencias

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

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

  • Hay una dependencia en LIB_A y LIB_B (en ese orden).
  • Además, 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

De esta manera, se garantiza que tanto LIB_A como LIB_B puedan anular a LIB_C; además, LIB_D sigue teniendo mayor prioridad que LIB_B porque LIB_A (que depende de esta) tiene mayor prioridad que LIB_B.

Para obtener más información sobre cómo se fusionan los manifiestos de diferentes fuentes o dependencias de proyectos, consulta Cómo fusionar varios archivos de manifiestos.

Cómo ver las dependencias de un módulo

Algunas dependencias directas pueden tener dependencias propias, que se denominan dependencias transitivas. A fin de que no tengas que declarar manualmente cada dependencia transitiva, Gradle las reúne y agrega automáticamente. El complemento de Android para Gradle proporciona una tarea en la que se muestra una lista de las dependencias que Gradle selecciona para un módulo específico.

Para cada módulo, el informe también agrupa las dependencias que se basan en la variante de compilación, el conjunto de fuentes de prueba y la ruta de clase. A continuación, se muestra un informe de ejemplo sobre la ruta de clase de tiempo de ejecución de su variante de compilación de depuración y la ruta de clase de compilación de su conjunto de fuentes de pruebas instrumentadas del módulo de una app.

debugRuntimeClasspath - Dependencies for runtime/packaging
    +--- :mylibrary (variant: debug)
    +--- com.google.android.material:material:1.0.0@aar
    +--- androidx.appcompat:appcompat:1.0.2@aar
    +--- androidx.constraintlayout:constraintlayout:1.1.3@aar
    +--- androidx.fragment:fragment:1.0.0@aar
    +--- androidx.vectordrawable:vectordrawable-animated:1.0.0@aar
    +--- androidx.recyclerview:recyclerview:1.0.0@aar
    +--- androidx.legacy:legacy-support-core-ui:1.0.0@aar
    ...

    debugAndroidTest
    debugAndroidTestCompileClasspath - Dependencies for compilation
    +--- androidx.test.ext:junit:1.1.0@aar
    +--- androidx.test.espresso:espresso-core:3.1.1@aar
    +--- androidx.test:runner:1.1.1@aar
    +--- junit:junit:4.12@jar
    ...
    

Para ejecutar la tarea, haz lo siguiente:

  1. Selecciona View > Tool Windows > Gradle (o haz clic en Gradle  en la barra de la ventana de herramientas).
  2. Expande NombreDeLaApp > Tasks > android y haz doble clic en androidDependencies. Una vez que Gradle ejecute la tarea, se debería abrir la ventana Run para mostrar el resultado.

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

Cómo corregir errores de selección de dependencias

Cuando agregas varias dependencias al proyecto de tu app, es posible que se genere un conflicto entre las dependencias directas y transitivas. El complemento de Android para Gradle intenta resolver estos conflictos de manera fluida, pero es posible que algunos generen errores de tiempo de ejecución o compilación.

Para investigar qué dependencias generan estos errores, inspecciona el árbol de dependencias de tu app y busca las dependencias que aparezcan más de una vez o tengan versiones conflictivas.

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

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

En las siguientes secciones, se describen diferentes tipos de errores de selección de dependencias que podrías experimentar y cómo corregirlos.

Cómo corregir errores de clases duplicadas

Si una clase aparece más de una vez en la ruta de clase de tiempo de ejecución, es posible que se produzca 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 contiene una biblioteca que tu app también incluye como dependencia directa. Por ejemplo, tu app declara que depende directamente de la Biblioteca A y de la Biblioteca B, pero la Biblioteca A ya incluye la Biblioteca B en su objeto binario.
    • Para resolver este problema, quita la Biblioteca B como 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 corregir conflictos entre rutas de clase

Cuando Gradle determina la ruta de clase de la compilación, primero especifica la ruta de clase de tiempo de ejecución y usa el resultado para establecer qué versiones de las dependencias deberían agregarse a la ruta de clase de la compilación. En otras palabras, la ruta de clase del tiempo de ejecución determina los números de versión que se requieren para dependencias idénticas en las rutas de clase descendientes.

La ruta de clase de tiempo de ejecución también determina los números de versión que Gradle requiere para las dependencias que coinciden en la ruta de clase de tiempo de ejecución del APK de prueba de la app. La jerarquía de rutas de clase se describe en la figura 1.

Figura 1: Los números de versión de las dependencias que aparecen en varias rutas de clase deben coincidir según esta jerarquía.

Es posible que se produzca un conflicto en el que diferentes versiones de la misma dependencia aparecen en varias rutas de clase cuando, por ejemplo, tu app incluye una versión de una dependencia que usa la configuración de dependencia implementation y un módulo de biblioteca incluye una versión diferente de la dependencia que usa la configuración runtimeOnly.

Al determinar las dependencias en las rutas de clase de tiempo de ejecución y compilación, el complemento de Android para Gradle 3.3.0 o una versión posterior intenta corregir automáticamente conflictos entre determinadas versiones descendentes. Por ejemplo, si la ruta de clase de tiempo de ejecución incluye la versión 2.0 de la Biblioteca A y la ruta de clase de la compilación incluye la versión 1.0 de la Biblioteca A, el complemento actualiza automáticamente la dependencia en la ruta de clase de la compilación a la versión 2.0 de la Biblioteca A para evitar errores.

Sin embargo, si la ruta de clase de tiempo de ejecución incluye la versión 1.0 de la Biblioteca A y la ruta de clase de la compilación incluye la versión 2.0 de la Biblioteca A, el complemento no pasará la dependencia en la ruta de clase de compilación a la versión 1.0 de la Biblioteca A, y aun así se producirá 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.
    

Para solucionar este problema, realiza una de las siguientes acciones:

  • Incluye la versión deseada de la dependencia como una dependencia api en tu módulo de biblioteca. Es decir, solo tu módulo de biblioteca declarará la dependencia, pero el módulo de la app también tendrá acceso a su API de manera transitiva.
  • Como alternativa, puedes declarar la dependencia en ambos módulos, pero deberías asegurarte de que cada uno use la misma versión de la dependencia. Considera configurar propiedades en todo el proyecto a fin de garantizar que las versiones de cada dependencia mantengan la coherencia en el proyecto.

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

En esta sección, se describen temas avanzados que son útiles cuando quieres extender el complemento de Android para Gradle o escribir tu propio complemento.

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

Una biblioteca puede tener funcionalidades que otros proyectos o subproyectos probablemente quieran usar. La publicación de una biblioteca es el proceso mediante el cual esta se habilita para sus consumidores. Las bibliotecas pueden controlar a qué dependencias pueden acceder sus consumidores en el tiempo de ejecución y compilación.

Existen dos configuraciones independientes que contienen las dependencias de cada ruta de clase que deben usar los consumidores para usar la biblioteca, como se describe a continuación:

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

Para obtener más información sobre la relación entre las diferentes opciones de configuración, ve a Opciones de configuración del complemento de biblioteca Java.

Cómo personalizar las estrategias de selección de dependencias

Un proyecto puede incluir una dependencia en dos versiones diferentes de la misma biblioteca, lo que puede generar conflictos entre las dependencias. Por ejemplo, si tu proyecto depende de la versión 1 del módulo A y la versión 2 del módulo B, y el módulo A depende de forma transitiva de la versión 3 del módulo B, se producirá un conflicto con las versiones de las dependencias.

Para resolver este conflicto, el complemento de Android para Gradle usa la siguiente estrategia de selección de dependencias: cuando el complemento detecta que hay diferentes versiones del mismo módulo en el gráfico de dependencias, selecciona de manera predeterminada la que tenga el número de versión más alto.

Sin embargo, es posible que esta estrategia no siempre funcione como lo deseas. Si quieres personalizar la estrategia de selección de dependencias, usa las siguientes opciones de configuración a fin de determinar las dependencias específicas de una variante que se necesitan para tu tarea:

  • variant_nameCompileClasspath: Esta configuración contiene la estrategia de resolución para la ruta de clase de la compilación de una variante determinada.
  • variant_nameRuntimeClasspath: Esta configuración contiene la estrategia de resolución de una ruta de clase de tiempo de ejecución de una variante determinada.

El complemento de Android para Gradle incluye captadores que puedes usar para acceder a los objetos de configuración de cada variante. Por lo tanto, puedes usar la API de variantes para consultar la selección de la dependencia 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 {
                ...
            }
        }
    }