Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

目录

目录
添加构建依赖项
依赖类型
本地库模块依赖:project
本地二进制依赖:fileTree 和 files
远程二进制依赖
依赖配置类型
implementation
api
compileOnly
runtimeOnly
annotationProcessor
lintChecks
lintPublish
依赖配置
为特定构建变体源集声明依赖项:configurations
添加注释处理器:annotationProcessor
将参数传递给注释处理器:argument
CommandLineArgumentProvider 示例
禁用注释处理器错误检查:includeCompileClasspath
排除传递依赖项:exclude
使用变体感知依赖关系管理
app 包含依赖库不包含的 buildTypes:matchingFallbacks
app 包含依赖库不包含的 productFlavors:matchingFallbacks
依赖库包括 app 不具有的 flavorDimensions:missingDimensionStrategy
远程存储库
谷歌的Maven存储库
添加Google的Maven中提供的library
程序化访问
SDK Manager 中的离线存储库
依赖关系
依赖顺序
查看依赖关系树
解决重复的类错误
修复重复class错误
修复classpaths之间的冲突
应用自定义构建逻辑
将变体依赖项发布到自定义逻辑
自定义依赖解析策略

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

添加构建依赖项

Add build dependencies

Android Studio中的Gradle构建系统可以轻松地将外部二进制文件其他库模块作为依赖项包含在构建中。依赖项可以位于您的计算机上或远程存储库中,并且它们声明的任何传递依赖项[transitive dependencies]也会自动包含在内。

此页面描述了如何在Android项目中使用依赖项,仅包含特定于Android的Gradle插件[specific to the Android plugin for Gradle]的行为和配置的详细信息。

依赖类型

Dependency types

要向项目添加依赖项,请在build.gradle文件的dependencies块中指定依赖项配置。

app模块的build.gradle文件包含以下三种不同类型的依赖项。

本地库模块依赖:project

Local library module dependency

这声明了对名为“mylibrary”的Android库模块的依赖。此名称必须与在settings.gradle文件中定义为include的库名称匹配。构建应用程序时,构建系统会编译库模块并将生成的AAR文件打包到APK中。

implementation project(":mylibrary") // 依赖当前目录下的本地库模块
implementation project(":chat:mylibrary") //依赖当前目录下 chat 目录中的本地库模块

本地二进制依赖:fileTree 和 files

Local binary dependency

Gradle在项目的 module_name/libs/ 目录(因为Gradle读取相对于build.gradle文件的路径)中声明对JAR文件的依赖。

implementation fileTree(dir: 'libs', include: ['*.jar']) //指定目录或满足规则的所有文件
implementation files('libs/foo.jar', 'libs/bar.jar') //指定单个文件

远程二进制依赖

Remote binary dependency

示例中声明了对 com.example.android 命名空间组[namespace group]内 app-magic 库 12.3 版的依赖性。构建时,如果远程二进制依赖的库本地不存在,Gradle会在构建时从远程站点中下载

implementation 'com.example.android:app-magic:12.3'  //简写
implementation group: 'com.example.android', name: 'app-magic', version: '12.3'  //完整写法

依赖配置类型

Dependency configurations

dependencies 块中,您可以使用几种不同的依赖项配置之一声明库依赖项。 每个依赖项配置都为Gradle提供了有关如何使用依赖项的不同说明。

implementation、api、compile 的区别
api 完全等同于 compile,两者没区别,你将所有的 compile 改成 api时完全没有错。

implementation 这个指令的特点就是,对于使用了该命令编译的依赖,对该项目有依赖的项目将无法访问到使用该命令编译的依赖中的任何程序,也就是将该依赖隐藏在内部,而不对外部公开。换句话说就是,使用 implementation 指令的依赖只作用于当前的 module,而不会传递

例如,有一个 module testsdk 依赖于 gson:implementation 'com.google.code.gson:gson:2.8.2'
另一个 module app 依赖于 testsdk:implementation project(':testsdk')
这时候,因为 testsdk 使用的是 implementation 指令来依赖 gson,所以 app 里边不能引用 gson。

但是,如果 testsdk 使用的是 api 来引用 gson:api 'com.google.code.gson:gson:2.8.2'
则与 Gradle3.0.0 之前的 compile 指令的效果完全一样,app 的 module 也可以引用 gson。

implementation

implementation 可以认为是功能精简的 compile

Gradle将依赖项添加到编译类路径[compilation classpath],并将依赖项打包到构建输出[packages the dependency to the build output]。 但是,当您的模块配置 implementation 依赖项时,它让Gradle知道,您不希望模块在编译时将依赖项泄露给其他模块(意思是在编写代码时不可见)。也就是说,依赖性仅在运行时(运行时是没有分模块的概念的,所以当然可见啦)可用于其他模块。

简单来说就是,使用 implementation 时,对于引用此模块的其他模块来说,在写代码时不可见(不能直接引用),但是在运行时可以通过反射方式调用。

