说明
本文主要介绍和 Gradle 关系密切相对不容易理解的配置, 偏重概念介绍部分内容是 Android 特有的(例如 ProductFlavor), 其他内容则是所有 Gradle 工程都相同或类似的知识
对于一些常规且相对简单的配置项, 例如签名配置 SigningConfig, 不做具体介绍而部分比较复杂且不太常用的内容, 例如 Manifest 的具体合并规则, 只做简单说明, 并给出深入学习的相关链接, 读者可自行阅读
文章主要基于 Gradle V3.3 + Android Gradle Plugin V2.3 + Android Studio 2.3, 在后续版本升级后部分内容可能会改变
文中的内容, 有些是根据源码分析得到, 有些是参考了官方文档, 还有些参考了网上的文章如有不正确的地方, 欢迎指正
关于 Gradle DSL 的语法原理和开发相关知识, 可参考我的另一篇文章
Gradle 开发快速入门 DSL 语法原理与常用 API 介绍
http://www.paincker.com/gradle-develop-basics
基本问题
开始看本文前, 可以思考下面这些关于 Gradle 的基本问题文中会对这些问题进行解释
settings.gradle 有什么作用?
repositories {}语句块的作用?
buildscript 和 allprojects 的区别?
ProductFlavor 和 BuildType 的区别?
依赖冲突的原因和常见解决思路?
classpath 'com.android.tools.build:gradle:2.2.3'
, 有什么作用?
gradle/wrapper/gradle-wrapper.properties
中的这句有什么作用?
distributionUrl=https://services.gradle.org/distributions/gradle-2.14.1-all.zip
命令行中, gradle assemblegradle assembleDebuggradle build 的关系?
Android Studio 环境下, Gradle Sync 操作做了什么工作?
Gradle
Gradle 是一个基于 Groovy 语言的强大的构建系统, Groovy 则是在 Java 基础上扩展的运行在 JVM 上的一种脚本语言
通过丰富的插件扩展, Gradle 可以支持 JavaJavaWebGroovyAndroid 等工程的编译, 同时可以很方便的从 MavenAnt 等迁移过来
C 系列语言也有相应的 Gradle 插件, 但 Gradle 支持最好的还是 Java 系列语言
Gradle 也是一个命令行可执行程序, 可从官网下载 Gradle, 可执行文件位于 bin/gradle
执行 Gradle 任务的过程, 主要就是在运行 Java/Groovy 代码编译期间如果有代码抛出了异常, 就会中断编译过程
在 Android Studio 中开发时, 编译就是基于 Gradle 实现的 Android Studio 中内置了 Gradle
Gradle 官网
- https://gradle.org/
- Gradle Wrapper
用 IDEA/Android Studio 创建基于 Gradle 的工程时, 默认会在工程根目录创建 GradleWrapper, 包括 gradlew 可执行脚本和 gradle/wrapper 文件夹, 其中指定了和工程配套的 gradle 版本
在工程根目录下直接执行./gradlew, 会自动将参数传给 wrapper 指定版本的 gradle, 执行对应的命令; 如果本机还没有该版本的 gradle, 则会先自动下载
工程配置和 Gradle 版本通常需要对应, 不正确的 Gradle 版本可能无法正常编译工程, 因此推荐使用 GradleWrapper 执行 Gradle 命令
gradle/wrapper/gradle-wrapper.properties
文件, 指定了 gradle 版本下载地址下载的文件存放位置(Mac 系统中默认在
~/.gradle/wrapper/dists
目录)此文件内容示例:
- distributionBase=GRADLE_USER_HOME
- distributionPath=wrapper/dists
- zipStoreBase=GRADLE_USER_HOME
- zipStorePath=wrapper/dists
- distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
在 Android Studio/IDEA 中, 可通过 Preferences - Build, Execution, Deployment - Gradle, 设置
Project-level settings
中 Use default gradle wrapper, 指定 Android Studio 使用工程配置的 Gradle Wrapper
DSLDSL Reference
Gradle 使用 Groovy 语言封装了一整套 API, 通常把这套 API 称为 DSL(Domain-Specific Languages, 领域特定语言)
通常在我们配置 Gradle 编译参数时, 所写的 gradle 脚本从形式上来看, 像是一门有着特殊语法格式的语言
Gradle 封装的 DSL, 按照固定格式用很简单的语法就能实现很复杂的配置, 大大简化了配置工作另一方面, 也正是由于封装的非常完善, 想深入学习 Gradle, 会感觉无从下手
可以通过 DSL Reference 文档查看 Gradle DSL 支持的语法配置项例如:
Gradle DSL Reference(Gradle 原生支持的 DSL 配置)
https://docs.gradle.org/current/dsl/
Android Plugin DSL Reference(Android 的 DSL 配置)
http://google.github.io/android-gradle-dsl/current/
关于 Gradle DSL 的语法原理和开发相关知识, 可参考我的另一篇文章
Gradle 开发快速入门 DSL 语法原理与常用 API 介绍
- http://www.paincker.com/gradle-develop-basics
- ProjectRootProjectSubProject (Module)
Project 是 Gradle 中的基本概念之一, 即一个工程一个工程可以包含多个 SubProject, 也称为 Module, 最顶层的工程也称为 RootProject
一个标准的 Android 工程, 文件结构如下
每个 build.gradle 对应一个 Project, 最外层的是 RootProject, 里面的 app 是 SubProject
settings.gradle 不是必须的, 一般在包含子工程时就需要用这个文件指定, 即我们通常所见的 include ':app'脚本
这里的':app'就是子工程的名字, 通常和文件夹名称对应
- settings.gradle
- build.gradle
- app
- build.gradle
- StartParameter
Gradle 执行时有一些称为 StartParameter 的参数, StartParameter 可在命令行设置, 可通过 gradle --help 查看例如:
--quiet, 执行过程中, 只显示 Error 级别的 Log
--stacktrace, 执行过程中, 输出所有 Exception 的 stacktrace
--full-stacktrace, 执行过程中, 输出所有 Exception 的完整 stacktrace
--no-daemon, 不使用 DeamonDeamon 是用于加速 Gradle 执行的后台进程, 有些情况下使用 Deamon 会有问题(可参考 https://docs.gradle.org/current/userguide/gradle_daemon.html)
--offline, 离线模式, 不使用网络资源
在命令行可通过 - P 参数传入 projectProperties, 并在 Gradle 脚本中获取
- # 命令行传入 projectProperties
- ./gradlew clean -Pkey=value
- // gradle 脚本中获取 projectProperties
- print gradle.startParameter.projectProperties.get('key')
还可以通过 - D 参数传入 systemPropertiesArgs, 并在 Gradle 脚本中获取
- # 命令行传入 systemPropertiesArgs
- ./gradlew clean -Dkey=value
- // gradle 脚本中获取 systemPropertiesArgs
- print gradle.startParameter.systemPropertiesArgs.get('key')
- gradle.properties
Properties 文件格式可由
java.util.Properties
解析, 包含若干键值对, 类似
HashMap<String,String>
Gradle 运行时会自动读取 gradle.properties 文件并引用其中的属性有多个位置可以放 gradle.properties 文件, 按优先级从低到高如下:
Project 所在目录(即 build.gradle 所在目录), 包括 RootProject 和 SubProject
GradleHome 目录(Mac 中默认为~/gradle)
通过 gradle 命令行 - D 参数指定的 Property
在 gradle.properties 文件中, 一些保留 Key 可用于配置 Gradle 运行环境, 例如 org.gradle.daemon 用于设置 GradleDeamon,
org.gradle.logging.level
用于设置 Gradle 的 Log 级别等
详情可参考
https://docs.gradle.org/current/userguide/build_environment.html
除了保留 Key 以外, 其他 Key 都可以作为变量用于配置工程例如在 Project 目录的 gradle.properties 中统一定义 Support 包的版本号, 然后在 build.gradle 中使用定义的变量如下
- SUPPORT_LIBRARY_VERSION=23.4.0
- dependencies {
- compile "com.android.support:support-v4:${SUPPORT_LIBRARY_VERSION}"
- compile "com.android.support:appcompat-v7:${SUPPORT_LIBRARY_VERSION}"
- compile "com.android.support:design:${SUPPORT_LIBRARY_VERSION}"
- compile "com.android.support:recyclerview-v7:${SUPPORT_LIBRARY_VERSION}"
- }
- Gradle Task
Gradle 以 Task(任务)的形式组织每一步操作, 每个 Task 执行一个原子操作(例如把 Java 编译成 class 文件把 class 打成 jar/dex 文件 APK 签名等)
每个 Project 包含若干 Task,Task 之间存在依赖关系, 执行一个 Task 前, 会先执行它所依赖的 Task
每个 Task 有自己的名字(例如'assemble'), 结合其所属 Project 的名字(例如':app'), 可以组成完整名(例如':app:assemble')
Gradle 内建了一个名为 tasks 的 Task, 可以列举 Project 中的所有 Task
执行 Task, 查看 Project 中的所有 Task
执行 Task 时, 直接把 Task 名称传给 gradle 即可
如果下载了 Gradle 并配置了环境变量, 则可在工程根目录执行:
gradle tasks
更推荐的做法, 是在工程根目录下调用 GradleWrapper 执行:
./gradlew tasks
执行结果如下(省略了部分输出):
- $ ./gradlew tasks
- :tasks
- ------------------------------------------------------------
- All tasks runnable from root project
- ------------------------------------------------------------
- Android tasks
- -------------
- androidDependencies - Displays the Android dependencies of the project.
- signingReport - Displays the signing info for each variant.
- sourceSets - Prints out all the source sets defined in this project.
- Build tasks
- -----------
- assemble - Assembles all variants of all applications and secondary packages.
- assembleAndroidTest - Assembles all the Test applications.
- assembleDebug - Assembles all Debug builds.
- assembleRelease - Assembles all Release builds.
- build - Assembles and tests this project.
- buildDependents - Assembles and tests this project and all projects that depend on it.
- buildNeeded - Assembles and tests this project and all projects it depends on.
- classes - Assembles main classes.
- clean - Deletes the build directory.
- cleanBuildCache - Deletes the build cache directory.
- compileDebugAndroidTestSources
- compileDebugSources
- compileDebugUnitTestSources
- compileReleaseSources
- compileReleaseUnitTestSources
- jar - Assembles a jar archive containing the main classes.
- mockableAndroidJar - Creates a version of android.jar that's suitable for unit tests.
- testClasses - Assembles test classes.
- Build Setup tasks
- -----------------
- init - Initializes a new Gradle build. [incubating]
- wrapper - Generates Gradle wrapper files. [incubating]
- Documentation tasks
- -------------------
- javadoc - Generates Javadoc API documentation for the main source code.
- Help tasks
- ----------
- buildEnvironment - Displays all buildscript dependencies declared in root project 'AndroidLint'.
- components - Displays the components produced by root project 'AndroidLint'. [incubating]
- dependencies - Displays all dependencies declared in root project 'AndroidLint'.
- dependencyInsight - Displays the insight into a specific dependency in root project 'AndroidLint'.
- dependentComponents - Displays the dependent components of components in root project 'AndroidLint'. [incubating]
- help - Displays a help message.
- model - Displays the configuration model of root project 'AndroidLint'. [incubating]
- projects - Displays the sub-projects of root project 'AndroidLint'.
- properties - Displays the properties of root project 'AndroidLint'.
- tasks - Displays the tasks runnable from root project 'AndroidLint' (some of the displayed tasks may belong to subprojects).
- Install tasks
- -------------
- installDebug - Installs the Debug build.
- installDebugAndroidTest - Installs the android (on device) tests for the Debug build.
- uninstallAll - Uninstall all applications.
- uninstallDebug - Uninstalls the Debug build.
- uninstallDebugAndroidTest - Uninstalls the android (on device) tests for the Debug build.
- uninstallRelease - Uninstalls the Release build.
- Verification tasks
- ------------------
- check - Runs all checks.
- connectedAndroidTest - Installs and runs instrumentation tests for all flavors on connected devices.
- connectedCheck - Runs all device checks on currently connected devices.
- connectedDebugAndroidTest - Installs and runs the tests for debug on connected devices.
- deviceAndroidTest - Installs and runs instrumentation tests using all Device Providers.
- deviceCheck - Runs all device checks using Device Providers and Test Servers.
- lint - Runs lint on all variants.
- lintDebug - Runs lint on the Debug build.
- lintRelease - Runs lint on the Release build.
- test - Run unit tests for all variants.
- testDebugUnitTest - Run unit tests for the debug build.
- testReleaseUnitTest - Run unit tests for the release build.
- To see all tasks and more detail, run gradlew tasks --all
- To see more detail about a task, run gradlew help --task <task>
- BUILD SUCCESSFUL
- Total time: 1.367 secs
执行多个 Task
如果需要先后执行多个 Task, 例如 tasks 和 clean, 将它们依次传给 gradle 即可:
./gradlew tasks clean
排除特定 Task
使用 gradle 的 - x 或 --exclude-task 参数, 可指定执行 Task 时排除特定 Task 例如:
./gradlew build -x check
执行 SubProject 中的 Task
如果想执行子工程':app'中的 Task, 可使用 Task 的完整名执行
./gradlew :app:tasks
也可以切换到子工程目录执行, 但切换当前目录会影响 Gradle 脚本中的相对路径, 不推荐
- cd app
- gradle tasks
Task 参数查看 Task 详细信息
Task 可以定义参数, 可在执行时从命令行传入例如 Gradle 内建了一个叫 help 的 Task, 带有一个 --task 参数, 可以用于查看一个 Task 的详细信息
查看 tasks 这个 Task 的详细信息, 就可以执行命令如下其中会显示一个 Task 的名称类型参数详细介绍分组等
- $ ./gradlew help --task tasks
- :help
- Detailed task information for tasks
- Path
- :tasks
- Type
- TaskReportTask (org.gradle.api.tasks.diagnostics.TaskReportTask)
- Options
- --all Show additional tasks and detail.
- Description
- Displays the tasks runnable from root project 'GradleStudy' (some of the displayed tasks may belong to subprojects).
- Group
- help
- BUILD SUCCESSFUL
- Total time: 1.051 secs
一些常用 GradleTask
clean: 清除 build 目录编译生成的文件 (Deletes the build directory.)
assemble: 编译工程 (Assembles the outputs of this project. [jar])
build: 编译并测试工程 (Assembles and tests this project. [assemble, check])
test: 单元测试等 (Runs the unit tests. [classes, testClasses])
check: 测试工程, 包含 test (Runs all checks. [test])
wrapper: 生成 GradleWrapper 文件 (Generates Gradle wrapper files. [incubating])
help: 帮助信息 (Displays a help message.)
tasks: 查看 Project 的所有 Task (Displays the tasks runnable from root project 'Xxx'.)
dependencies: 查看 Project 的依赖 (Displays all dependencies declared in root project 'Xxx'.)
projects: 查看 SubProject (Displays the sub-projects of root project 'Xxx'.)
查看 Task 依赖树
每个 Task 都会依赖若干 Task, 这些 Task 又会依赖别的 Task, 所有 Task 就会形成一个依赖树
为了更加直观的学习, 可以在 app/build.gradle 中添加如下的简单脚本, 让 Gradle 输出 Task 的依赖树
方法 printDependencies 通过递归的方式, 输出每个 Task 依赖的 TaskafterEvaluate 语句块中, 先找到 assembleDebug 这个 Task, 然后调用 printDependencies 输出其依赖树由于 Android 中有大量 Task 依赖, 打印出所有 Task 需要很久, 所以这里限制了最大递归深度为 3
- def printDependencies(Task task, String prefix, int depth, int maxDepth) {
- println prefix + task.project.name + ':' + task.name
- def tasks = task.getTaskDependencies().getDependencies(task)
- if (depth < maxDepth - 1) {
- tasks.each { t ->
- printDependencies(t, prefix + '\t', depth + 1, maxDepth)
- }
- } else {
- if (tasks.size() > 0) {
- println prefix + '\t' + "(${tasks.size()} child tasks...)"
- }
- }
- }
- afterEvaluate {
- println '==============================='
- def buildTask = tasks.findByName('assembleDebug')
- printDependencies(buildTask, '', 0, 3)
- println '==============================='
- }
执行任意 Gradle 任务, 例如 clean, 部分输出内容如下
- $ ./gradlew clean
- ===============================
- app:assembleDebug
- app:packageDebug
- app:processDebugResources
- (2 child tasks...)
- app:compileDebugJavaWithJavac
- (4 child tasks...)
- app:mergeDebugAssets
- (2 child tasks...)
- app:validateSigningDebug
- app:transformNativeLibsWithMergeJniLibsForDebug
- (3 child tasks...)
- app:transformResourcesWithMergeJavaResForDebug
- (2 child tasks...)
- app:transformClassesWithDexForDebug
- (2 child tasks...)
- app:compileDebugSources
- app:compileDebugNdk
- (1 child tasks...)
- app:compileDebugJavaWithJavac
- (4 child tasks...)
- ===============================
- :clean
- :app:clean
- BUILD SUCCESSFUL
- Total time: 0.975 secs
buildscript 与 allprojects
在 RootProject 的 build.gradle 中, 经常会看到 buildscript 和 allprojects 两个语句块, 并且里面都定义了一些相同的东西
buildscript, 顾名思义, 是编译脚本, 也就是说编译一个工程时需要的配置, 例如常会看到下面这样的脚本, 表示编译时要用到 Android Gradle Plugin
- buildscript {
- repositories {
- jcenter()
- }
- dependencies {
- classpath 'com.android.tools.build:gradle:2.3.3'
- }
- }
allprojects, 则用于配置所有 project, 包括 SubProject, 这里面的配置的东西, 则是工程代码需要的东西, 例如依赖的各种开源库等
- allprojects {
- repositories {
- jcenter()
- }
- }
关于编译与 Groovy
编译就是将程序源码转换成可执行文件或中间代码的过程具体到 Java, 就是将. java 代码文件变成. class 或者进一步打包成. jar 的过程
Gradle 基于 Groovy,Groovy 是在 Java 基础上扩展的脚本语言 Groovy 有和解释型语言一样的特性, 可以直接从源码运行而不需要提前编译但实际运行过程中, 也是先转换成 Java 的 class 文件, 再运行在 JVM 上的
在 buildscript 的 dependencies 中, 通过 classpath 语句引用一些编译好的 jar 包, Gradle 在执行时就会将其下载并加入 Java 的 classpath, 其中的 class 在编译时就可以被调用, 运行在电脑或云主机上
Gradle Plugin
Gradle 之所以是个强大的构建系统, 很重要的一点在于其完善的插件支持
Gradle 内建了 JavaGroovy 等插件, 除此之外, 还可以在 Gradle 提供的一整套 API 基础上开发插件, 实现各种编译打包工作
Gradle Android Plugin
在 Android 开发编译时, 会有很多 Android 相关的配置, 这些都是由 Gradle 的 Android 插件实现的
在 buildscript 中, 通过 dependencies 引入了 Gradle Android 插件:
- buildscript {
- dependencies {
- classpath 'com.android.tools.build:gradle:2.3.3'
- }
- }
在 app/build.gradle 中, 通过 apply 的方式, 应用了 Android 插件:
- // 对于 Android Application(APK)
- apply plugin: 'com.android.application'
- // 对于 Android Library(AAR)
- apply plugin: 'com.android.library'
应用了 Android 插件后, 即可在 app/build.gradle 中使用插件定义的 Android 相关 DSL 了:
- android {
- compileSdkVersion 24
- buildToolsVersion '25.0.2'
- defaultConfig {
- applicationId "com.paincker.lint.demo"
- minSdkVersion 15
- targetSdkVersion 25
- versionCode 1
- versionName "1.0"
- }
- }
- Repositories
很多从 Eclipse 转到 Android Studio 的开发者, 刚开始都对 Gradle 自动下载依赖包的功能印象深刻
Gradle 的依赖管理完全兼容 Maven 和 Ivy, 常使用 Maven 仓库来实现依赖管理, 当 Library 打包完成后上传到 Maven 仓库, Gradle 则会从 Maven 仓库下载需要的依赖
Repository 就是用来指定所需要的 Maven 仓库除了常见的 jcenter(),mavenCentral(), 还可以指定本地搭建的 Maven 仓库指定 URL 的 Maven 仓库等, 例如国内一些 Maven 仓库镜像, 以及很多公司内部私有的 Maven 仓库等
- repositories {
- jcenter()
- mavenCentral()
- maven { url 'http://maven.oschina.net/content/groups/public/' }
- ivy { url "http://repo.mycompany.com/repo" }
- localRepository { dirs 'lib' }
- maven {
- url "sftp://repo.mycompany.com:22/maven2"
- credentials {
- username 'user'
- password 'password'
- }
- }
- }
- Dependencies
Gradle 依赖管理官方文档
- https://docs.gradle.org/current/userguide/dependency_management.html
- DependencyNotation
DependencyNotation 用于描述要依赖的模块
外部依赖
通常用
group:name:version:classifier@ext
的形式表示其中 group 通常用包名, name 表示实际的名字, version 表示版本, classifier 在 Android 中是 ProductFlavor 和 BuildType 的组合(后面会介绍),ext 则表示扩展名
- compile "org.gradle.test.classifiers:service:1.0:jdk15@jar"
- compile group: 'org.gradle.test.classifiers', name: 'service', version: '1.0', classifier: 'jdk15'
Project 依赖
compile project(':someProject')
文件依赖
- dependencies {
- //declaring arbitrary files as dependencies
- compile files('hibernate.jar', 'libs/spring.jar')
- //putting all jars from 'libs' onto compile classpath
- compile fileTree('libs')
- }
参考官方文档
https://docs.gradle.org/current/dsl/org.gradle.api.artifacts.dsl.DependencyHandler.html
依赖传递(transitive)
Gradle 依赖项可配置 transitive 属性, 表示是否递归解析此模块的依赖项, 默认为 true
- compile('org.hibernate:hibernate:3.0.5') {
- transitive = true
- }
依赖树查看
每个模块都会依赖若干模块, 这些模块又分别依赖其他模块, 形成一个依赖树 Gradle 提供了名为 dependencies 的 Task, 可查看 Project 的依赖树, 执行效果如下(省略了部分输出)
- $ ./gradlew :app:dependencies
- ------------------------------------------------------------
- Project :app
- ------------------------------------------------------------
- compile - Classpath for compiling the main sources.
- +--- com.android.support:appcompat-v7:24.0.0
- | +--- com.android.support:support-v4:24.0.0
- | | \--- com.android.support:support-annotations:24.0.0
- | +--- com.android.support:support-vector-drawable:24.0.0
- | | \--- com.android.support:support-v4:24.0.0 (*)
- | \--- com.android.support:animated-vector-drawable:24.0.0
- | \--- com.android.support:support-vector-drawable:24.0.0 (*)
- \--- com.android.support.constraint:constraint-layout:1.0.2
- \--- com.android.support.constraint:constraint-layout-solver:1.0.2
- Artifact
Artifact 可以理解成一个模块的具体实现一个依赖项可以包含多个 Artifact, 例如依赖项
com.demo:mymodule:library:1.0
中可以包含多个不同格式 BuildType 的 Artifact:
- library-1.0-debug.jar
- library-1.0-release.jar
- library-1.0-debug.aar
- library-1.0-release.aar
Module DescriptorPOM 文件
Gradle 是如何获取到一个模块的依赖项的呢?
在 Maven 或 Ivy 仓库中, 模块的依赖信息并不包含在 Artifact 文件中, 而是通过 ModuleDescriptor 文件声明的
以阿里的 Maven 仓库为例, 用浏览器打开链接
http://maven.aliyun.com/nexus/content/groups/public/com/android/tools/build/gradle/2.3.0/
可以看到
com.android.tools.build:gradle:2.3.0
这个模块所包含的文件其中 sources.jar 为代码源文件, pom 文件则为 ModuleDescriptor
- gradle-2.3.0-sources.jar
- gradle-2.3.0-sources.jar.md5
- gradle-2.3.0-sources.jar.sha1
- gradle-2.3.0.jar
- gradle-2.3.0.jar.md5
- gradle-2.3.0.jar.sha1
- gradle-2.3.0.pom
- gradle-2.3.0.pom.md5
- gradle-2.3.0.pom.sha1
在 Maven 仓库中, 模块的 POM 文件可以指定默认的 Artifact, 并声明其依赖项; 不支持分别声明多个 Artifact 的依赖项 AAR 工程配置多版本发布的时候, 需要考虑这一特性
If you declare a module dependency, Gradle looks for a module descriptor file (pom.xml or ivy.xml) in the repositories. If such a module descriptor file exists, it is parsed and the artifacts of this module (e.g. hibernate-3.0.5.jar) as well as its dependencies (e.g. cglib) are downloaded. If no such module descriptor file exists, Gradle looks for a file called hibernate-3.0.5.jar to retrieve. In Maven, a module can have one and only one artifact. In Gradle and Ivy, a module can have multiple artifacts. Each artifact can have a different set of dependencies.
多 Artifact 的依赖处理 Artifact only notation
Gradle 在处理依赖时, 对于有多个 Artifact 的 Maven 模块, 可在 DependencyNotation 中声明需要的 Artifact, 没有声明则使用 POM 文件指定的默认版本, POM 中也没有指定则默认使用和 module 名一致的 jar 包
当使用 @指定了所依赖模块的 Artifact, 称为 Artifact only notation, 此时 Gradle 只会下载对应的 Artifact, 而不会下载其依赖, 此时可能就需要设置 transitive 属性
- compile('com.facebook.fresco:fresco:0.10.0@aar') {
- transitive = true
- }
- If no module descriptor file can be found, Gradle by default downloads a jar with the name of the module. But sometimes, even if the repository contains module descriptors, you want to download only the artifact jar, without the dependencies. [11] And sometimes you want to download a zip from a repository, that does not have module descriptors. Gradle provides an artifact only notation for those use cases - simply prefix the extension that you want to be downloaded with '@' sign.
依赖冲突分解
依赖项很多时, 依赖项之间经常会发生冲突例如多个 SDK 分别依赖了不同版本的 AppCompat, 就可能导致冲突 Gradle 提供了一些 API 可以用来处理依赖冲突
常见的依赖冲突解决思路可参考:
Gradle 依赖项学习总结, dependenciestransitiveforceexclude 的使用与依赖冲突解决
http://www.paincker.com/gradle-dependencies
ProductFlavorBuildType 与 Build Variant
Android 中定义了 ProductFlavor 和 BuildType 的 DSL
ProductFlavor
ProductFlavor 可以实现一套代码编译成不同的版本, 版本之间差异比较小, 例如开发版本测试版本线上版本; 或是发布到某些应用市场的定制版本 (例如需要修改一些资源文件) 等
ProductFlavor 中包含了一些应用相关的配置, 例如 minSdkVersion,versionCode 等下面的代码, 就是在对默认的 ProductFlavor 做配置
- android {
- defaultConfig {
- applicationId "com.paincker.gradle.demoapplication"
- minSdkVersion 15
- targetSdkVersion 24
- versionCode 1
- versionName "1.0"
- }
- }
可以在 ProductFlavors 中定义新的 Flavor 并进行配置, 覆盖 DefaultProductFlavor 中的相应配置
- android {
- productFlavors {
- myflavor {
- minSdkVersion 20
- }
- }
- }
ProductFlavor 还支持多维度(Multi-flavors), 每个纬度之间可以进行组合例如下面的示例, flavor 有 abi 和 version 两个纬度, 最后就会有 6 种组合:
- x86-freeapp
- arm-freeapp
- mips-freeapp
- x86-paidapp
- arm-paidapp
- mips-paidapp
- android {
- ...
- flavorGroups "abi", "version"
- productFlavors {
- freeapp {
- flavorGroup "version"
- ...
- }
- paidapp {
- flavorGroup "version"
- ...
- }
- x86 {
- flavorGroup "abi"
- ...
- }
- arm {
- flavorGroup "abi"
- ...
- }
- mips {
- flavorGroup "abi"
- ...
- }
- }
- }
参考: 多定制的变种版本
- https://flyouting.gitbooks.io/gradle-plugin-user-guide-cn/content/multi-flavor_variants.html
- BuildType
BuildType 本身是软件开发中的通用概念, 表示编译版本
Android 中定义了自己的 BuildType 接口, 其中包含了一些编译相关的配置, 例如 debuggable(是否可调试)minifyEnable(是否开启 Proguard)等
可以在 buildTypes 中配置支持的 BuildType 如下即使不做任何配置, 默认也会有 Debug 和 Release 两个 BuildType, 且分别包含了一套默认值, 例如 Debug 的 debuggable 参数默认为 true, 而 Release 的 debuggable 参数默认为 false
- android {
- buildTypes {
- debug {
- }
- develop {
- debuggable false
- minifyEnabled false
- }
- release {
- debuggable false
- minifyEnabled true
- proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
- }
- }
- }
- BuildVariant
ProductFlavor 与 BuildType 组合, 就成为 BuildVariant 在前面多纬度 Flavor 的示例基础上, 6 个 Flavor 组合 2 个 BuildType, 总共就会有 12 种 BuildVariant
每个 Build Variant 包含了一个 ProductFlavor 和一个 BuildTypeBuildType 和 ProductFlavor 中某些配置是重叠的, 组合成 BuildVariant 后, 通常会按优先级处理(一般 BuildType 优先级更高), 或做合并处理
例如两者都可以配置签名 signingConfigs, 合并成 BuildVariant 后, 会优先取取 BuildType 中定义的; 而对于配置项 proguardFiles, 则会采取合并处理
具体的合并逻辑, 可以参考这个类中的实现
- com.android.builder.core.VariantConfiguration
- BuildConfig
Android 开发常用到 BuildConfig 类, 这个类可在编译时生成, 用于在代码中获取一些编译相关的参数, 包括是否可以 Debug 当前 BuildType 和 Flavor 名字 VersionCode 和 VersionName 等, 例如常会用 BuildConfig.DEBUG 判断是否输出 Log 信息
BuildType 配置中提供了一个 buildConfigField 方法, 可以往 BuildConfig 中添加自定义字段
- int xxLibraryVersion = 192
- android {
- buildTypes {
- debug {
- buildConfigField "int", "XX_LIBRARY_VERSION", xxLibraryVersion
- }
- release {
- buildConfigField "int", "XX_LIBRARY_VERSION", xxLibraryVersion
- }
- }
- }
- dependencies {
- compile "com.xxx:xx:1.0.${xxLibraryVersion}"
- }
- public final class BuildConfig {
- public static final boolean DEBUG = Boolean.parseBoolean("true");
- public static final String BUILD_TYPE = "debug";
- // Fields from build type: debug
- public static final int XX_LIBRARY_VERSION = 192;
- }
- private void showLibraryInfo() {
- String msg = "xx library version is" + BuildConfig.XX_LIBRARY_VERSION;
- Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
- }
- Configurations
在 Gradle 中, 一个 Project 可以有多个 Configuration, 每个 Configuration 有不同的依赖配置
例如在 dependencies 中, 经常用到 compile xxx, 这里的 compile 就是一个 Configuration 一些常用的 Configuration 例如:
compile: 最常用, 参与编译并打包到 APK 中
testCompile: 用于单元测试
androidTestCompile: 用于 Android 自动化测试
provided: 参与编译但不打包到 APK 中, 类似 eclipse 中的 external-libs
apk: 打包到 APK 中但不参与编译, 不能在代码中调用
考虑到 BuildType 和 ProductFlavor, 又会和上述 Configuration 组合成新的 Configuration, 例如:
- compile
- debugCompile
- myflavorCompile
- myflavorDebugCompile
- testCompile
- testDebugCompile
- testMyflavorCompile
- testMyflavorDebugCompile
在运行 gradle dependencies 时, 也会分别显示每个 Configuration 对应的依赖树, 如下(省略了部分输出)
- ./gradlew :app:dependencies
- :app:dependencies
- ------------------------------------------------------------
- Project :app
- ------------------------------------------------------------
- androidJacocoAgent - The Jacoco agent to use to get coverage data.
- \--- org.jacoco:org.jacoco.agent:0.7.5.201505241946
- androidJacocoAnt - The Jacoco ant tasks to use to get execute Gradle tasks.
- \--- org.jacoco:org.jacoco.ant:0.7.5.201505241946
- +--- org.jacoco:org.jacoco.core:0.7.5.201505241946
- | \--- org.ow2.asm:asm-debug-all:5.0.1
- +--- org.jacoco:org.jacoco.report:0.7.5.201505241946
- | +--- org.jacoco:org.jacoco.core:0.7.5.201505241946 (*)
- | \--- org.ow2.asm:asm-debug-all:5.0.1
- \--- org.jacoco:org.jacoco.agent:0.7.5.201505241946
- androidTestAnnotationProcessor - Classpath for the annotation processor for 'androidTest'.
- No dependencies
- androidTestApk - Classpath packaged with the compiled 'androidTest' classes.
- No dependencies
- androidTestCompile - Classpath for compiling the androidTest sources.
- No dependencies
- androidTestJackPlugin - Classpath for the 'androidTest' Jack plugins.
- No dependencies
- androidTestProvided - Classpath for only compiling the androidTest sources.
- No dependencies
- androidTestWearApp - Link to a wear app to embed for object 'androidTest'.
- No dependencies
- annotationProcessor - Classpath for the annotation processor for 'main'.
- No dependencies
- apk - Classpath packaged with the compiled 'main' classes.
- No dependencies
- archives - Configuration for archive artifacts.
- No dependencies
- compile - Classpath for compiling the main sources.
- +--- com.android.support:appcompat-v7:24.0.0
- | +--- com.android.support:support-v4:24.0.0
- | | \--- com.android.support:support-annotations:24.0.0
- | +--- com.android.support:support-vector-drawable:24.0.0
- | | \--- com.android.support:support-v4:24.0.0 (*)
- | \--- com.android.support:animated-vector-drawable:24.0.0
- | \--- com.android.support:support-vector-drawable:24.0.0 (*)
- \--- com.android.support.constraint:constraint-layout:1.0.2
- \--- com.android.support.constraint:constraint-layout-solver:1.0.2
- debugAnnotationProcessor - Classpath for the annotation processor for 'debug'.
- No dependencies
- debugApk - Classpath packaged with the compiled 'debug' classes.
- No dependencies
- debugCompile - Classpath for compiling the debug sources.
- No dependencies
- debugJackPlugin - Classpath for the 'debug' Jack plugins.
- No dependencies
- debugProvided - Classpath for only compiling the debug sources.
- No dependencies
- debugWearApp - Link to a wear app to embed for object 'debug'.
- No dependencies
- default - Configuration for default artifacts.
- No dependencies
- default-mapping - Configuration for default mapping artifacts.
- No dependencies
- default-metadata - Metadata for the produced APKs.
- No dependencies
- jackPlugin - Classpath for the 'main' Jack plugins.
- No dependencies
- provided - Classpath for only compiling the main sources.
- No dependencies
- ...
- SourceSet
Gradle 中使用 SourceSet 管理 Java 源码; Android 定义了自己的 SourceSet, 其用法和 Gradle 类似
Gradle 的 SourceSet 官方文档:
https://docs.gradle.org/current/dsl/org.gradle.api.tasks.SourceSet.html
Android 的 SourceSet 官方文档:
http://google.github.io/android-gradle-dsl/current/com.android.build.gradle.api.AndroidSourceSet.html
默认的 SourceSet 即 main, 根目录位于 src/main, 其中又包括多个子目录, 例如:
src/main/java,Java 源码
src/main/resources,Java 资源文件
src/main/res,Android 资源文件
src/main/assets,Android assets 文件
ProductFlavorBuildTypeBuildVarianttest/androidTest, 也会按照一定的形式组合产生 SourceSet
可以配置某个 SourceSet 的根目录, 或者指定具体的子目录(支持多个目录), 如下:
- android {
- sourceSets {
- myflavor {
- res.srcDirs = ['src/main/res', 'src/main/res2']
- }
- debug.setRoot('src/main')
- }
- }
使用 Gradle 的 sourceSet 可以查看项目中所有的 SourceSet
- $ ./gradlew :app:sourceSets
- :app:sourceSets
- ------------------------------------------------------------
- Project :app
- ------------------------------------------------------------
- androidTest
- -----------
- Compile configuration: androidTestCompile
- build.gradle name: android.sourceSets.androidTest
- Java sources: [app/src/androidTest/java]
- Manifest file: app/src/androidTest/AndroidManifest.xml
- Android resources: [app/src/androidTest/res]
- Assets: [app/src/androidTest/assets]
- AIDL sources: [app/src/androidTest/aidl]
- RenderScript sources: [app/src/androidTest/rs]
- JNI sources: [app/src/androidTest/jni]
- JNI libraries: [app/src/androidTest/jniLibs]
- Java-style resources: [app/src/androidTest/resources]
- androidTestMyflavor
- -------------------
- Compile configuration: androidTestMyflavorCompile
- build.gradle name: android.sourceSets.androidTestMyflavor
- Java sources: [app/src/androidTestMyflavor/java]
- Manifest file: app/src/androidTestMyflavor/AndroidManifest.xml
- Android resources: [app/src/androidTestMyflavor/res]
- Assets: [app/src/androidTestMyflavor/assets]
- AIDL sources: [app/src/androidTestMyflavor/aidl]
- RenderScript sources: [app/src/androidTestMyflavor/rs]
- JNI sources: [app/src/androidTestMyflavor/jni]
- JNI libraries: [app/src/androidTestMyflavor/jniLibs]
- Java-style resources: [app/src/androidTestMyflavor/resources]
- debug
- -----
- Compile configuration: debugCompile
- build.gradle name: android.sourceSets.debug
- Java sources: [app/src/debug/java]
- Manifest file: app/src/debug/AndroidManifest.xml
- Android resources: [app/src/debug/res]
- Assets: [app/src/debug/assets]
- AIDL sources: [app/src/debug/aidl]
- RenderScript sources: [app/src/debug/rs]
- JNI sources: [app/src/debug/jni]
- JNI libraries: [app/src/debug/jniLibs]
- Java-style resources: [app/src/debug/resources]
- main
- ----
- Compile configuration: compile
- build.gradle name: android.sourceSets.main
- Java sources: [app/src/main/java]
- Manifest file: app/src/main/AndroidManifest.xml
- Android resources: [app/src/main/res]
- Assets: [app/src/main/assets]
- AIDL sources: [app/src/main/aidl]
- RenderScript sources: [app/src/main/rs]
- JNI sources: [app/src/main/jni]
- JNI libraries: [app/src/main/jniLibs]
- Java-style resources: [app/src/main/resources]
- myflavor
- --------
- Compile configuration: myflavorCompile
- build.gradle name: android.sourceSets.myflavor
- Java sources: [app/src/myflavor/java]
- Manifest file: app/src/myflavor/AndroidManifest.xml
- Android resources: [app/src/myflavor/res]
- Assets: [app/src/myflavor/assets]
- AIDL sources: [app/src/myflavor/aidl]
- RenderScript sources: [app/src/myflavor/rs]
- JNI sources: [app/src/myflavor/jni]
- JNI libraries: [app/src/myflavor/jniLibs]
- Java-style resources: [app/src/myflavor/resources]
- myflavorDebug
- -------------
- Compile configuration: myflavorDebugCompile
- build.gradle name: android.sourceSets.myflavorDebug
- Java sources: [app/src/myflavorDebug/java]
- Manifest file: app/src/myflavorDebug/AndroidManifest.xml
- Android resources: [app/src/myflavorDebug/res]
- Assets: [app/src/myflavorDebug/assets]
- AIDL sources: [app/src/myflavorDebug/aidl]
- RenderScript sources: [app/src/myflavorDebug/rs]
- JNI sources: [app/src/myflavorDebug/jni]
- JNI libraries: [app/src/myflavorDebug/jniLibs]
- Java-style resources: [app/src/myflavorDebug/resources]
- myflavorRelease
- ---------------
- Compile configuration: myflavorReleaseCompile
- build.gradle name: android.sourceSets.myflavorRelease
- Java sources: [app/src/myflavorRelease/java]
- Manifest file: app/src/myflavorRelease/AndroidManifest.xml
- Android resources: [app/src/myflavorRelease/res]
- Assets: [app/src/myflavorRelease/assets]
- AIDL sources: [app/src/myflavorRelease/aidl]
- RenderScript sources: [app/src/myflavorRelease/rs]
- JNI sources: [app/src/myflavorRelease/jni]
- JNI libraries: [app/src/myflavorRelease/jniLibs]
- Java-style resources: [app/src/myflavorRelease/resources]
- release
- -------
- Compile configuration: releaseCompile
- build.gradle name: android.sourceSets.release
- Java sources: [app/src/release/java]
- Manifest file: app/src/release/AndroidManifest.xml
- Android resources: [app/src/release/res]
- Assets: [app/src/release/assets]
- AIDL sources: [app/src/release/aidl]
- RenderScript sources: [app/src/release/rs]
- JNI sources: [app/src/release/jni]
- JNI libraries: [app/src/release/jniLibs]
- Java-style resources: [app/src/release/resources]
- test
- ----
- Compile configuration: testCompile
- build.gradle name: android.sourceSets.test
- Java sources: [app/src/test/java]
- Java-style resources: [app/src/test/resources]
- testDebug
- ---------
- Compile configuration: testDebugCompile
- build.gradle name: android.sourceSets.testDebug
- Java sources: [app/src/testDebug/java]
- Java-style resources: [app/src/testDebug/resources]
- testMyflavor
- ------------
- Compile configuration: testMyflavorCompile
- build.gradle name: android.sourceSets.testMyflavor
- Java sources: [app/src/testMyflavor/java]
- Java-style resources: [app/src/testMyflavor/resources]
- testMyflavorDebug
- -----------------
- Compile configuration: testMyflavorDebugCompile
- build.gradle name: android.sourceSets.testMyflavorDebug
- Java sources: [app/src/testMyflavorDebug/java]
- Java-style resources: [app/src/testMyflavorDebug/resources]
- testMyflavorRelease
- -------------------
- Compile configuration: testMyflavorReleaseCompile
- build.gradle name: android.sourceSets.testMyflavorRelease
- Java sources: [app/src/testMyflavorRelease/java]
- Java-style resources: [app/src/testMyflavorRelease/resources]
- testRelease
- -----------
- Compile configuration: testReleaseCompile
- build.gradle name: android.sourceSets.testRelease
- Java sources: [app/src/testRelease/java]
- Java-style resources: [app/src/testRelease/resources]
- BUILD SUCCESSFUL
- Total time: 1.041 secs
SourceSet 的合并 Manifest 合并
对于某个具体的编译任务中某一类源文件, 会根据一定的优先级与合并规则, 对多个 SourceSet 中的同类源文件进行合并得到
一般情况下, 优先级从高到底分别是:
- BuildVariant(src/armFreeappDebug)
- BuildType(src/debug)
- MultiFlavor(src/armFreeapp)
每个单独的 Flavor(src/arm, src/freeapp)
sourceSet.main(src/main)
依赖中的对应文件(JARAAR 或 SubProject 中解析出来的源文件)
对于 Java 类 drawable 目录下的图片资源文件 layout 等, 合并措施一般就是同名文件直接覆盖
对于 values 目录下的标签类型资源, 合并时会以每个标签为最小单元进行覆盖
- <!-- 多个 SourceSet 都定义了同名 style 标签, 则高优先级会直接覆盖低优先级 -->
- <!-- src/debug/res/values/xxx.xml 高优先级 -->
- <style name="txt_main">
- <item name="android:textSize">12sp</item>
- </style>
- <!-- src/main/res/values/yyy.xml 低优先级 -->
- <style name="txt_main">
- <item name="android:textSize">14sp</item>
- <item name="android:textColor">@android:color/white</item>
- </style>
- <!-- 合并后 -->
- <style name="txt_main">
- <item name="android:textSize">12sp</item>
- </style>
而 Manifest 文件的合并规则更复杂一些具体可参考官方文档:
- https://developer.android.com/studio/build/manifest-merge.html
- Android Gradle Task
Android Gradle 环境下, 有下面几个常见的 Task
assemble:Gradle 内建的编译任务(生成 APK / JAR / AAR)
test:Gradle 内建的测试任务
lint:Android 定义的 Lint 检查任务
check:Gradle 内建的检查任务, 依赖 linttest
build:Gradle 内建的 Build 任务, 依赖 assemblecheck
结合 ProductFlavorBuildTypeBuildVariant, 又会组合成很多 Task
这些 Task 的依赖关系示例如下:
- app:build
- app:check
- app:lint
- app:test
- app:testMyflavor2DebugUnitTest
- app:testMyflavor2ReleaseUnitTest
- app:testMyflavor1DebugUnitTest
- app:testMyflavor1ReleaseUnitTest
- app:assemble
- app:assembleDebug
- app:assembleMyflavor2Debug
- app:assembleMyflavor1Debug
- app:assembleRelease
- app:assembleMyflavor1Release
- app:assembleMyflavor2Release
Android Studio/IDEA 相关
在 Android Studio/IDEA 中开发时, 会在 Build Variants 窗口选择指定的 Build 参数, 例如 myflavor1Debug
Sync Project With Gradle Files
当修改了 gradle 文件等情况, 会提示:
Gradle files have changed since last project sync. A project sync may be necessary for the IDE to work properly.
此时点击提示栏中的 Sync, 会触发 Gradle 同步操作刚打开工程, 或者手动选择菜单 Tools-Android-Sync Project With Gradle Files 或工具栏中的同步按钮, 也会触发同步操作
在同步过程中, Gradle 会执行很多任务, 包括解析并下载所有依赖项, 解压 AAR 合并 SourceSet 生成 BuildConfigR 文件 (结果会输出到 build 目录) 等, 这样 Android Studio 就能加载所有引用的 classjar 文件, 对源码进行语法解析, 从而代码也可以正常的跳转了
通过 GradleConsole 窗口, 可以看到同步过程中 Gradle 所执行的 Task, 其中最主要的是
generateMyflavor1DebugSources
, 即生成源码的过程, 依赖了 prepareMyflavor1DebugDependenciesgenerateMyflavor1DebugBuildConfiggenerateMyflavor1DebugResValues 等 Task
- :app:preBuild UP-TO-DATE
- :app:preMyflavor1DebugBuild UP-TO-DATE
- :app:checkMyflavor1DebugManifest
- :app:preMyflavor1ReleaseBuild UP-TO-DATE
- :app:preMyflavor2DebugBuild UP-TO-DATE
- :app:preMyflavor2ReleaseBuild UP-TO-DATE
- :app:prepareComAndroidSupportAnimatedVectorDrawable2400Library
- :app:prepareComAndroidSupportAppcompatV72400Library
- :app:prepareComAndroidSupportConstraintConstraintLayout102Library
- :app:prepareComAndroidSupportSupportV42400Library
- :app:prepareComAndroidSupportSupportVectorDrawable2400Library
- :app:prepareComFacebookFrescoDrawee0100Library
- :app:prepareComFacebookFrescoFbcore0100Library
- :app:prepareComFacebookFrescoFresco0100Library
- :app:prepareComFacebookFrescoImagepipeline0100Library
- :app:prepareComFacebookFrescoImagepipelineBase0100Library
- :app:prepareMyflavor1DebugDependencies
- :app:compileMyflavor1DebugAidl
- :app:compileMyflavor1DebugRenderscript
- :app:generateMyflavor1DebugBuildConfig
- :app:generateMyflavor1DebugResValues
- :app:generateMyflavor1DebugResources
- :app:mergeMyflavor1DebugResources
- :app:processMyflavor1DebugManifest
- :app:processMyflavor1DebugResources
- :app:generateMyflavor1DebugSources
- :app:preMyflavor1DebugAndroidTestBuild UP-TO-DATE
- :app:prepareMyflavor1DebugAndroidTestDependencies
- :app:compileMyflavor1DebugAndroidTestAidl
- :app:processMyflavor1DebugAndroidTestManifest
- :app:compileMyflavor1DebugAndroidTestRenderscript
- :app:generateMyflavor1DebugAndroidTestBuildConfig
- :app:generateMyflavor1DebugAndroidTestResValues
- :app:generateMyflavor1DebugAndroidTestResources
- :app:mergeMyflavor1DebugAndroidTestResources
- :app:processMyflavor1DebugAndroidTestResources
- :app:generateMyflavor1DebugAndroidTestSources
- :app:mockableAndroidJar UP-TO-DATE
- :app:preMyflavor1DebugUnitTestBuild UP-TO-DATE
- :app:prepareMyflavor1DebugUnitTestDependencies
- BUILD SUCCESSFUL
- Total time: 6.425 secs
- Run
点击三角形箭头时, 除了执行 assembleMyflavor1Debug, 还会执行 install(将 APK 安装至设备)等 Task
在 Android Studio 的 Run/Debug Configuration 窗口中, 还可以指定点击三角箭头时要执行的 Gradle Task 例如可以添加一个 clean 操作, 每次编译前先用 clean 清理 build 目录
AAR 多版本发布
Android 开发经常会用到 AAR, 有时候希望 AAR 能支持发布多个版本, 并在不同的情况下依赖不同版本 (包括不同的 BuildType 和 ProductFlavor) 例如主工程依赖 xxLibrary, 希望 Debug 版本 APK 依赖 Debug 版本的 AAR, 而 Release 版本 APK 依赖 Release 版本的 AAR
在 Android 中依赖 SubProject 或 AAR 时, 如果没有特殊配置, AAR 的发布和模块依赖默认均为 Release 版本
实际尝试主工程依赖子工程, 子工程中读取 BuildConfig.DEBUG 的值始终是 false, 修改 Android Studio 中子模块的 BuildVariant 配置也没有效果
- dependencies {
- compile project(':xxx_library')
- compile 'com.xxx:xxx:1.0.5@aar' {
- transitive = true
- }
- }
可用如下方式配置子模块或者独立 AAR 工程发布所有版本:
- apply plugin: 'com.android.library'
- android {
- // 发布非默认版本
- publishNonDefault true
- // 指定默认版本, 发布 AAR 到 Maven 时会从默认版本生成 POM 依赖配置
- // 不指定会导致 POM 无法正确生成, 从而依赖不能传递
- defaultPublishConfig "falvorARelease"
- productFlavors {
- flavorA { }
- flavorB { }
- }
- }
用下面的方式依赖子模块或已经发布的 AAR:
- dependencies {
- // DebugRelease 版本 APK, 分别依赖 DebugRelease 版本子模块
- debugCompile project(path: ':xxx', configuration: 'flavorADebug')
- releaseCompile project(path: ':xxx', configuration: 'flavorARelease')
- // 指定依赖 aar 版本, 并设置 transitive 为 true
- debugCompile('com.xxx:library:1.0.5:flavorADebug@aar') {
- transitive = true
- }
- releaseCompile('com.xxx:library:1.0.5:flavorARelease@aar') {
- transitive = true
- }
- }
来源: http://www.jianshu.com/p/3c700e7d3855