「这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战」。
- Gradle、Gradle Plugin Version和Android SDK Tools Version有啥关系?
- compileSdkVersion、minSdkVersion和targetSdkVersion有啥区别?
- implementation、api和compileOnly是干啥用的?
本篇旨在针对以上三个问题做出充分的解释。
Gradle、Gradle Plugin Version和Android SDK Tools Version
Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化建构工具。Gradle 构建脚本使用的是 Groovy 或 Kotlin 的特定领域语言来编写的[2],而不是传统的XML。
简单来说Gradle是一套软件,用来帮助我们是想软件项目的自动化构建。Gradle也是Android Studio推荐使用构建工具,但是我们在使用Android Studio开发时,通常不直接使用Gradle进行编译,而是使用Gradle插件提供编译支持。可以简单理解为Gradle插件是为Android Studio能够使用Gradle而提供的插件,Gradle插件提供了构建和测试Android项目所需要的一切,Gradle会为Gradle插件提供支持,但是他们彼此版本独立。Gradle插件通常会跟Android Studio同步更新。
Gradle、Gradle Plugin Version和Android SDK Tools Version关系如下:
-
三者版本是完全独立维护,如:
- Gradle Version 最新版(21年3月)—— 6.5;
- 可以在Android Studio项目的gradle/wrappe/gradle-wrapper.properties中配置gradle版本。
- Gradle Android插件版本,最新 —— 4.1.1;
- 在根目录build.gradle中配置classpath
"com.android.tools.build:gradle:4.1.1"
- 在根目录build.gradle中配置classpath
- SDK Tools Version: android SDK组件,需要与compileSdkVersion搭配;
- 在module的build.gradle中配置(Gradle插件3.0.0版本以上可以不用配置,会自动适配,但也可以手动指定)
- Gradle Version 最新版(21年3月)—— 6.5;
-
Gradle 对Gradle Plugin 提供支持;
-
Gradle Plugin 对 SDK Tools提供支持;
他们的对应关系如下:
| Gradle android插件版本 | 所需的 Gradle 版本 | Android SDK Tools Version |
|---|---|---|
| 1.0.0 - 1.1.3 | 2.2.1 - 2.3 | |
| 1.2.0 - 1.3.1 | 2.2.1 - 2.9 | |
| 1.5.0 | 2.2.1 - 2.13 | |
| 2.0.0 - 2.1.2 | 2.10 - 2.13 | 21.1.1+ |
| 2.1.3 - 2.2.3 | 2.14.1+ | 23.0.2+ |
| 2.3.0+ | 3.3+ | 25.0.0+ |
| 3.0.0+ | 4.1+ | 26.0.2+,不在需要指定版本,插件会默认使用最低要求版本 |
| 3.1.0+ | 4.4+ | 27.0.3+ |
| 3.2.0 - 3.2.1 | 4.6+ | |
| 3.3.0 - 3.3.3 | 4.10.1+ | |
| 3.4.0 - 3.4.3 | 5.1.1+ | |
| 3.5.0 - 3.5.4 | 5.4.1+ | |
| 3.6.0 - 3.6.4 | 5.6.4+ | |
| 4.0.0+ | 6.1.1+ | |
| 4.1.0+ | 6.5+ |
使用时,需要在Module的build.gradle中声明所需要的插件。
apply plugin: 'com.android.application'
或
apply plugin: 'com.android.library'
一个是应用模块需要声明的插件,一个是依赖模块需要声明的插件(不可同时声明两种插件)。
Gradle Wrapper
上面提到了Android Sutido是使用Gradle插件进行项目编译的,但是需要Gradle为Gradle插件提供支持,那么如何保证Gradle插件与Gradle是兼容的呢?这就是Gradle Wrapper的作用。
Android Studio项目中通常有一个gradle/wrapper文件夹,其中包含gradle-wrapper.jar和一个properites配置文件,配置文件决定了使用哪一版本的gradle。
gradle wrapper的作用原理是这样,当执行gradlew xx任务来构建项目时,会自动判断指定gradle版本是否被安装,如果没有则先安装gradle后在执行构建任务,从而保证了Gradle插件与Gradle的版本对齐。当然也可以不使用Gradel Wrapper而使用手动更新Gradle版本的方式,Wrapper的作用是减少了繁琐手动更新的工作。
如果当前项目使用的不是最新的Gradle版本,Android Studio会给出提示并建议更新Gradle版本。其原理就是更新wrapper配置文件中的版本号并触发一次构建任务。
compileSdkVersion、minSdkVersion和targetSdkVersion
- compileSdkVersion顾名思义,设置使用哪个SDK版本编译你的APK,如果使用的新的API需要使用对应的compileSdkVersion版本。
- 不会改变应用运行时的行为。
- 允许使用新的API进行编码。
- 编译时错误提示和警告,提示启用API等。
- 建议使用最新的SDK进行编译。
- minSdkVersion,应用运行时的最低SDK要求。
- 在低于minSdkVersion的设备上应用不可被安装。
- 使用高于minSdkVersion的API时会警告你。
- 不同的第三方库中的minSdkVersion不同,注意应该使用最高的minSdkVersion。如:目前三个库的minSdkVersion分辨是4,7和9,那么应用的minSdkVersion应该设置为9。(有办法避免此限制,但不建议使用)
- 可以用目前Android 设备分布统计,来作为minSdkVersion的设置参考。
- targetSdkVersion,是 Android 提供向前兼容的主要依据,在应用的 targetSdkVersion 没有更新之前系统不会应用最新的行为变化。
- 例如:Android 6.0以后引入了动态权限机制,当compileSdkVersion设置为23+之后我们就可以在代码中使用此功能。但是当我们代码中未进行动态权限注册,而target设置为22时,运行在Android6.0的设备上不会有任何问题。但是当target设置为23,运行在Android 6.0设备上就会报错。
- 随着Android版本的升级总会引入一些新的功能,如果你不需要引入这些功能,可以不用升级target版本。但是还是建议将target版本更新为最新的SDK版本。
- 不要在未做充分测试的情况下升级target版本。
implementation、api和compileOnly
这三个是在添加依赖时需要使用的,除了常用的implementation还有api、compileOnly甚至compile等,不同的关键字对应不同的依赖导入规则和适用场景。
具体说明如下:
在
dependencies代码块内,您可以从多种不同的依赖项配置中选择其一(如上面所示的implementation)来声明库依赖项。每种依赖项配置都向 Gradle 提供了有关如何使用该依赖项的不同说明。下表介绍了您可以对 Android 项目中的依赖项使用的各种配置。此表还将这些配置与自 Android Gradle 插件 3.0.0 起弃用的配置进行了比较。
配置 行为 implementationGradle 会将依赖项添加到编译类路径,并将依赖项打包到构建输出。不过,当您的模块配置 implementation依赖项时,会让 Gradle 了解您不希望该模块在编译时将该依赖项泄露给其他模块。也就是说,其他模块只有在运行时才能使用该依赖项。使用此依赖项配置代替api或compile(已弃用)可以显著缩短构建时间,因为这样可以减少构建系统需要重新编译的模块数。例如,如果implementation依赖项更改了其 API,Gradle 只会重新编译该依赖项以及直接依赖于它的模块。大多数应用和测试模块都应使用此配置。apiGradle 会将依赖项添加到编译类路径和构建输出。当一个模块包含 api依赖项时,会让 Gradle 了解该模块要以传递方式将该依赖项导出到其他模块,以便这些模块在运行时和编译时都可以使用该依赖项。此配置的行为类似于compile(现已弃用),但使用它时应格外小心,只能对您需要以传递方式导出到其他上游消费者的依赖项使用它。这是因为,如果api依赖项更改了其外部 API,Gradle 会在编译时重新编译所有有权访问该依赖项的模块。因此,拥有大量的api依赖项会显著增加构建时间。除非要将依赖项的 API 公开给单独的模块,否则库模块应改用implementation依赖项。compileOnlyGradle 只会将依赖项添加到编译类路径(也就是说,不会将其添加到构建输出)。如果您创建 Android 模块时在编译期间需要相应依赖项,但它在运行时可有可无,此配置会很有用。如果您使用此配置,那么您的库模块必须包含一个运行时条件,用于检查是否提供了相应依赖项,然后适当地改变该模块的行为,以使该模块在未提供相应依赖项的情况下仍可正常运行。这样做不会添加不重要的瞬时依赖项,因而有助于减小最终 APK 的大小。此配置的行为类似于 provided(现已弃用)。注意:您不能将compileOnly配置与 AAR 依赖项配合使用。runtimeOnlyGradle 只会将依赖项添加到构建输出,以便在运行时使用。也就是说,不会将其添加到编译类路径。此配置的行为类似于 apk(现已弃用)。annotationProcessor如需添加对作为注解处理器的库的依赖,您必须使用 annotationProcessor配置将其添加到注解处理器的类路径。这是因为,使用此配置可以将编译类路径与注释处理器类路径分开,从而提高构建性能。如果 Gradle 在编译类路径上找到注释处理器,则会禁用避免编译功能,这样会对构建时间产生负面影响(Gradle 5.0 及更高版本会忽略在编译类路径上找到的注释处理器)。如果 JAR 文件包含以下文件,则 Android Gradle 插件会假定依赖项是注释处理器:META-INF/services/javax.annotation.processing.Processor。 如果插件检测到编译类路径上包含注解处理器,则会产生构建错误。注意:Kotlin 项目应使用 kapt 声明注解处理器依赖项。lintChecks使用此配置可以添加您希望 Gradle 在构建项目时执行的 lint 检查。注意:使用 Android Gradle 插件 3.4.0 及更高版本时,此依赖项配置不再将 lint 检查打包在 Android 库项目中。如需将 lint 检查依赖项包含在 AAR 库中,请使用下面介绍的 lintPublish配置。lintPublish在 Android 库项目中使用此配置可以添加您希望 Gradle 编译成 lint.jar文件并打包在 AAR 中的 lint 检查。这会使得使用 AAR 的项目也应用这些 lint 检查。如果您之前使用lintChecks依赖项配置将 lint 检查添加到已发布的 AAR 中,则需要迁移这些依赖项以改用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') }已弃用的配置(在 AGP 1.0–4.2 中可用):
配置 行为 apkGradle 只会将依赖项添加到构建输出,以便在运行时使用。也就是说,不会将其添加到编译类路径。 compileGradle 会将依赖项添加到编译类路径和构建输出。 将依赖项导出到其他模块。 providedGradle 只会将依赖项添加到编译类路径(也就是说,不会将其添加到构建输出)。 以上所有配置会将依赖项应用于所有构建变体。如果您只想为特定的构建变体源代码集或测试源代码集声明依赖项,则必须将配置名称的首字母大写,并在其前面加上构建变体或测试源代码集的名称作为前缀。
常用的也就以下三个,简单来说:
| 配置 | 说明 | |
|---|---|---|
implementation | 1.可以编译、打包到输出。 2.编译时,其他模块不可引用。 3.运行时其他模块可用。 | 使用此配置代替api可减少编译时间 |
api | 1.可以编译、打包到输出。 2.编译时,其他模块可引用。 3.运行时其他模块可用。 | 依赖传递,Gradle 会在编译时重新 编译所有有权访问该依赖项的模块 |
compileOnly | 1.只在编译时可用。 2.不会打包到输出。 | 此配置的行为类似于 provided(现已弃用 |