使用此依赖项配置而不是 api 或 compile,会减少构建时间,因为它减少了构建系统需要重新编译的模块数量。例如,如果一个 implementation 依赖项更改了其 API,那么Gradle只会重新编译依赖性和直接依赖于它的模块。大多数 app 和 test 模块都应使用此配置。

api

api 完全等同于 compile

Gradle将依赖项添加到编译类路径并构建输出。当一个模块包含一个 api 依赖项时,它让Gradle知道,该模块想要将该依赖项传递给其他模块,以便它们在运行时和编译时都可用

此配置的行为与 compile 类似,但您应谨慎使用它,通常,你应当仅在需要将依赖项传递给上游使用者时使用。这是因为,如果 api 依赖项更改其外部 API,Gradle 在重新编译时将重新编译有权访问该依赖项的所有模块。因此,拥有大量的 api 依赖项会显著增加构建时间。除非您希望将依赖项的 API 公开给单独的模块,否则模块应该使用 implementation 依赖项。

compileOnly

compileOnly 与废弃的 provided 完全一样

Gradle仅将依赖项添加到编译类路径,即,它不会添加到构建输出中

这在以下情况非常有用:您想创建一个 Android 模块,并且在编译期间需要依赖项,但在运行时其存在是可选的

如果使用此配置,则库模块必须包含运行时条件[runtime condition]以检查依赖项是否可用,然后优雅的更改其行为,以便在未提供时仍可正常运行。这有助于通过,不添加不重要的瞬态[transient]依赖项,来减小最终APK的大小。

注意:经测试发现,compileOnly不能传递依赖。

runtimeOnly

runtimeOnly 与废弃的 apk 完全一样

Gradle仅将依赖项添加到构建输出,以便在运行时使用。也就是说,它不会添加到编译类路径中

annotationProcessor

annotationProcessor 可以认为是用于特定场景的 compile

要添加对作为注释处理器的库的依赖关系,必须使用 annotationProcessor 配置将其添加到注释处理器 classpath。这是因为使用此配置可以通过将 compile classpath 与 annotationProcessor classpath 分开来提高构建性能

如果Gradle在编译类路径上找到注释处理器,它将 deactivates compile avoidance,这会对构建时间产生负面影响(Gradle 5.0及更高版本,忽略在 compile classpath 上找到的注释处理器)。

如果依赖项的JAR文件包含以下文件,则 Android Gradle Plugin 假定其是注释处理器,:

META-INF/services/javax.annotation.processing.Processor

如果插件检测到编译类路径上的注释处理器,则会产生构建错误。

lintChecks

Use this configuration to include lint checks you want Gradle to execute when building your project.

使用此配置包括您希望Gradle在构建项目时执行的lint检查。

Note: When using Android Gradle plugin 3.4.0 and higher, this dependency configuration no longer packages the lint checks in your Android Library projects. To include lint check dependencies in your AAR libraries, use the lintPublish configuration described below.

注意:使用Android Gradle插件3.4.0及更高版本时,此依赖关系配置不再在您的Android库项目中打包lint检查。 要在AAR库中包含lint检查依赖项,请使用下面描述的lintPublish配置。

lintPublish

Use this configuration in Android library projects to include lint checks you want Gradle to compile into a lint.jar file and package in your AAR.

在Android库项目中使用此配置,以包含您希望Gradle在AAR中编译为lint.jar文件和包的lint检查。

This causes projects that consume your AAR to also apply those lint checks. If you were previously using the lintChecks dependency configuration to include lint checks in the published AAR, you need to migrate those dependencies to instead use the lintPublish configuration.

这会导致使用AAR的项目也应用这些lint检查。 如果您之前使用lintChecks依赖关系配置在已发布的AAR中包含lint检查,则需要迁移这些依赖关系,而不是使用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')
}

依赖配置

Dependency configurations

为特定构建变体源集声明依赖项:configurations

The above configurations apply dependencies to all build variants. If you instead want to declare a dependency for only a specific build variant source set or for a testing source set, you must capitalize the configuration name and prefix it with the name of the build variant or testing source set.

以上配置适用于所有构建变体。如果您只想为特定的构建变体源集或测试源集声明依赖项,则必须将配置名称大写,并在其前面加上构建变量或测试源集的名称。

For example, to add an implementation dependency only to your "free" product flavor, it looks like this:

例如,要仅将 implementation 依赖项添加到 "free" 产品风味,它看起来像这样:

freeImplementation 'com.google.firebase:firebase-ads:9.8.0' // Implementation 的基础上加 build variant 的前缀

However, if you want to add a dependency for a variant that combines a product flavor and a build type, then you must initialize theconfiguration name in the configurations block. The following sample adds a runtimeOnly dependency to your "freeDebug" build variant:

但是,如果要为组合 product flavor 和 build type 的变体添加依赖项,则必须在 configurations 块中初始化配置名称。 以下示例将 runtimeOnly 依赖项添加到"freeDebug"构建变体:

configurations {
    //Initializes a placeholder for the freeDebugRuntimeOnly dependency configuration.
    freeDebugRuntimeOnly {} //初始化名称。free:product flavor; Debug:build type
}
dependencies {
    freeDebugRuntimeOnly fileTree(dir: 'libs', include: ['*.jar']) //使用
}

