O sistema de build Gradle no Android Studio facilita a inclusão de binários externos ou outros módulos de biblioteca no build 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 orientações conceituais mais detalhadas sobre as dependências do Gradle, consulte também o Guia do Gradle para gerenciamento de dependências (link em inglês). No entanto, não esqueça 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
do módulo.
Por exemplo, o arquivo build.gradle
a seguir para um módulo do app inclui
três tipos diferentes de dependências:
Groovy
plugins { id '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' }
Kotlin
plugins { id("com.android.application") } android { ... } dependencies { // Dependency on a local library module implementation(project(":mylibrary")) // Dependency on local binaries implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.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
-
Groovy
implementation project(':mylibrary')
Kotlin
implementation(project(":mylibrary"))
Isso declara uma dependência em um módulo de biblioteca do Android chamado "mylibrary". Esse nome precisa corresponder ao nome da biblioteca definido com
include:
no arquivosettings.gradle
. Ao criar o app, o sistema compila o módulo de biblioteca e empacota o conteúdo compilado resultante nesse app. - Dependência binária local
-
Groovy
implementation fileTree(dir: 'libs', include: ['*.jar'])
Kotlin
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
O Gradle declara dependências nos arquivos JAR dentro do diretório
module_name/libs/
do projeto, porque ele lê caminhos relativos ao arquivobuild.gradle
.Como alternativa, você pode especificar arquivos individuais da seguinte forma:
Groovy
implementation files('libs/foo.jar', 'libs/bar.jar')
Kotlin
implementation(files("libs/foo.jar", "libs/bar.jar"))
- Dependência binária remota
-
Groovy
implementation 'com.example.android:app-magic:12.3'
Kotlin
implementation("com.example.android:app-magic:12.3")
Na verdade, esse código é uma abreviação de:
Groovy
implementation group: 'com.example.android', name: 'app-magic', version: '12.3'
Kotlin
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 vai extraí-la do armazenamento remoto quando exigido pelo build (por exemplo, quando você clica em Sync Project with Gradle Files
ou executa um build).
Se você precisa de uma dependência do AGP durante a compilação, é necessário que ela seja adicionada como uma
dependência explícita. Como o AGP usa configurações api/implementation
internamente, alguns artefatos podem ser removidos do caminho de
classe de compilação, que pode mudar.
Dependências nativas
A partir do Plug-in do Android para Gradle 4.0, as dependências nativas também podem ser importadas da forma descrita nesta página.
A dependência em um AAR que expõe bibliotecas nativas vai disponibilizá-las
automaticamente para o sistema de build usado por externalNativeBuild
. Para acessar as
bibliotecas no seu código, faça a vinculação aos scripts de build nativos.
Nesta página, consulte Como usar dependências nativas.
Configurações de dependência
Dentro do bloco dependencies
, você pode declarar uma dependência de biblioteca usando uma das várias configurações de dependência diferentes (por exemplo, implementation
, mostrado 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 àquelas descontinuadas do Plug-in do
Android para Gradle 3.0.0.
Configuração | Comportamento |
---|---|
implementation |
O Gradle adiciona a dependência ao caminho de classe de compilação e
empacota a dependência no resultado do build. 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 durante a compilação. Ou seja, a dependência é disponibilizada a outros módulos apenas no momento da execução.
O uso dessa configuração de dependência, em vez de
|
api |
O Gradle adiciona a dependência ao caminho de classe de compilação e ao resultado do
build. Quando um módulo inclui uma dependência api , está
informando ao Gradle que ela deve ser exportada de forma transitiva
para outros módulos. Dessa forma, ela vai ficar disponível a
todos eles durante a execução e a compilação.
Essa configuração se comporta como |
compileOnly |
O Gradle adiciona a dependência somente ao caminho de classe,
ou seja, a dependência não é adicionada ao resultado do build. Isso é útil quando
você está criando um módulo do Android e precisa da dependência durante a
compilação, mas a presença dela durante a execução é opcional.
Se você usar essa configuração, o módulo de biblioteca vai ter que
incluir uma condição de execução para verificar se a dependência está
disponível. Se a resposta for negativa, o comportamento do módulo deverá ser modificado de forma controlada para continuar
funcionando. Isso ajuda a reduzir o tamanho do
app final, evitando a adição de dependências transitórias não essenciais.
Essa configuração se comporta da mesma forma que
Observação: não é possível usar a configuração |
runtimeOnly |
O Gradle adiciona a dependência apenas à saída de build, 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 |
Para adicionar uma dependência em uma biblioteca que processa anotações,
adicione-a ao caminho de classe do processador de anotações usando a
configuração O Plug-in do Android para Gradle entende que uma dependência é um processador de anotações quando o arquivo JAR contém o seguinte arquivo:
Se o plug-in detecta que há um processador de anotações no caminho de classe da compilação, ele gera um erro de build. Observação: projetos Kotlin precisam usar o kapt (link em inglês) para declarar dependências do processador de anotações. |
lintChecks |
Use essa configuração para incluir verificações de lint que você quer que o Gradle execute ao criar seu projeto. Observação: com o plug-in do Android para Gradle 3.4.0
e versões mais recentes, 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 |
Use essa configuração em projetos de biblioteca do Android para incluir verificações de lint que você quer que o Gradle compile em um arquivo lint.jar e empacote no seu AAR. Isso faz com que os projetos que consomem seu AAR também apliquem essas verificações de lint. Se você estava usando
a configuração de dependência lintChecks anteriormente para incluir verificações
de lint no AAR publicado, precisa migrar essas dependências
para usar a nova configuração lintPublish descrita abaixo.
Groovydependencies { // 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') } Kotlindependencies { // 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")) } |
apk
|
O Gradle adiciona a dependência apenas à saída de build, para uso durante o tempo de execução. Ou seja, a dependência não é adicionada ao caminho de classe de compilação. Esta configuração foi descontinuada (disponível no AGP 1.0-4.2). |
compile
|
O Gradle adiciona a dependência ao caminho de classe de compilação e ao resultado do build e a exporta para outros módulos. Esta configuração foi descontinuada (disponível no AGP 1.0-4.2). |
provided
|
O Gradle adiciona a dependência somente ao caminho de classe, ou seja, a dependência não é adicionada ao resultado do build. Esta configuração foi descontinuada (disponível no AGP 1.0-4.2). |
Todas as configurações acima aplicam dependências a todas as variantes de build. Se, em vez disso, você quiser declarar uma dependência apenas para um conjunto de origem de uma variante de build específica ou para um conjunto de origem de teste, use uma inicial maiúscula para o nome da configuração de dependência e adicione um prefixo ao nome da variante de build 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 vai ser semelhante a este:
Groovy
dependencies { freeImplementation 'com.google.firebase:firebase-ads:9.8.0' }
Kotlin
dependencies { freeImplementation("com.google.firebase:firebase-ads:9.8.0") }
No entanto, para adicionar uma dependência a uma variante que combina uma
variação de produto e um tipo de build, inicialize o
nome da configuração no bloco configurations
. O exemplo a seguir
adiciona uma dependência runtimeOnly
à variante de build "freeDebug" (usando uma dependência binária local).
Groovy
configurations { // Initializes a placeholder for the freeDebugRuntimeOnly dependency configuration. freeDebugRuntimeOnly {} } dependencies { freeDebugRuntimeOnly fileTree(dir: 'libs', include: ['*.jar']) }
Kotlin
// Initializes a placeholder for the freeDebugRuntimeOnly dependency configuration. val freeDebugRuntimeOnly by configurations.creating dependencies { freeDebugRuntimeOnly(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) }
Para adicionar a dependência implementation
para testes locais e instrumentados, o código é semelhante a:
Groovy
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 'androidx.test.espresso:espresso-core:3.5.1' }
Kotlin
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("androidx.test.espresso:espresso-core:3.5.1") }
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, vai 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 ao seu projeto, configurando
sua dependência com annotationProcessor
, conforme mostrado abaixo.
Groovy
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' }
Kotlin
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 mais recentes
não oferece mais suporte ao
plug-in android-apt
.
Transmitir argumentos a processadores de anotações
Se você precisar transmitir os argumentos para um processador de anotações, use o
bloco AnnotationProcessorOptions
na configuração do build do seu módulo. Por exemplo, para transmitir
tipos de dados primitivos como pares chave-valor, você pode usar a propriedade argument
,
conforme mostrado abaixo.
Groovy
android { ... defaultConfig { ... javaCompileOptions { annotationProcessorOptions { argument 'key1', 'value1' argument 'key2', 'value2' } } } }
Kotlin
android { ... defaultConfig { ... javaCompileOptions { annotationProcessorOptions { arguments += mapOf("key1" to "value1", "key2" to "value2") } } } }
No entanto, ao usar o plug-in do Android para Gradle 3.2.0 e versões mais recentes, você precisa
transmitir argumentos de processador que representam arquivos ou diretórios usando a interface
CommandLineArgumentProvider
do Gradle.
O uso de CommandLineArgumentProvider
permite que você ou
o autor do processador de anotações melhore a exatidão e o desempenho de
builds limpos graduais e em cache aplicando as anotações de tipo de propriedade de build
incremental
a cada argumento.
Por exemplo, a classe abaixo implementa CommandLineArgumentProvider
e anota cada argumento do processador. O exemplo também usa a
sintaxe da linguagem Groovy e está incluída diretamente no arquivo build.gradle
do módulo.
Groovy
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 {...}
Kotlin
class MyArgsProvider( // Annotates each directory as either an input or output for the // annotation processor. @get:InputFiles // Using this annotation helps Gradle determine which part of the file path // should be considered during up-to-date checks. @get:PathSensitive(PathSensitivity.RELATIVE) val inputDir: FileCollection, @get:OutputDirectory val outputDir: File ) : CommandLineArgumentProvider { // 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 fun asArguments(): Iterable<String> { // Use the form '-Akey[=value]' to pass your options to the Java compiler. return listOf("-AinputDir=${inputDir.singleFile.absolutePath}", "-AoutputDir=${outputDir.absolutePath}") } } android {...}
Depois de definir uma classe que implementa CommandLineArgumentProvider
, você precisa
criar uma instância e transmiti-la ao plug-in do Android usando o método
annotationProcessorOptions.compilerArgumentProvider
,
mostrado abaixo.
Groovy
// 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")) } } } }
Kotlin
// 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(MyArgsProvider(files("input/path"), file("output/path"))) } } } }
Para saber mais sobre como a implementação de CommandLineArgumentProvider
ajuda
a melhorar o desempenho do build, 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 desnecessários, poderá desativar a verificação de erros adicionando
o seguinte código ao arquivo build.gradle
. Não esqueça que os processadores de
anotações adicionados ao caminho de classe da compilação ainda não estão incluídos no
caminho de classe do processador.
Groovy
android { ... defaultConfig { ... javaCompileOptions { annotationProcessorOptions { includeCompileClasspath false } } } }
Kotlin
android { ... defaultConfig { ... javaCompileOptions { annotationProcessorOptions { argument("includeCompileClasspath", "false") } } } }
Se você usa o Kotlin e o kapt (em inglês):
Groovy
android { ... defaultConfig { ... kapt { includeCompileClasspath false } } }
Kotlin
android { ... defaultConfig { ... kapt { 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 app cresce em escopo, ele pode conter uma série de dependências, incluindo
dependências diretas e transitivas (bibliotecas do seu app
que dependem de bibliotecas importadas).
Para excluir as dependências transitivas que você não precisa mais, é possível usar a palavra-chave exclude
, conforme mostrado abaixo.
Groovy
dependencies { implementation('some-library') { exclude group: 'com.example.imgtools', module: 'native' } }
Kotlin
dependencies { implementation("some-library") { exclude(group = "com.example.imgtools", module = "native") } }
Excluir dependências transitivas das configurações de teste
Se você precisar excluir determinadas dependências transitivas dos seus testes,
o exemplo de código mostrado acima talvez não funcione conforme o esperado. Isso acontece porque uma configuração de teste (por exemplo, androidTestImplementation
) estende a configuração implementation
do módulo. Ou seja, sempre há dependências implementation
quando o Gradle resolve a configuração.
Assim, para excluir dependências transitivas dos seus testes, é preciso fazer isso no tempo de execução, conforme mostrado abaixo.
Groovy
android.testVariants.all { variant -> variant.getCompileConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp' variant.getRuntimeConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp' }
Kotlin
android.testVariants.all { compileConfiguration.exclude(group = "com.jakewharton.threetenabp", module = "threetenabp") runtimeConfiguration.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 transitivas 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.
Configurar dependências do app Wear OS
A configuração de dependências para um módulo do Wear OS é semelhante
à de qualquer outro módulo. Ou seja, os módulos do Wear OS usam as mesmas configurações
de dependência, como implementation
e compileOnly
.
Os módulos do Wear também oferecem suporte ao gerenciamento de dependências com reconhecimento de variantes. Como resultado, se o módulo do app base tiver uma dependência em um módulo do Wear OS, cada variante do módulo de base vai consumir a variante correspondente no módulo do Wear.
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 dependencyResolutionManagement { repositories {...} }
do arquivo settings.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 está disponível nos repositórios A e B, e você lista A primeiro,
o Gradle faz o download da dependência do repositório A.
Por padrão, os novos projetos do Android Studio especificam o repositório Maven do Google e o
repositório Maven central como
locais de repositório no arquivo settings.gradle
do projeto, como mostrado abaixo:
Groovy
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() } }
Kotlin
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() } }
Se você quiser algo de um repositório local, use mavenLocal()
:
Groovy
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() mavenLocal() } }
Kotlin
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() mavenLocal() } }
Você também pode declarar repositórios Maven ou Ivy específicos da seguinte forma:
Groovy
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { maven { url 'https://repo.example.com/maven2' } maven { url 'file://local/repo/' } ivy { url 'https://repo.example.com/ivy' } } }
Kotlin
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { maven(url = "https://repo.example.com/maven2") maven(url = "file://local/repo/") ivy(url = "https://repo.example.com/ivy") } }
Para saber mais, 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:
- Bibliotecas do AndroidX
- Biblioteca Architecture Components
- Biblioteca Constraint Layout
- AndroidX Test
- Biblioteca Databinding
- Biblioteca Instant Apps Android
- Wear OS
- Google Play Services
- Biblioteca Google Play Faturamento
- Firebase
Você pode conferir todos os artefatos disponíveis no Índice do repositório Maven do Google (informações sobre o acesso programático são mostradas abaixo).
Para adicionar uma dessas bibliotecas ao seu build, inclua o repositório Maven do Google
no arquivo build.gradle
de nível superior:
Groovy
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 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/'. } }
Kotlin
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 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
vai ficar assim:
Groovy
dependencies { implementation 'androidx.appcompat:appcompat:1.6.1' }
Kotlin
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 essa versão não está disponível no repositório Maven e que você precisa a extrair do repositório off-line.
Acesso programático
Para acesso programático aos artefatos do Maven do Google, você pode conferir uma lista XML dos grupos de artefatos em maven.google.com/master-index.xml. Em seguida, para qualquer grupo, você pode conferir os nomes e versões das bibliotecas 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
No caso de bibliotecas que não estão disponíveis no repositório Maven do Google (normalmente, versões antigas), é necessário 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/
.
Dependências nativas com o Plug-in do Android para Gradle
As bibliotecas AAR podem conter dependências nativas que o Plug-in do Android para Gradle pode consumir. O AGP também é capaz de produzir AARs que expõem bibliotecas nativas aos consumidores.
Como usar dependências nativas
No Plug-in do Android para Gradle 4.0 e versões mais recentes, as dependências C/C++ podem ser importadas de
AARs vinculados ao arquivo build.gradle
. O Gradle disponibiliza essas
opções automaticamente para o sistema de build nativo, mas esse sistema precisa ser configurado
para usar as bibliotecas e os cabeçalhos importados. Como as dependências C/C++ são distribuídas como
AARs, os links a seguir sobre AARs genéricos podem ser úteis:
- Como criar uma biblioteca do Android, para conferir uma documentação genérica de AAR e aprender a integrá-lo ao projeto, principalmente quando você quiser usar o AAR como uma dependência local de C/C++.
- Adicionar dependências de build, para ler informações sobre como adicionar dependências ao arquivo
build.gradle
, principalmente no caso de dependências remotas.
Este documento ensina como configurar o sistema de build nativo e supõe que você já adicionou um AAR de dependência C/C++ ao ambiente de build Gradle do seu projeto.
Dependências nativas em AARs
As dependências de AAR dos módulos do Gradle podem expor bibliotecas nativas para uso pelo
seu aplicativo. Dentro do AAR, o diretório prefab
contém um pacote Prefab,
que inclui os cabeçalhos e bibliotecas da dependência nativa.
Cada dependência pode expor, no máximo, um pacote Prefab, que compreende um ou mais módulos. Um módulo Prefab é uma única biblioteca, que pode ser compartilhada, estática ou apenas de cabeçalho.
Os nomes do pacote e do módulo precisam ser conhecidos para que você possa usar as bibliotecas. Por convenção, o nome do pacote corresponderá ao do artefato Maven, e o nome do módulo corresponderá ao da biblioteca C/C++, mas isso não é obrigatório. Consulte a documentação da dependência para determinar quais nomes são usados.
Configuração do sistema de build
O recurso prefab
precisa estar ativado para seu módulo do Gradle para Android.
Para fazer isso, adicione o código abaixo ao bloco android
do arquivo
build.gradle
do módulo:
Groovy
buildFeatures { prefab true }
Kotlin
buildFeatures { prefab = true }
Como opção, configure uma versão
no arquivo gradle.properties
do projeto:
android.prefabVersion=2.0.0
Normalmente, a versão padrão selecionada do AGP atende às suas necessidades. Você só selecionará uma versão diferente se houver um bug que precise ser resolvido ou um novo recurso que você queira.
Cada dependência expõe um arquivo Android.mk
ao build. Eles são
importados com o comando import-module (link em inglês). Esse comando pesquisa arquivos Android.mk
com o caminho fornecido nos diretórios de importação do build (conforme configurado
por import-add-path
) e expõe os módulos definidos para serem usados no
build. Por exemplo, caso o aplicativo defina libapp.so
e use cURL,
seu arquivo Android.mk
deverá incluir o seguinte:
include $(CLEAR_VARS)
LOCAL_MODULE := libapp
LOCAL_SRC_FILES := app.cpp
LOCAL_SHARED_LIBRARIES := curl
include $(BUILD_SHARED_LIBRARY)
# If you don't need your project to build with NDKs older than r21, you can omit
# this block.
ifneq ($(call ndk-major-at-least,21),true)
$(call import-add-path,$(NDK_GRADLE_INJECTED_IMPORT_PATH))
endif
$(call import-module,prefab/curl)
O import-add-path
explícito só é necessário ao usar NDKs
anteriores a r21. Na versão r21 e mais recentes, o NDK_GRADLE_INJECTED_IMPORT_PATH
vai ser adicionado automaticamente
aos caminhos de importação.
app.cpp
agora pode #include "curl/curl.h"
, libapp.so
. Portanto, ele é
automaticamente vinculado ao libcurl.so
durante a criação, e o libcurl.so
é
incluído no app.
Como publicar bibliotecas nativas em AARs
A capacidade de criar AARs nativos foi adicionada inicialmente no AGP 4.1.
Para exportar suas bibliotecas nativas, adicione o código abaixo ao bloco android
do
arquivo build.gradle
do projeto da biblioteca:
Groovy
buildFeatures { prefabPublishing true } prefab { mylibrary { headers "src/main/cpp/mylibrary/include" } myotherlibrary { headers "src/main/cpp/myotherlibrary/include" } }
Kotlin
buildFeatures { prefabPublishing = true } prefab { create("mylibrary") { headers = "src/main/cpp/mylibrary/include" } create("myotherlibrary") { headers = "src/main/cpp/myotherlibrary/include" } }
Neste exemplo, as bibliotecas mylibrary
e myotherlibrary
do ndk-build ou do
build nativo externo do CMake vão ser empacotadas no AAR produzido pelo
build, e cada uma exportará os cabeçalhos do diretório especificado para
os dependentes.
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 integrados ou elementos do manifesto são mesclados ao app a partir das bibliotecas.
Por exemplo, se o projeto declarar:
- A dependência de
LIB_A
eLIB_B
(nessa ordem) - E
LIB_A
depende deLIB_C
eLIB_D
(nessa ordem) - E
LIB_B
também depende deLIB_C
A ordem de dependência combinada será a seguinte:
LIB_A
LIB_D
LIB_B
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 saber mais sobre como manifestos de diferentes origens/dependências do projeto são integrados, consulte Integrar vários arquivos de manifesto.
Visualizar dependências do módulo
Algumas dependências diretas podem ter as 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 mostra 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 build, no conjunto de origem de teste e no caminho de classe. Confira abaixo um exemplo de relatório do caminho de classe da execução de um módulo de app referente à variante de build de depuração e a um caminho de classe da 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:
- Selecione View > Tool Windows > Gradle (ou clique
em Gradle
na barra da janela de ferramentas).
- Abra AppName > Tasks > android e clique duas vezes em androidDependencies. Depois que o Gradle executa a tarefa, a janela Run é aberta para mostrar 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 app, 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 app 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:
- Selecione Navigate > Class na barra de menus.
- Na caixa de diálogo pop-up de pesquisa, confira se a caixa ao lado de Include non-project items está marcada.
- Digite o nome da classe que aparece no erro de build.
- Examine os resultados das dependências que incluem a classe.
As seções a seguir descrevem os diferentes tipos de erro de resolução de dependência que você pode encontrar e como corrigi-los.
Corrigir erros de classe duplicados
Se uma classe aparecer mais de uma vez no caminho de classe de execução, você vai encontrar 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 app 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 app 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 de compilação, ele primeiro resolve o de execução e usa o resultado para determinar quais versões das dependências precisam ser adicionadas ao de compilação. Em outras palavras, o caminho de classe de execução determina os números de versão necessários para dependências idênticas nos caminhos de classe downstream.
O caminho de classe 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 execução para o APK de teste do app. A hierarquia dos 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 app 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 execução e compilação, o Plug-in do Android para Gradle 3.3.0 ou versões mais recentes tentam corrigir automaticamente alguns conflitos de versão downstream. Por exemplo, se o caminho de classe de execução incluir a Biblioteca A versão 2.0 e o de compilação incluir a versão 1.0, o plug-in vai evitar erros atualizando automaticamente a dependência do caminho de classe de compilação para a Biblioteca A 2.0.
No entanto, se o caminho de classe 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 vai fazer downgrade da dependência do caminho de classe de compilação para a Biblioteca A versão 1.0, e isso vai gerar um erro semelhante a este:
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, execute uma destas 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 app 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 build 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 momento da compilação e execução.
Existem duas configurações diferentes 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
: esta configuração possui as dependências transitivas que estão disponíveis aos clientes durante a execução.
Para saber mais sobre as relações entre as diferentes configurações, acesse 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 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 configurações abaixo para resolver dependências específicas de uma variante que são necessárias para sua tarefa:
variant_nameCompileClasspath
: esta configuração contém a estratégia de resolução do caminho de classe da compilação de uma determinada variante.variant_nameRuntimeClasspath
: essa configuração contém a estratégia de resolução do caminho de classe de execução de uma determinada variante.
O plug-in do Android para Gradle inclui getters 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.
Groovy
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 { ... } } }
Kotlin
android { applicationVariants.all { // Return compile configuration objects of a variant. compileConfiguration.resolutionStrategy { // Use Gradle's ResolutionStrategy API // to customize how this variant resolves dependencies. ... } // Return runtime configuration objects of a variant. runtimeConfiguration.resolutionStrategy { ... } // Return annotation processor configuration of a variant. annotationProcessorConfiguration.resolutionStrategy { ... } } }
Informações de dependência do Play Console
Ao criar seu app usando o AGP 4.0.0 e versões mais recentes, o plug-in inclui metadados que descrevem as dependências da biblioteca compiladas no app. Ao fazer upload do app, o Play Console inspeciona esses metadados para fornecer alertas de problemas conhecidos com SDKs e dependências que o app usa e, em alguns casos, fornecem feedback útil para resolver esses problemas.
Os dados são compactados, criptografados por uma chave de assinatura do Google Play e armazenados no
bloco de assinatura do app de lançamento. Recomendamos manter esse arquivo de dependências
para uma experiência do usuário segura e positiva. Se você preferir não compartilhar essas
informações, desative isso incluindo o seguinte bloco
dependenciesInfo
no arquivo build.gradle
do módulo:
android {
dependenciesInfo {
// Disables dependency metadata when building APKs.
includeInApk = false
// Disables dependency metadata when building Android App Bundles.
includeInBundle = false
}
}
Para mais informações sobre nossas políticas e possíveis problemas com dependências, consulte nossa página de suporte sobre como usar SDKs de terceiros no seu app.
Insights do SDK
O Android Studio mostra avisos de lint em arquivos build.gradle
e na
caixa de diálogo Project Structure para SDKs públicos que foram marcados como desatualizados
pelos autores no
SDK Index do Google Play. Esse é um
indicador para atualizar essas dependências, porque o uso de versões desatualizadas pode
impedir você de publicar no Google Play Console no futuro.