Adicionar dependências de compilação

O sistema de compilações Gradle no Android Studio facilita a inclusão de binários externos ou outros módulos de biblioteca na compilação como dependências. As dependências podem estar localizadas na sua máquina ou em um repositório remoto. Todas as dependências transitivas declaradas também serão automaticamente incluídas. Esta página descreve como usar dependências com um projeto do Android, incluindo detalhes sobre comportamentos e configurações específicos do plug-in do Android para Gradle. Para ter orientações conceituais mais detalhadas sobre as dependências do Gradle, consulte também o guia do Gradle para gerenciamento de dependências. No entanto, lembre-se de que o projeto do Android precisa usar apenas as configurações de dependência definidas nesta página.

Tipos de dependência

Para adicionar uma dependência ao projeto, especifique uma configuração de dependência como implementation no bloco dependencies do arquivo build.gradle.

Por exemplo, o arquivo build.gradle a seguir de um módulo de aplicativo inclui três tipos de dependências:

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 solicitação exige um tipo diferente de dependência de biblioteca:

Dependência de módulo de biblioteca local
implementation project(':mylibrary')

Esse código declara uma dependência de um módulo de biblioteca do Android chamado "mylibrary" (esse nome precisa corresponder ao nome da biblioteca definido com um include: no arquivo settings.gradle). Ao criar seu aplicativo, o sistema compila o módulo de biblioteca e empacota o conteúdo compilado resultante no APK.

Dependência binária local
implementation fileTree(dir: 'libs', include: ['*.jar'])

O Gradle declara dependências nos arquivos JAR dentro do diretório module_name/libs/ do projeto porque ele lê caminhos relativos para o arquivo build.gradle.

Como alternativa, você pode especificar arquivos individuais da seguinte forma:

implementation files('libs/foo.jar', 'libs/bar.jar')
Dependência binária remota
implementation 'com.example.android:app-magic:12.3'

Na verdade, esse código é uma abreviação de:

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

Esse código declara uma dependência da versão 12.3 da biblioteca "app-magic", dentro do grupo de namespace "com.example.android".

Observação: dependências remotas como essa exigem que você declare os repositórios remotos adequados em que o Gradle precisa procurar a biblioteca. Se a biblioteca ainda não existir localmente, o Gradle a extrairá do site remoto quando exigido pela compilação (como quando você clica em Sync Project with Gradle Files ou executa uma compilação).

Configurações de dependência

Dentro do bloco dependencies, você pode declarar uma dependência de biblioteca usando uma entre várias configurações de dependência diferentes (como implementation acima). Cada configuração de dependência fornece ao Gradle instruções diferentes sobre como usar a dependência. A tabela a seguir descreve cada uma das configurações que podem ser usadas para uma dependência em um projeto do Android. A tabela também compara essas configurações às configurações obsoletas do plug-in do Android para Gradle 3.0.0.

Nova configuração Configuração obsoleta Comportamento
implementation compile O Gradle adiciona a dependência ao caminho de classe de compilação e empacota a dependência no resultado de compilação. No entanto, quando o módulo configura uma dependência implementation, isso informa ao Gradle que você não quer que o módulo vaze a dependência para outros módulos no tempo da compilação. Ou seja, a dependência é disponibilizada a outros módulos apenas no tempo de execução.

O uso dessa configuração de dependência, em vez de api ou compile (obsoleto), pode resultar em melhorias consideráveis no tempo de compilação, já que isso reduz o número de módulos que o sistema de compilação precisa processar. Por exemplo, se uma dependência implementation alterar sua API, o Gradle recompilará apenas essa dependência e os módulos que dependem diretamente dela. A maioria dos módulos de teste e aplicativos precisa usar essa configuração.

api compile O Gradle adiciona a dependência ao caminho de classe de compilação e ao resultado de compilação. Quando um módulo inclui uma dependência api, informa ao Gradle que quer exportá-la de forma transitiva para outros módulos para que ela fique disponível a eles no tempo de execução e de compilação.