To add implementation dependencies for your local tests and instrumented tests , it looks like this:

要为本地测试和instrumented测试添加 implementation 依赖项,它看起来像这样:

testImplementation 'junit:junit:4.12' // Adds a remote binary dependency only for local tests.
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' // only for the instrumented test APK.

However, certain configurations don't make sense in this situation. For example, because other modules can't depend on androidTest, you get the following warning if you use the androidTestApi configuration:

但是,某些配置在这种情况下没有意义。 例如,因为其他模块不能依赖于androidTest,所以如果使用androidTestApi配置,则会收到以下警告:
WARNING: Configuration 'androidTestApi' is obsolete废弃 and has been replaced with 'androidTestImplementation'

添加注释处理器:annotationProcessor

Add annotation processors

如果将注释处理器添加到编译类路径中,您将看到类似于以下内容的错误消息:

Error: Annotation processors must be explicitly declared[显式声明] now.

要解决此错误,请使用 annotationProcessor 配置依赖关系,为项目添加注释处理器,如 dagger2 可以按如下方式配置:

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

Note: Android Plugin for Gradle 3.0.0+ no longer supports android-apt plugin.

将参数传递给注释处理器:argument

Pass arguments to annotation processors

If you need to pass arguments to an annotation processor, you can do so using the annotationProcessorOptions block in your module's build configuration. For example, if you want to pass primitive data types as key-value pairs, you can use the argument property, as shown below:

如果需要将参数传递给注释处理器,则可以使用模块的构建配置中的 annotationProcessorOptions 块来执行此操作。例如,如果要将原始数据类型作为键值对传递,则可以使用argument属性,如下所示:

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

However, when using Android Gradle plugin 3.2.0 and higher, you need to pass processor arguments that represent files or directories using Gradle's CommandLineArgumentProvider interface.

但是,使用Android Gradle插件3.2.0及更高版本时,需要使用Gradle的 CommandLineArgumentProvider 接口传递表示文件或目录的处理器参数。

Using CommandLineArgumentProvider allows you or the annotation processor author to improve the correctness and performance of incremental and cached clean builds by applying incremental build property type annotations to each argument.

使用 CommandLineArgumentProvider 允许您或注释处理器作者,通过将增量构建属性类型注释应用于每个参数,来提高增量和缓存干净构建的正确性和性能。

For example, the class below implements CommandLineArgumentProvider and annotates each argument for the processor. The sample also uses the Groovy language syntax and is included directly in the module's build.gradle file.

例如,下面的类实现了 CommandLineArgumentProvider 并为处理器注释了每个参数。该示例还使用Groovy语言语法,并直接包含在模块的 build.gradle 文件中。

Note: Typically, annotation processor authors provide either this class or instructions on how to write such a class. That's because each argument needs to specify the correct build property type annotation in order to work as intended.

注意:通常,注释处理器作者提供此类或有关如何编写此类的说明。 这是因为每个参数都需要指定正确的构建属性类型注释才能按预期工作。

CommandLineArgumentProvider 示例

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

After you create a class that implements CommandLineArgumentProvider, you need to initialize and pass it to the Android plugin using the annotationProcessorOptions.compilerArgumentProvider property, as shown below.

在创建实现 CommandLineArgumentProvider 的类之后,需要使用 annotationProcessorOptions.compilerArgumentProvider 属性初始化并将其传递给 Android 插件,如下所示。

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

To learn more about how implementing CommandLineArgumentProvider helps improve build performance, read Caching Java projects

禁用注释处理器错误检查:includeCompileClasspath

Disable the annotation processor error check

If you have dependencies on the compile classpath that include annotation processors you don't need, you can disable the error check by adding the following to your build.gradle file. Keep in mind, the annotation processors you add to the compile classpath are still not added to the processor classpath.

如果您对包含您不需要的注释处理器的 compile classpath 具有依赖性,则可以通过将以下内容添加到build.gradle文件来禁用错误检查。 请记住,添加到 compile classpath 的注释处理器仍未添加到 processor classpath 中。

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

If you experience issues after migrating your project's annotation processors to the processor classpath, you can allow annotation processors on the compile classpath by setting includeCompileClasspath to true. However, setting this property to true is not recommended, and the option to do so will be removed in a future update of the Android plugin.

如果在将项目的注释处理器迁移到 processor classpath 后遇到问题,则可以通过将 includeCompileClasspath 设置为 true 来允许编译类路径上的注释处理器。 但是,建议不要将此属性设置为 true,并且在将来的 Android 插件更新中将删除执行此操作的选项。

排除传递依赖项:exclude

Exclude transitive dependencies

随着应用程序的增长,它可能包含许多依赖项,包括直接依赖项和传递依赖项(应用程序导入的库所依赖的库)。 要排除不再需要的传递依赖项,可以使用 exclude 关键字,如下所示:

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

如果您需要从 tests 中排除某些传递依赖项,则上面显示的代码示例可能无法按预期工作。这是因为 test configuration 扩展了模块的 implementation 配置。 也就是说,当Gradle解析配置时,它始终包含 implementation 依赖性。

因此,要从 tests 中排除传递依赖性,必须在 execution 时执行此操作,如下所示:

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

Note: You can still use the exclude keyword in the dependencies block as shown in the original code sample from the Exclude dependencies section to omit transitive dependencies that are specific to the test configuration and are not included in other configurations.

注意:您仍然可以在依赖项块中使用exclude关键字,如“排除依赖项”部分中的原始代码示例所示,以省略特定于测试配置但未包含在其他配置中的传递依赖项。

使用变体感知依赖关系管理

Use variant-aware dependency management

Android plugin 3.0.0 and higher include a new dependency mechanism that automatically matches variants when consuming a library. This means an app's debug variant automatically consumes a library's debug variant, and so on. It also works when using flavors — an app's freeDebug variant will consume a library's freeDebug variant.

Android插件3.0.0及更高版本包含一个新的依赖机制,可以在使用库时自动匹配变体。这意味着应用程序的debug变体会自动使用库的debug变体,依此类推。它在使用flavor时也有效 - 应用程序的freeDebug变体将使用库的freeDebug变体。

In order for the plugin to accurately match variants, you need to provide matching fallbacks for instances where a direct match is not possible. Consider if your app configures a build type called "staging", but one of its library dependencies does not. When the plugin tries to build the "staging" version of your app, it won't know which version of the library to use, and you'll see an error message similar to the following:

为了使插件准确匹配变体,您需要为无法直接匹配的实例提供 matching fallbacks。假如你的应用//程序配置了一个名为“staging”的构建类型,但其中一个库依赖项却没有。当插件尝试构建应用程序的“staging”版本时,它将不知道要使用的库版本,您将看到类似于以下内容的错误消息:

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

The plugin includes DSL elements to help you control how Gradle should resolve situations in which a direct variant match between an app and a dependency is not possible. Consult the table below to determine which DSL property you should use to resolve certain build errors related to variant-aware dependency matching.

该插件包含DSL元素,可帮助您控制Gradle应如何解决,无法在应用程序和依赖项之间进行直接变体匹配的情况。请参阅下表以确定应使用哪个DSL属性来解决与变体感知依赖项匹配相关的某些构建错误。

app 包含依赖库不包含的 buildTypes:matchingFallbacks

Your app includes a build type that a library dependency does not.

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.

指定插件在依赖项不包含 staging 构建类型时,应尝试使用的回退构建类型的排序列表。您可以根据需要指定尽可能多的回退,并且插件会选择依赖项中可用的第一个构建类型。

For example, your app includes a "staging" build type, but a dependency includes only a "debug" and "release" build type.

例如,您的应用程序包含“staging”构建类型,但依赖项仅包括“debug”和“release”构建类型。

Use matchingFallbacks to specify alternative matches for a given build type, as shown below:

使用 matchingFallbacks 为给定的构建类型指定替代匹配,如下所示:

// In the app's build.gradle file.
android {
    buildTypes {
        debug {...}
        release {...}//由于依赖项已包含此构建类型,因此您无需在此处提供 matchingFallbacks
        stage {
            matchingFallbacks = ['debug', 'qa'] //指定当依赖项不包含此构建类型时,应尝试使用的构建类型的排序列表
        }
    }
}

Note that there is no issue when a library dependency includes a build type that your app does not. That's because the plugin simply never requests that build type from the dependency.

请注意,当库依赖项包含您的应用程序不包含的构建类型时,没有问题。 那是因为插件根本不会从依赖项中请求构建类型。

app 包含依赖库不包含的 productFlavors:matchingFallbacks

For a given flavor dimension that exists in both the app and its library dependency, your app includes flavors that the library does not.

For example, both your app and its library dependencies include a "tier" flavor dimension. However, the "tier" dimension in the app includes "free" and "paid" flavors, but a dependency includes only "demo" and "paid" flavors for the same dimension.

例如,您的 app 及其库依赖项都包含“tier”风格维度。但是,应用程序中的“tier”维度包括 "free" and "paid" 风格,但依赖项仅包括相同维度的 "demo" and "paid” 风格。

Use matchingFallbacks to specify alternative matches for theapp's "free" product flavor, as shown below:

使用matchingFallbacks为应用程序的“free”产品风格指定替代匹配,如下所示:

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.

不要在defaultConfig块中配置matchingFallbacks。相反,您必须在productFlavors块中指定给定 roduct Flavors 的回退,如下所示。

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.

指定当依赖项的匹配 dimension 不包含“free”风格时,插件应尝试使用的后备风格的排序列表。您可以根据需要指定尽可能多的回退,并且插件会选择依赖项的“tier”维度中可用的第一个flavor。