Essa configuração se comporta como compile (agora obsoleta). No entanto, use-a com cautela e somente com dependências que você precisa exportar de modo transitivo para outros clientes ascendentes. Isso porque, se uma dependência api alterar a API externa, o Gradle recompilará todos os módulos que têm acesso a ela no tempo de compilação. Portanto, a existência de um grande número de dependências api pode aumentar consideravelmente o tempo de compilação. A menos que você queira expor a API de uma dependência a um módulo separado, os módulos de biblioteca precisam usar dependências implementation.

compileOnly provided O Gradle adiciona a dependência somente ao caminho de classe (ou seja, a dependência não é adicionada ao resultado da compilação). Isso é útil quando você está criando um módulo do Android e precisa da dependência durante a compilação, mas a presença durante o tempo de execução é opcional.

Se você usar essa configuração, o módulo de biblioteca precisará incluir uma condição de tempo de execução para verificar se a dependência está disponível e alterar seu comportamento de forma controlada para continuar funcionando, caso a dependência não esteja disponível. Isso ajuda a reduzir o tamanho do APK final, evitando a adição de dependências transientes não essenciais. Essa configuração se comporta da mesma forma que provided (obsoleta).

runtimeOnly apk O Gradle adiciona a dependência apenas ao resultado da compilação, para uso durante o tempo de execução. Ou seja, a dependência não é adicionada ao caminho de classe de compilação. Essa configuração se comporta da mesma forma que apk (obsoleta).
annotationProcessor compile Para adicionar uma dependência a uma biblioteca que seja um processador de anotações, é preciso adicioná-la ao caminho de classe do processador de anotações usando a configuração annotationProcessor. Usar essa configuração aprimora o desempenho de compilação, separando o caminho de classe da compilação do caminho de classe do processador de anotações. Se o Gradle encontrar processadores de anotações no caminho de classe de compilação, ele desativará a evasão de compilação, o que afeta negativamente o tempo de compilação. O Gradle 5.0 e versões posteriores ignoram os processadores de anotações encontrados no caminho de classe de compilação.

O plug-in do Android para Gradle entenderá que uma dependência é um processador de anotações se o arquivo JAR contiver o seguinte arquivo:
META-INF/services/javax.annotation.processing.Processor. Se o plug-in detectar que há um processador de anotações no caminho de classe da compilação, ele gerará um erro de compilação.
lintChecks Use essa configuração para incluir verificações de lint que você quer que o Gradle execute ao criar seu projeto.

Observação: ao usar o plug-in do Android para Gradle 3.4.0 e posterior, essa configuração de dependência não empacota mais as verificações de lint nos projetos da biblioteca Android. Para incluir dependências de verificação de lint nas bibliotecas AAR, use a configuração lintPublish descrita abaixo.

lintPublish Use essa configuração em projetos de biblioteca Android para incluir verificações de lint que você quer que o Gradle compile em um arquivo lint.jar e empacote no AAR. Isso faz com que os projetos que consomem seu AAR também apliquem essas verificações de lint. Se você usava a configuração de dependência lintChecks para incluir verificações de lint no AAR publicado, será necessário migrar essas dependências para usar a configuração lintPublish.

    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')
    }

As configurações acima aplicam dependências a todas as variantes de compilação. Se, em vez disso, você quiser declarar uma dependência apenas para um conjunto de origem de uma variante de compilação específica ou para um conjunto de origem de teste, capitalize o nome da configuração de dependência e adicione um prefixo com o nome da variante de compilação ou do conjunto de origem de teste.

Por exemplo, para adicionar uma dependência implementation apenas à variação de produto "free” (usando uma dependência binária remota), o código é semelhante a:

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

No entanto, se quiser adicionar uma dependência para uma variante que combina uma variação de produto e um tipo de compilação, inicialize o nome da configuração no bloco configurations. O exemplo a seguir adiciona uma dependência runtimeOnly à variante de compilação "freeDebug" (usando uma dependência binária local):

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

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

Para adicionar a dependência implementation para testes locais e instrumentados, o código é semelhante a:

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