// In the app's build.gradle file.
android {
    defaultConfig{...} //不要在defaultConfig块中配置matchingFallbacks,而要在具体的productFlavors中配置
    flavorDimensions 'tier' //风格维度
    productFlavors { //产品风格
        paid {
            dimension 'tier' //由于依赖库中风格维度tier下也有此productFlavors,因此无需提供matchingFallbacks
        }
        free {
            dimension 'tier' //由于依赖库中风格维度tier下没有此productFlavors,因此需要提供matchingFallbacks
            matchingFallbacks = ['demo', 'trial'] //排序列表中指定的是【库】中可能有的productFlavors
        }
    }
}

Note that, for a given flavor dimension that exists in both the app and its library dependencies, there is no issue when a library includes a product flavor that your app does not. That's because the plugin simply never requests that flavor from the dependency.

请注意,对于应用程序及其库依赖项中存在的给定风味维度,当库包含app不包含的 product flavor 时,不会出现问题。 那是因为插件根本不会从依赖中请求那种flavors。

依赖库包括 app 不具有的 flavorDimensions:missingDimensionStrategy

A library dependency includes a flavor dimension that your app does not.

For example, a library dependency includes flavors for a "minApi" dimension, but your app includes flavors for only the "tier" dimension. So, when you want to build the "freeDebug" version of your app, the plugin doesn't know whether to use the "minApi23Debug" or "minApi18Debug" version of the dependency.

例如,库依赖项包括“minApi”维度的风格,但您的app仅包含“tier”维度的风格。因此,当您想要构建app的“freeDebug”版本时,该插件不知道是否使用依赖项的“minApi23Debug”或“minApi18Debug”版本。

Use missingDimensionStrategy in the defaultConfig block to specify the default flavor the plugin should select from each missing dimension, as shown in the sample below. You can also override your selections in the productFlavors block, so each flavor can specify a different matching strategy for a missing dimension.

在defaultConfig块中使用missingDimensionStrategy指定插件应从每个缺少的维度中选择的默认flavor,如下面的示例所示。 您还可以覆盖productFlavors块中的选择,因此每种flavor都可以为缺少的维度指定不同的匹配策略。

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.

指定插件应尝试从给定维度使用的排序样式列表。 以下告诉插件,当遇到包含“minApi”维度的依赖项时,它应该选择“minApi18”风格。您可以包含其他flavor名称,以提供维度的回退的排序列表。

You should specify a missingDimensionStrategy property for each dimension that exists in a local dependency but not in your app.

您应该为本地依赖项中存在但不在应用程序中的每个维度指定missingDimensionStrategy属性。

You can override the default selection at the product flavor level by configuring another missingDimensionStrategy property for the "minApi" dimension.

您可以通过为“minApi”维度配置另一个missingDimensionStrategy属性来覆盖产品风格级别的默认选择。

// In the app's build.gradle file.
android {
    defaultConfig{
        missingDimensionStrategy 'minApi', 'minApi18', 'minApi23' //优先使用依赖库 minApi 下的 minApi18
        missingDimensionStrategy 'abi', 'x86', 'arm64' //优先使用依赖库 abi 下的 x86
    }
    flavorDimensions 'tier'
    productFlavors {
        free {
            dimension 'tier'
            missingDimensionStrategy 'minApi', 'minApi23', 'minApi18' //覆盖默认配置
        }
        paid {...}
    }
}

Note that there is no issue when your app includes a flavor dimension that a library dependency does not. That's because the plugin matches flavors of only the dimensions that exist in the dependency. For example, if a dependency did not include a dimension for ABIs, the "freeX86Debug" version of your app would simply use the "freeDebug" version of the dependency.

请注意,当您的app包含库依赖项不包含的flavor dimension时,不会出现问题。那是因为插件只匹配依赖项中存在的维度。 例如,如果依赖项不包含ABI的维度,则app的“freeX86Debug”版本将仅使用依赖项的“freeDebug”版本。

远程存储库

Remote repositories

When your dependency is something other than a local library or file tree, Gradle looks for the files in whichever online repositories are specified in the repositories block of your build.gradle file.

当您的依赖项不是本地库或文件树时,Gradle将在build.gradle文件的repositories块中指定的任何联机存储库中查找文件。

The order in which you list each repository determines the order in which Gradle searches the repositories for each project dependency. For example, if a dependency is available from both repository A and B, and you list A first, Gradle downloads the dependency from repository A.

列出每个存储库的顺序决定了Gradle在每个项目依赖项中搜索存储库的顺序。例如,如果存储库A和B都需要使用一个依赖项,并且您首先列出A,则Gradle将从存储库A下载依赖项。

By default, new Android Studio projects specifies Google's Maven repository and JCenter as repository locations in the project's top-level build.gradle file, as shown below:

默认情况下,新建的Android Studio项目将Google的Maven存储库和JCenter指定为项目顶级build.gradle文件中的存储库位置,如下所示:

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

If you want something from the Maven central repository, then add mavenCentral(), or for a local repository use mavenLocal():

如果你想要 Maven central 存储库中的东西,那么添加 mavenCentral(),或者对于本地存储库使用mavenLocal():

allprojects {
    repositories {
        google()
        jcenter()
        mavenCentral() //maven中央存储库
        mavenLocal()  //maven本地存储库
    }
}

Or you can declare specific Maven or Ivy repositories as follows:

或者,您可以按如下方式声明特定的Maven或Ivy存储库:

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

For more information, see the Gradle Repositories guide.

谷歌的Maven存储库

Google's Maven repository

The most recent versions of the following Android libraries are available from Google's Maven repository:

You can see all available artifacts at Google's Maven repository index (see below for programmatic access).

添加Google的Maven中提供的library

To add one of these libraries to your build, include Google's Maven repository in your top-level build.gradle file:

要在构建中添加其中一个库,请在顶级build.gradle文件中包含Google的Maven存储库:

allprojects {
    repositories {
        google() //如果您使用的Gradle版本低于4.1,则必须使用【maven { url 'https://maven.google.com'}】
    }
}

然后将所需的库添加到模块的 dependencies 块中。 例如,appcompat库如下所示:

implementation 'com.android.support:appcompat-v7:27.1.1'

However, if you're trying to use an older version of the above libraries and your dependency fails, then it's not available in the Maven repository and you must instead get the library from the offline repository.

但是,如果您尝试使用上述库的旧版本,并且您的依赖项失败,那么它在Maven存储库中不可用,您必须从offline存储库获取库。

程序化访问

[Programmatic access]

要以编程方式访问Google的Maven工件,您可以从 maven.google.com/master-index.xml 获取工件组的XML列表。然后,对于任何 group,您可以在以下位置查看其 library 的名称和版本:

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

例如,android.arch.lifecycle组中的库列在maven.google.com/android/arch/lifecycle/group-index.xml

您还可以在以下位置下载POM和JAR文件:

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

例如:maven.google.com/android/arch/lifecycle/compiler/1.0.0/compiler-1.0.0.pom

SDK Manager 中的离线存储库

Offline repository from SDK Manager

For libraries not available from the Google Maven repository (usually older library versions), you must download the offline Google Repository package from the SDK Manager. Then you can add these libraries to your dependencies block as usual.

对于Google Maven存储库不可用的库(通常是较旧的库版本),您必须从SDK Manager下载脱机Google Repository包。然后,您可以像平常使用的方式一样将这些库添加到依赖项块中。

脱机库保存在 android_sdk/extras/ 中。

依赖关系

依赖顺序

Dependency order

The order in which you list your dependencies indicates the priority for each: the first library is higher priority than the second, the second is higher priority than the third, and so on. This order is important in the event that resources are merged or manifest elements are merged into your app from the libraries.

列出依赖项的顺序表示每个依赖项的优先级:第一个库的优先级高于第二个库,第二个库的优先级高于第三个库,依此类推。 在合并资源或将清单元素从库合并到您的应用程序中时,此顺序非常重要。

例如,如果您的项目声明以下内容:

  • 按顺序依赖 LIB_A 和 LIB_B
  • 并且 LIB_A 按顺序依赖于 LIB_C 和 LIB_D
  • LIB_B 也依赖于 LIB_C

然后,flat 依赖顺序如下:LIB_A LIB_D LIB_B LIB_C
这可以确保 LIB_A 和 LIB_B 都可以覆盖 LIB_C;LIB_D的优先级仍然高于 LIB_B,因为 LIB_A 的优先级高于 LIB_B。

其实这个顺序并不是特别好理解

For more information about how manifests from different project sources/dependencies are merged, see Merge multiple manifest files.

查看依赖关系树

[View the dependency tree]

Some direct dependencies may have dependencies of their own. These are called transitive dependencies. Rather than requiring you to manually declare each transitive dependency, Gradle automatically gathers and adds them for you.

某些直接依赖关系可能具有自己的依赖关系。 这些被称为传递依赖。Gradle不会要求您手动声明每个传递依赖项,而是自动收集并添加它们。

To visualize both the direct and transitive dependencies of your project, the Android plugin for Gradle provides a Gradle task that generates a dependency tree for each build variant and testing source set.

为了可视化项目的直接依赖性和传递性依赖性,Gradle的Android插件提供了一个Gradle任务,该任务为每个构建变体和测试源集生成依赖关系树。

要运行任务,请执行以下操作:

  • 选择 View > Tool Windows > Gradle(或直接单击工具窗口栏中的“Gradle”窗体)。
  • 展开 AppName > Tasks > android > androidDependencies。双击执行Gradle任务后,应该会打开 Run 窗口以显示输出。

Gradle 翻译 build dependencies 依赖 MD 随笔 第1张

The following sample output shows the dependency tree for the debug build variant, and includes the local library module dependency and remote dependency from the previous example.

以下示例输出显示了调试版本构建变体的依赖关系树,并包含上一示例中的本地库模块依赖关系和远程依赖关系。