No entanto, algumas configurações não fazem sentido nessa situação. Por exemplo, como outros módulos não podem depender de androidTest, você receberá o seguinte aviso se usar a configuração androidTestApi:

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

Adicionar processadores de anotações

Se você adicionar processadores de anotações ao caminho de classe da compilação, receberá uma mensagem de erro parecida com esta:

    Error: Annotation processors must be explicitly declared now.
    

Para resolver esse erro, adicione processadores de anotações a seu projeto, configurando sua dependência com annotationProcessor, como mostrado abaixo:

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

Observação: o plug-in do Android para Gradle 3.0.0 e versões posteriores não são mais compatíveis com o plug-in android-apt.

Passar argumentos para os processadores de anotações

Se você precisar passar os argumentos para um processador de anotações, use o bloco AnnotationProcessorOptions na configuração de compilação do seu módulo. Por exemplo, se você quiser transmitir tipos de dados primitivos como pares de chave-valor, poderá usar a propriedade argument, como mostrado abaixo:

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

No entanto, ao usar o plug-in do Android para Gradle 3.2.0 e versões posteriores, você precisará passar argumentos de processador que representam arquivos ou diretórios usando a interface CommandLineArgumentProvider.

Usar CommandLineArgumentProvider permite que você ou o autor do processador de anotações melhore a exatidão e o desempenho de compilações limpas graduais e em cache aplicando as anotações de tipo de propriedade de compilação gradual a cada argumento.

Por exemplo, a classe abaixo implementa CommandLineArgumentProvider e anota cada argumento do processador. A amostra também usa a sintaxe da linguagem Groovy e está incluída diretamente no arquivo build.gradle do 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 {...}
    

Após criar uma classe que implementa CommandLineArgumentProvider, você precisa inicializar e passá-la ao plug-in do Android usando a propriedade annotationProcessorOptions.compilerArgumentProvider, como mostrado abaixo.

// 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 saber mais sobre como a implementação de CommandLineArgumentProvider ajuda a melhorar o desempenho da compilação, leia Projetos Java em cache.

Desativar a verificação de erros do processador de anotações

Se você tiver dependências no caminho de classe da compilação que incluem processadores de anotações que não são necessários, será possível desativar a verificação de erros adicionando o seguinte ao arquivo build.gradle. Lembre-se de que os processadores de anotações adicionados ao caminho de classe da compilação ainda não serão incluídos ao caminho de classe do processador.

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

Se você tiver problemas após migrar os processadores de anotações do seu projeto para o caminho de classe do processador, permita processadores de anotações no caminho de classe da compilação configurando includeCompileClasspath como true. No entanto, configurar essa propriedade como true não é recomendado, e a opção para isso será removida em uma atualização futura do plug-in do Android.

Excluir dependências transitivas

À medida que um aplicativo cresce no escopo, ele pode conter uma série de dependências, incluindo dependências diretas e transitivas (bibliotecas do seu aplicativo que dependem de bibliotecas importadas). Para excluir as dependências transitivas de que você não precisa mais, é possível usar a palavra-chave exclude, conforme mostrado abaixo:

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

Excluir dependências transitivas das configurações de teste

Se você precisar excluir certas dependências transitivas dos seus testes, a amostra do código mostrada acima talvez não funcione conforme o esperado. Isso porque uma configuração de teste (por exemplo, androidTestImplementation) estende a configuração implementation do módulo. Ou seja, sempre haverá dependências implementation quando o Gradle resolver a configuração.

Assim, para excluir dependências transitivas dos seus testes, é preciso fazer isso no tempo de execução, conforme mostrado abaixo:

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

Observação: ainda é possível usar a palavra-chave exclude no bloco de dependências, conforme mostrado no exemplo de código original na seção Excluir dependências para omitir dependências transitivas que são específicas à configuração de teste e não estão incluídas em outras configurações.

Usar gerenciamento de dependências com reconhecimento de variantes

O plug-in do Android 3.0.0 ou posterior inclui um novo mecanismo de dependência que faz a correspondência automática de variantes ao consumir uma biblioteca. Isso significa que a variante debug de um aplicativo consome automaticamente a variante debug de uma biblioteca e assim por diante. Isso também funciona ao usar variações: a variante freeDebug de um aplicativo consumirá a variante freeDebug de uma biblioteca.