Executing tasks: [androidDependencies]
:app:androidDependencies
debug
+--- MyApp:mylibrary:unspecified
|    \--- com.android.support:appcompat-v7:27.1.1
|         +--- com.android.support:animated-vector-drawable:27.1.1
|         |    \--- com.android.support:support-vector-drawable:27.1.1
|         |         \--- com.android.support:support-v4:27.1.1
|         |              \--- LOCAL: internal_impl-27.1.1.jar
|         +--- com.android.support:support-v4:27.1.1
|         |    \--- LOCAL: internal_impl-27.1.1.jar
|         \--- com.android.support:support-vector-drawable:27.1.1
|              \--- com.android.support:support-v4:27.1.1
|                   \--- LOCAL: internal_impl-27.1.1.jar
\--- com.android.support:appcompat-v7:27.1.1
     +--- com.android.support:animated-vector-drawable:27.1.1
     |    \--- com.android.support:support-vector-drawable:27.1.1
     |         \--- com.android.support:support-v4:27.1.1
     |              \--- LOCAL: internal_impl-27.1.1.jar
     +--- com.android.support:support-v4:27.1.1
     |    \--- LOCAL: internal_impl-27.1.1.jar
     \--- com.android.support:support-vector-drawable:27.1.1
          \--- com.android.support:support-v4:27.1.1
               \--- LOCAL: internal_impl-27.1.1.jar
...

For more information about managing dependencies in Gradle, see Dependency management basics in the Gradle User Guide.

解决重复的类错误

[Resolve duplicate class errors]

When you add multiple dependencies to your app project, those direct and transitive dependencies might conflict with one another. The Android Gradle Plugin tries to resolve these conflicts gracefully, but some conflicts may lead to compile time or runtime errors.

当您向应用程序项目添加多个依赖项时,这些直接和传递依赖项可能会相互冲突,Android Gradle Plugin尝试优雅地解决这些冲突,但是一些冲突可能导致编译时或运行时错误。

To help you investigate which dependencies are contributing to errors, inspect your app's dependency tree and look for dependencies that appear more than once or with conflicting versions.

为了帮助您调查哪些依赖项导致错误,请检查应用程序的依赖关系树,并查找出现多次或存在冲突版本的依赖项。

If you can't easily identify the duplicate dependency, try using Android Studio's UI to search for dependencies that include the duplicate class as follows:

如果您无法轻松识别重复的依赖项,请尝试使用Android Studio的UI搜索包含重复类的依赖项,如下所示:

  • Select Navigate > Class from the menu bar.
  • In the pop-up search dialog, make sure that the box next to Include non-project items is checked.
  • Type键入 the name of the class that appears in the build error.
  • Inspect检查 the results for the dependencies that include the class.

Gradle 翻译 build dependencies 依赖 MD 随笔 第2张

The following sections describe the different types of dependency resolution errors you may encounter and how to fix them.

以下部分描述了您可能遇到的不同类型的依赖项解析错误,以及如何解决这些错误。

修复重复class错误

Fix duplicate class errors

例如,如果一个类在 runtime classpath 上出现多次,则会出现类似以下的错误:

Program type already present com.example.MyClass

此错误通常会在下列情况之一时发生:

  • A binary dependency includes a library that your app also includes as a direct dependency.

For example, your app declares a direct dependency on Library A and Library B, but Library A already includes Library B in its binary.
To resolve this issue, remove Library B as a direct dependency.

  • Your app has a local binary dependency and a remote binary dependency on the same library.

To resolve this issue, remove one of the binary dependencies.

修复classpaths之间的冲突

Fix conflicts between classpaths

When Gradle resolves the compile classpath, it first resolves the runtime classpath and uses the result to determine确定 what versions of dependencies should be added to the compile classpath. In other words, the runtime classpath determines确定 the required version numbers for identical相同 dependencies on downstream下游 classpaths.

当Gradle解析编译类路径时,它首先解析运行时类路径,并使用此结果来确定应将哪些版本的依赖项添加到编译类路径中。换句话说,运行时类路径确定下游类路径上相同依赖项所需的版本号。

Your app's runtime classpath also determines the version numbers that Gradle requires for matching dependencies in the runtime classpath for the app's test APK. The hierarchy of classpaths is described in figure 1.

您的应用程序的运行时类路径还确定了Gradle在应用程序测试APK的运行时类路径中匹配依赖项所需的版本号。类路径的层次结构如图1所示。

Gradle 翻译 build dependencies 依赖 MD 随笔 第3张

Figure 1. Version numbers of dependencies that appear across multiple classpaths must match according to this hierarchy. 多个类路径中出现的依赖关系的版本号必须根据此层次结构匹配。

A conflict where different versions of the same dependency appears across multiple classpaths migh occur when, for example, your app includes a version of a dependency using the implementation dependency configuration and a library module includes a different version of the dependency using the runtimeOnly configuration.

例如,当您的app包含使用implementation依赖项配置的依赖项版本,并且库模块包含使用runtimeOnly配置的不同版本的依赖项时,会出现多个类路径中出现相同依赖关系的不同版本的冲突。

When resolving dependencies on your runtime and compile time classpaths, Android Gradle plugin 3.3.0 and higher attempt to automatically fix certain downstream version conflicts. For example, if the runtime classpath includes Library A version 2.0 and the compile classpath includes Library A version 1.0, the plugin automatically updates the dependency on the compile classpath to Library A version 2.0 to avoid errors.