Para que o plug-in estabeleça correspondências precisas entre as variantes, será necessário fornecer fallbacks de correspondência para os casos em que uma correspondência direta é impossível. Verifique se seu aplicativo configura um tipo de compilação chamado "staging", mas uma das dependências de biblioteca dele não. Quando o plug-in tentar criar a versão "staging" do seu aplicativo, ele não saberá qual versão da biblioteca usar e você verá uma mensagem de erro semelhante à seguinte:

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

Resolver erros de compilação relacionados à correspondência de variantes

O plug-in inclui elementos DSL para ajudar a controlar como o Gradle precisa solucionar situações em que uma correspondência direta de variante entre um aplicativo e uma dependência não é possível. Consulte a tabela para determinar qual propriedade de DSL você precisa usar para solucionar certos erros de compilação relacionados à correspondência de dependências com reconhecimento de variantes.

Causa do erro de compilaçãoResolução

Seu aplicativo inclui um tipo de compilação que uma dependência de biblioteca não tem.

Por exemplo, seu aplicativo inclui um tipo de compilação "staging", mas uma dependência inclui somente tipos de compilação "debug" e "release".

Observe que não há problema quando uma dependência de biblioteca inclui um tipo de compilação que seu aplicativo não tem. Isso ocorre porque o plug-in simplesmente nunca solicita esse tipo de compilação da dependência.

Use matchingFallbacks para especificar correspondências alternativas para determinado tipo de compilação, conforme mostrado abaixo:


    // 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 determinada dimensão de variação que existe no aplicativo e na sua dependência de biblioteca, seu aplicativo inclui variações que a biblioteca não tem.

Por exemplo, tanto o aplicativo quanto as dependências de biblioteca incluem uma dimensão de variação "tier". Entretanto, a dimensão "tier" no aplicativo inclui variações "free" e "paid", mas uma dependência inclui somente variações "demo" e "paid" para a mesma dimensão.

Observe que, para determinada dimensão de variação que existe no aplicativo e nas dependências de biblioteca, não há problema quando uma biblioteca inclui uma variação de produto que o aplicativo não tem. Isso ocorre porque o plug-in simplesmente nunca solicita essa variação da dependência.

Use matchingFallbacks para especificar correspondências alternativas para a variação de produto "free" do aplicativo, conforme é mostrado abaixo:


    // 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']
            }
        }
    }
    

Uma dependência de biblioteca inclui uma dimensão de variação que o aplicativo não tem.

Por exemplo, uma dependência de biblioteca inclui variações para uma dimensão "minApi", mas seu aplicativo inclui variações apenas para a dimensão "tier". Então, quando você quiser compilar a versão "freeDebug" do seu aplicativo, o plug-in não saberá se precisa usar a versão "minApi23Debug" ou "minApi18Debug" da dependência.

Observe que não há problema quando seu aplicativo inclui uma dimensão de variação que uma dependência de biblioteca não tem. Isso ocorre porque o plug-in faz a correspondência de variações apenas nas dimensões que existem na dependência. Por exemplo, se uma dependência não incluir uma dimensão para ABIs, a versão "freeX86Debug" do aplicativo simplesmente usará a versão "freeDebug" da dependência.

Use missingDimensionStrategy no bloco defaultConfig para especificar a variação padrão que o plug-in precisa selecionar de cada dimensão ausente, conforme mostrado no exemplo abaixo. Você também pode modificar suas seleções no bloco productFlavors, de forma que cada variação possa especificar uma estratégia de correspondência diferente para uma dimensão ausente.


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

Configurar dependências do app Wear OS

Configurar dependências para um módulo de Wear OS é similar ao de qualquer outro módulo. Ou seja, eles usam as mesmas configurações de dependência, como implementation e compileOnly.

Os módulos de Wear também são compatíveis com gerenciamento de dependências com reconhecimento de variantes. Como resultado, se o módulo do aplicativo base tiver uma dependência em um módulo de Wear, cada variante do módulo de base consumirá a variante correspondente no módulo de Wear. Se você estiver compilando um app simples com uma dependência somente em um módulo de Wear, em que o módulo configura as mesmas variantes do seu módulo base, você precisará especificar a configuração wearApp no arquivo build.gradle do módulo base, conforme mostrado abaixo:

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')
    }
    

Se tiver vários módulos de aplicativo Wear e quiser especificar um módulo diferente por variação de aplicativo, você poderá fazer isso usando a configuração flavorWearApp, conforme indicado a seguir. No entanto, não é possível incluir outras dependências que usem a configuração wearApp:

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

Repositórios remotos

Quando a dependência é relacionada a algo diferente de uma biblioteca ou árvore de arquivos local, o Gradle procura os arquivos nos repositórios on-line especificados no bloco repositories do arquivo build.gradle. A ordem usada para listar cada repositório determina a ordem de pesquisa de repositórios do Gradle para cada dependência de projeto. Por exemplo, se uma dependência estiver disponível em ambos os repositórios A e B, e você listar A primeiro, o Gradle fará o download da dependência do repositório A.

Por padrão, novos projetos do Android Studio especificam o repositório Maven do Google e o JCenter como os locais de repositório no arquivo build.gradle de nível superior do projeto, conforme mostrado abaixo:

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

Se você quiser algo do repositório central Maven, adicione mavenCentral() ou, para um repositório local, use mavenLocal():

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

Você também pode declarar repositórios Maven ou Ivy específicos da seguinte forma:

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

Para mais informações, consulte o guia de repositórios do Gradle.

Repositório Maven do Google

As versões mais recentes das seguintes bibliotecas do Android estão disponíveis no repositório Maven do Google:

Você pode ver todos os artefatos disponíveis no índice do repositório Maven do Google (veja abaixo informações sobre o acesso programático).

Para adicionar uma dessas bibliotecas à sua compilação, inclua o repositório Maven do Google no arquivo build.gradle de nível 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/'
        }
    }
    

Em seguida, adicione a biblioteca desejada ao bloco dependencies do módulo. Por exemplo, a biblioteca appcompat é semelhante a:

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

No entanto, se você estiver tentando usar uma versão anterior das bibliotecas acima e a dependência falhar, isso significa que ela não está disponível no repositório Maven e que você precisa consegui-la no repositório off-line.

Acesso programático

Para acesso programático aos artefatos do Maven do Google, você pode ver uma lista XML dos grupos de artefatos em maven.google.com/master-index.xml. Em seguida, para qualquer grupo, você pode ver os nomes e versões de biblioteca em:

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

Por exemplo, as bibliotecas do grupo android.arch.lifecycle estão listadas em maven.google.com/android/arch/lifecycle/group-index.xml.

Também é possível fazer o download dos arquivos POM e JAR em:

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

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

Repositório off-line do SDK Manager

Para as bibliotecas não disponíveis no repositório Maven do Google (normalmente, versões anteriores das bibliotecas), você precisa fazer o download do pacote Google Repository off-line no SDK Manager.

Em seguida, você pode adicionar essas bibliotecas ao bloco dependencies da forma habitual.

As bibliotecas off-line são salvas em android_sdk/extras/.

Ordem de dependências

A ordem em que as dependências são listadas indica a prioridade de cada uma: a primeira biblioteca tem maior prioridade que a segunda, a segunda tem maior prioridade que a terceira e assim por diante. Essa ordem é importante quando recursos são combinados ou elementos do manifesto são combinados no aplicativo a partir das bibliotecas.

Por exemplo, se o projeto declarar:

  • A dependência de LIB_A e LIB_B (nessa ordem)
  • E LIB_A depende de LIB_C e LIB_D (nessa ordem)
  • E LIB_B também depende de LIB_C

A ordem de dependência combinada será a seguinte:

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

Isso garante que LIB_A e LIB_B possam substituir LIB_C. LIB_D mantém a prioridade maior que LIB_B porque LIB_A (que depende dele) tem prioridade maior que LIB_B.