在解析运行时和编译时类路径的依赖关系时,Android Gradle插件3.3.0及更高版本会尝试自动修复某些下游版本冲突。例如,如果运行时类路径包含库A版本2.0并且编译类路径包含库A版本1.0,则插件会自动将编译类路径的依赖性更新为库A版本2.0以避免错误。

However, if the runtime classpath includes Library A version 1.0 and the compile classpath includes Library A version 2.0, the plugin does not downgrade the dependency on the compile classpath to Library A version 1.0, and you still get an error similar to the following:

但是,如果运行时类路径包含库A版本1.0且编译类路径包含库A版本2.0,则插件不会将编译类路径上的依赖项降级为库A版本1.0,并且仍会出现类似于以下内容的错误:

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.

要解决此问题,请执行以下操作之一:

  • Include the desired version of the dependency as an api dependency to your library module. That is, only your library module declares the dependency, but the app module will also have access to its API, transitively.

    将所需的依赖项版本作为 api 依赖项包含在库模块中。也就是说,只有你的库模块声明了依赖关系,但 app 模块也可以传递访问它的API。

  • Alternatively, you can declare the dependency in both modules, but you should make sure that each module uses the same version of the dependency. Consider configuring project-wide properties to ensure versions of each dependency remain consistent保持一致 throughout your project.

    或者,您可以在两个模块中声明依赖项,但应确保每个模块使用相同版本的依赖项。 考虑配置项目范围的属性,以确保每个依赖项的版本在整个项目中保持一致。

应用自定义构建逻辑

[Apply custom build logic]

以下内容实际工作中还没有使用过

This section describes advanced topics that are useful when you want to extend the Android Gradle plugin or write your own plugin.

本节介绍了在扩展 Android Gradle 插件或编写自己的插件时非常有用的高级主题。

将变体依赖项发布到自定义逻辑

Publish variant dependencies to custom logic

A library can have functionalities that other projects or sub-projects might want to use. Publishing a library is the process by which the library is made available to its consumers. Libraries can control which dependencies its consumers have access to at compile time and runtime.

库中可以具有其他项目或子项目可能想要使用的功能。发布库是向其使用者提供库的过程。库可以控制其消费者在编译时和运行时可以访问的依赖项。

There are two separate configurations that hold the transitive dependencies of each classpath which must be used by consumers to consume the library as described below:

有两个独立的配置,用以保存每个类路径的传递依赖关系,消费者必须使用它们来使用库,如下所述:

  • variant_nameApiElements: This configuration holds the transitive dependencies that are available to consumers at compile time.
  • variant_nameRuntimeElements: This configuration holds the transitive dependencies that are available to consumers at runtime.

To learn more about the relationships between the different configurations, go to The Java Library plugin configurations

自定义依赖解析策略

[Custom dependency resolution strategies]

A project may include a dependency on two different versions of the same library which can lead to dependency conflicts. For example, if your project depends on version 1 of module A and version 2 of module B, and module A transitively depends on version 3 of module B, there arises a dependency version conflict.

项目可能包括对同一库的两个不同版本的依赖,这可能导致依赖性冲突。例如,如果您的项目依赖于模块A的版本1和模块B的版本2,并且模块A transitively 地依赖于模块B的版本3,则会出现依赖版本冲突。

To resolve this conflict, the Android Gradle Plugin uses the following dependency resolution strategy: when the plugin detects that different versions of the same module are in the dependency graph, by default, it chooses the one with the highest version number.

为解决此冲突,Android Gradle Plugin使用以下依赖项解析策略:当插件检测到同一模块的不同版本在依赖关系图中时,默认情况下,它会选择版本号最高的版本。

However, this strategy might not always work as you intend. To customize the dependency resolution strategy, use the following configurations to resolve specific dependencies of a variant that are needed for your task:

但是,此策略可能并不总是按您的意愿运行。要自定义依赖项解析策略,请使用以下配置来解析任务所需的变体的特定依赖项:

  • variant_nameCompileClasspath:This configuration contains the resolution strategy for a given variant’s compile classpath.
  • variant_nameRuntimeClasspath:This configuration contains the resolution strategy for a given variant’s runtime classpath.

The Android Gradle plugin includes getters that you can use to access the configuration objects of each variant. Thus, you can use the variant API to query the dependency resolution as shown in the example below:

Android Gradle插件包含可用于访问每个变体的配置对象的getter方法。 因此,您可以使用 variant API 来查询依赖项解析,如下例所示:

精简版

android {
    applicationVariants.all { variant ->
        variant.getCompileConfiguration().resolutionStrategy {...} //返回一个variant的compile configuration objects
        variant.getRuntimeConfiguration().resolutionStrategy  {...}
        variant.getAnnotationProcessorConfiguration().resolutionStrategy {...}
    }
}

完整版

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

最后更新日期:August 16, 2018.

2019-5-12

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