Para mais informações sobre como manifestos de diferentes origens/dependências do projeto são combinados, consulte Combinar vários arquivos de manifesto.

Visualizar dependências do módulo

Algumas dependências diretas podem ter suas próprias dependências. Essas próprias dependências são denominadas dependências transitivas. Em vez de exigir que você declare manualmente cada dependência transitiva, o Gradle coleta e adiciona automaticamente essas dependências para você. O plug-in do Android para Gradle disponibiliza uma tarefa que exibe uma lista das dependências que o Gradle resolve para determinado módulo.

Para cada módulo, o relatório também agrupa as dependências com base na variante de compilação, no conjunto de origem de teste e no caminho de classe. Veja a seguir um relatório de amostra do caminho de classe de tempo de execução de um módulo de aplicativo referente à variante de compilação de depuração e a um caminho de classe de compilação do conjunto de origem de teste instrumentado.

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 executar a tarefa, faça o seguinte:

  1. Selecione View > Tool Windows > Gradle (ou clique em Gradle na barra de janelas de ferramentas).
  2. Abra AppName > Tasks > android e clique duas vezes em androidDependencies. Depois que o Gradle executa a tarefa, a janela Run é aberta para exibir a saída.

Para saber mais sobre como gerenciar as dependências no Gradle, consulte Conceitos básicos sobre o gerenciamento de dependências (link em inglês) no guia do usuário do Gradle.

Corrigir erros de resolução de dependência

Quando você adiciona várias dependências ao projeto do seu aplicativo, essas dependências diretas e transitivas podem entrar em conflito. O plug-in do Android para Gradle tenta resolver esses conflitos, mas alguns deles podem levar a erros de tempo de execução ou compilação.

Para ajudar a investigar quais dependências contribuem com erros, examine a árvore de dependências do aplicativo e procure dependências que aparecem mais de uma vez ou versões conflitantes.

Se não for possível identificar facilmente a dependência duplicada, tente usar a IU do Android Studio para procurar dependências que incluem a classe duplicada da seguinte forma:

  1. Selecione Navigate > Class na barra de menus.
  2. Na caixa de diálogo pop-up de pesquisa, verifique se a caixa ao lado de Include non-project items está marcada.
  3. Digite o nome da classe que aparece no erro de compilação.
  4. Examine os resultados das dependências que incluem a classe.

As seguintes seções descrevem os tipos diferentes de erros de resolução de dependência que você talvez tenha e como corrigi-los.

Corrigir erros de classe duplicados

Se uma classe aparecer mais de uma vez no caminho de classe do tempo de execução, você receberá um erro parecido com este:

    Program type already present com.example.MyClass
    

Normalmente, esse erro ocorre devido a uma das seguintes circunstâncias:

  • Uma dependência binária inclui uma biblioteca que o aplicativo também inclui como uma dependência direta. Por exemplo, o método declara uma dependência direta de Biblioteca A e Biblioteca B, mas a Biblioteca A já inclui a Biblioteca B no binário dela.
    • Para resolver esse problema, remova a Biblioteca B como dependência direta.
  • O aplicativo tem uma dependência binária local e uma dependência binária remota na mesma biblioteca.
    • Para resolver esse problema, remova uma das dependências binárias.

Corrigir conflitos entre caminhos de classe

Quando o Gradle resolve o caminho de classe da compilação, ele primeiro resolve o caminho de classe do tempo de execução e usa o resultado para determinar quais versões das dependências precisam ser adicionadas ao caminho de classe de compilação. Em outras palavras, o caminho de classe do tempo de execução determina os números de versão necessários para dependências idênticas nos caminhos de classe descendentes.

O caminho de classe de tempo de execução do app também determina os números da versão que o Gradle exige para corresponder dependências no caminho de classe de tempo de execução para o APK de teste do aplicativo. A hierarquia de caminhos de classe está descrita na figura 1.

Figura 1. Números da versão das dependências que aparecem em vários caminhos de classe precisam corresponder a esta hierarquia.

Um conflito em que versões diferentes da mesma dependência aparecem em vários caminhos de classe ocorre quando, por exemplo, o aplicativo inclui uma versão de uma dependência usando a configuração de dependência implementation e um módulo de biblioteca inclui uma versão diferente da dependência usando a configuração runtimeOnly.

Ao resolver dependências nos caminhos de classe de tempo de execução e compilação, o plug-in do Android para Gradle 3.3.0 ou posterior tenta corrigir automaticamente alguns conflitos de versão anterior. Por exemplo, se o caminho de classe do tempo de execução incluir a Biblioteca A versão 2.0 e o de compilação incluir a Biblioteca A versão 1.0, o plug-in automaticamente atualizará a dependência do caminho de classe de compilação para a Biblioteca A 2.0 para evitar erros.

No entanto, se o caminho de classe do tempo de execução incluir a Biblioteca A versão 1.0 e o de compilação incluir a Biblioteca A versão 2.0, o plug-in não fará downgrade da dependência do caminho de classe de compilação para a Biblioteca A versão 1.0, e isso gerará um erro semelhante ao seguinte:

    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 resolver esse problema, faça uma das seguintes ações:

  • Inclua a versão desejada da dependência como uma dependência api ao seu módulo de biblioteca. Ou seja, somente seu módulo de biblioteca declara a dependência, mas o módulo do aplicativo também terá acesso transitivo à API.
  • Como alternativa, é possível declarar a dependência em ambos os módulos, mas cada módulo tem que usar a mesma versão da dependência. Considere configurar propriedades em todo o projeto para garantir que as versões de cada dependência permaneçam consistentes em todo o projeto.

Aplicar lógica de compilação personalizada

Esta seção descreve os tópicos avançados que são úteis para estender o plug-in do Android para Gradle ou para escrever seu próprio plug-in.

Publicar dependências variantes na lógica personalizada

Uma biblioteca pode ter funcionalidades que outros projetos ou subprojetos talvez queiram usar. Publicar uma biblioteca é o processo de disponibilização da biblioteca aos clientes. As bibliotecas podem controlar a quais dependências os clientes terão acesso no tempo de compilação e execução.

Existem duas configurações separadas que possuem as dependências transitivas de cada caminho de classe. Elas podem ser usadas pelos clientes para consumir a biblioteca conforme descrito abaixo:

  • variant_nameApiElements: essa configuração possui as dependências transitivas que estão disponíveis aos clientes no tempo de compilação.
  • variant_nameRuntimeElements: essa configuração possui as dependências transitivas que estão disponíveis aos clientes no tempo de execução.

Para saber mais sobre as relações entre as diferentes configurações, acesse as Configurações de plug-in da Biblioteca Java (link em inglês).

Estratégias de resolução de dependências personalizadas

Um projeto pode incluir uma dependência em duas versões diferentes da mesma biblioteca, o que pode resultar em conflitos de dependência. Por exemplo, se o projeto depende da versão 1 do módulo A e da versão 2 do módulo B, e o módulo A depende transitivamente da versão 3 do módulo B, ocorre um conflito de versão de dependência.

Para resolver esse conflito, o plug-in do Android para Gradle usa a seguinte estratégia de resolução de dependência: quando o plug-in detecta que as diferentes versões do mesmo módulo estão no gráfico de dependência, por padrão, ele escolhe aquele com o número de versão mais alto.

No entanto, talvez essa estratégia não funcione sempre como o esperado. Para personalizar a estratégia de resolução de dependência, use as seguintes configurações para resolver dependências específicas de uma variante que são necessárias para sua tarefa:

  • variant_nameCompileClasspath: essa configuração contém a estratégia de resolução do caminho de classe da compilação de uma dada variante.
  • variant_nameRuntimeClasspath: essa configuração contém a estratégia de resolução do caminho de classe do tempo de execução de uma dada variante.

O plug-in do Android para Gradle inclui coletores que podem ser usados para acessar os objetos de configuração de cada variante. Assim, é possível usar a API da variante para consultar a resolução da dependência, conforme mostrado no exemplo abaixo:

    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 {
                ...
            }
        }
    }