Gradle Plugin 使用手册

x775

贡献于2015-10-10

字数:0 关键词: 项目构建

1. 介绍 2. 简介 i. 新构建系统的目标 ii. 为什么使用 Gradle? 3. 配置要求 4. 基础项目 i. 构建文件示例 ii. 项目结构 i. 配置项目结构 iii. 构建任务 i. 通用任务 ii. Java 项目的 Task iii. Android Tasks iv. 基本的构建定制 i. Manifest 属性 ii. 构建类型 iii. 签名配置 iv. 运行 ProGuard v. 清理资源 5. 依赖、Library 和多项目 i. 包依赖 i. 本地包依赖 ii. 远程包依赖 ii. 多项目设置 iii. Library 项目 i. 创建 Library 项目 ii. 普通项目和 Library 项目的区别 iii. 引用 Library 项目 iv. Library 项目发布 6. 测试 i. 单元测试 ii. 基本知识和配置 iii. 运行测试 iv. 测试 Android Library 项目 v. 测试报告 i. 独立项目 ii. 多项目报告 vi. Lint 支持 7. 构建 Variants(变种)版本 i. 产品定制 ii. 构建类型+产品定制=构建变种版本 iii. 产品定制的配置 iv. 源组件和依赖 v. 构建和任务 vi. 测试 vii. 多定制的变种版本 8. 高级构建的自定义 i. 构建选项 i. Java 编译选项 目录 Gradle Android Plugin 2 ii. aapt 选项 iii. dex 选项 ii. 操作 task iii. 构建类型和产物定制的属性引用 iv. 使用sourceCompatibility 1.7 9. 附录 i. ApplicationId 与 packageName Gradle Android Plugin 3 Gradle Plugin User Guide 官方地址 http://tools.android.com/tech-docs/new-build-system/user-guide 在线阅读译文 http://chaosleong.gitbooks.io/gradle-for-android/content/ 译文 Github 地址 https://github.com/ChaosLeong/Gradle-Android-Plugin 本中文指南的翻译内容大部分参考 Avatar Qing 的 《Gradle Plugin User Guide 中文版》 flyouting 的 《Gradle Plugin User Guide 中文版》 并做了相应的修正以及更新,如有纰漏,望斧正。 License 采用 CC BY-NC-SA 4.0 许可协议进行许可。 译者序 Gradle Android Plugin 4译者序 简介 Gradle Android Plugin 5简介 新构建系统的目标: 让重用代码和资源变得更容易 使针对不同渠道构建多个 APK 或构建同一个应用的不同定制版本更容易 使构建过程更容易配置,扩展和自定义 优秀的 IDE 集成 新构建系统的目标 Gradle Android Plugin 6新构建系统的目标 Gradle 是一个允许通过插件来创建自定义的构建逻辑的优秀构建工具。 以下的一些特性让我们选择了 Gradle: 使用领域专用语言(DSL)来描述和控制构建逻辑 构建文件基于 Groovy,并允许通过 DSL 来声明元素、使用代码操作 DSL 元素这样的混合方式来自定义的构建逻辑 内置了 Maven 和 Ivy 来进行依赖管理 相当灵活。允许使用最好的实现,但是不会强制实现的形式 插件提供 DSL 和 API 来定义构建文件 优秀的 API 工具与 IDE 集成 为什么使用 Gradle? Gradle Android Plugin 7为什么使用 Gradle? Gradle 1.10,1.11,1.12 使用插件 0.11.1 版本 SDK Build Tools 19.0.0 版本的一些特性需要更高版本。 译者注:Gradle 目前已经是 2.4 版本,插件 1.2.+ 最新可以关注: http://www.gradle.org/ 配置要求 Gradle Android Plugin 8配置要求 Gradle 项目的构建描述定义在项目根目录下的 build.gradle 文件中。 基础项目 Gradle Android Plugin 9基础项目 一个纯 Java 的 Gradle 项目的 build.gradle 文件可以简单到只包含以下内容: apply plugin: 'java' 这里引入了 Gradle 的 Java 插件,该插件提供了所有构建和测试 Java 应用程序所需的东西。 最简单的 Android Gradle 项目的 build.gradle: buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.11.1' } } apply plugin: 'android' android { compileSdkVersion 19 buildToolsVersion "19.0.0" } 译者注:目前 Gradle Tools 版本为 1.2.3 (2015.05.26) 上述内容包含了 Android 构建文件的 3 个主要部分: buildscript { ... } 配置了驱动构建的代码. 在这部分,声明了项目使用 Maven 仓库,并且声明了一个 Maven 文件的 classpath。 该文件声明了项目的 Android Gradle 插件版本为 0.11.1。 注意:这里的配置只影响了构建过程的代码,而不是整个工程的代码.工程本身需要声明它自己的仓库和依赖.这个后面 会提到. 接下来,跟前面提到的 Java 插件一样添加了 android 插件. 最后,android { ... } 配置了所有 android 构建所需的参数,这也是 Android DSL 的入口点。 默认情况下,只有 compileSdkVersion 和 buildtoolsVersion 这两个属性是必须的。 compileSdkVersion 属性相当于旧构建系统中 project.properites 文件中的 target 属性。这个新的属性可以跟旧的 target 属性一样指定一个 int 或者 String 类型的值。 重要: android 插件不能与 java 插件同时使用,否则会导致构建错误. 注意: 你需要在相同路径下添加一个 local.properties 文件,并使用 sdk.dir 属性来设置 SDK 路径。或通过设置 ANDROID_HOME 环境变量来设置 SDK 路径,这两种方式没有什么不同,根据你自己的喜好选择其中一种设置。 构建文件示例 Gradle Android Plugin 10构建文件示例 Gradle Android Plugin 11构建文件示例 上面提到的构建文件中有默认的文件夹结构。Gradle 遵循约定优先于配置的概念,在尽可能的情况下提供合理的默认配置参 数。 最基本的项目有两个 “source sets” 组件,分别存放应用源代码及测试源代码。它们分别位于: src/main/ src/androidTest/ 里面每个存在的文件夹对应相应的源组件。 对于 Java plugin 和 Android plugin 来说,它们的 Java 源代码和资源文件路径如下: java/ resources/ 但对于 Android plugin 来说,它还拥有以下特有的文件和文件夹结构: AndroidManifest.xml res/ assets/ aidl/ rs/ jni/ 注意: src/androidTest/AndroidManifest.xml 会被自动创建,所以一般情况下不需要手动创建。 项目结构 Gradle Android Plugin 12项目结构 当默认的项目结构不适用时,就可能需要去配置它。根据 Gradle 文档描述,可以通过以下代码重新配置 Java 项目的 sourceSets: sourceSets { main { java { srcDir 'src/java' } resources { srcDir 'src/resources' } } } 注意: srcDir 将会被添加到已存在的源文件目录中(这个在Gradle 文档中没有提到,但是实际上确实是这样执行了) 要替换默认的源文件目录,你需要使用一个数组路径的 srcDirs 来替代。下面是使用调用对象的另外一种不同的方法: sourceSets { main.java.srcDirs = ['src/java'] main.resources.srcDirs = ['src/resources'] } 想了解更多的信息,可以查看 Gradle 文档中 Java 插件 部分. Android 插件使用了类似的语法,因为使用了它自己的 sourceSet,这些配置会被添加到 android 对象中。 下面这个例子,使用了旧工程结构的 main 代码,并把 androidTest 的 sourceSet 映射到 tests 目录中。 android { sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] resources.srcDirs = ['src'] aidl.srcDirs = ['src'] renderscript.srcDirs = ['src'] res.srcDirs = ['res'] assets.srcDirs = ['assets'] } androidTest.setRoot('tests') } } 注意:因为旧的结构把所有的源文件(java, aidl, renderscript, and java resources)放在同一个目录中,所以我们需要 重新映射所有的 sourceSet 新组件到同一个 src 目录下。 注意:setRoot() 会移动所有的 sourceSet(包括它的子目录)到新的目录。例子中把 src/androidTest/* 移动到 tests/* Android 特有的 sourceSets 在 Java sourceSets 中不起作用. 配置项目结构 Gradle Android Plugin 13配置项目结构 上述的就是项目迁移的简单示例. Gradle Android Plugin 14配置项目结构 构建任务 Gradle Android Plugin 15构建任务 添加一个插件到构建文件中将会自动创建一系列构建任务(build tasks)去执行(注:Gradle 属于任务驱动型构建工具,构 建过程基于 Task)。 Java 插件和 Android 插件都会创建以下 Task: assemble 组合项目所有输出任务 check 执行所有检查任务 build 执行 assemble 和 check 两个 task 的所有工作 clean 会清空项目的输出 实际上 assemble,check 和 build 这三个 task 不做任何事情。它们只是一个 Task 标志,用来告诉 plugin 添加实际需要执 行的 task 去完成这些工作。 这就允许你去调用相同的 task,而不需要考虑当前是什么类型的项目,或者当前项目添加了什么 plugin。 例如,添加了 findbugs plugin 将会创建一个新的 task 并且让 check task 依赖于这个新的 task。当 check task 被调用的时 候,这个新的 task 将会先被调用。 在命令行环境中,你可以执行以下命令来获取更多高级别的 task: gradle tasks 查看所有 task 列表和它们之间的依赖关系可以执行以下命令: gradle tasks --all 注意:Gradle 会自动监视一个 task 声明的所有输入和输出。 两次执行 build task 并且期间项目没有任何改动,Gradle 将会使用 UP-TO-DATE 通知所有 task。这意味着第二次 build 执行的时候不会请求任何 task 执行。这允许 task 之间互相依赖,而不会导致不需要的构建请求被执行。 通用任务 Gradle Android Plugin 16通用任务 Java plugin 主要创建了两个 task,依赖于主要的 task(一个标识性的 task): assemble jar 该 task 创建所有输出 check test 该 task 执行所有测试 jar task 本身直接或者间接依赖于其他 task: classes task 将会被调用于编译 Java 代码。testClasses task 用于编译测试, 但是很少被调用,因为 test task 依赖于它(类似于 classes task)。 通常情况下,你可能只需要调用 assemble 和 check,而不需要其他 task。 你可以在 Gradle 文档中查看 Java plugin 的全部 task。 Java 项目的 Task Gradle Android Plugin 17Java 项目的 Task Android plugin 使用相同的约定以兼容其他插件,并且附加了标志性的 task,包括: assemble 组合项目所有输出 check 执行所有检查 connectedCheck 在一个连接的设备或者模拟器上执行检查,它们可以在所有连接的设备上并行执行检查 deviceCheck 通过 APIs 连接远程设备来执行检查,主要用于 CI(Continuos integration ,持续集成)服务上。 build 执行 assemble 和 check 的所有工作 clean 清空项目的输出 这些新的标志性 task 是必须的,以保证能够在没有设备连接的情况下执行定期检查。 注意 build task 不依赖于 deviceCheck 或者 connectedCheck。 一个 Android 项目至少拥有两个输出:debug APK 和 release APK。每个输出都有各自的标志性 task 以便能够单独构建它 们。 assemble assembleDebug assembleRelease 它们都依赖于其它一些 tasks 以完成构建一个APK所需的多个步骤。其中 assemble task 依赖于上述两个 task,所以执行 assemble 将会同时构建出两个 APK。 提示: Gradle 在命令行上支持驼峰命名法的 task 简称,例如,执行 gralde aR 等同与输入 gradle assembleRelease 只要没有其它命令匹配 aR 译者注:assR 同样能运行 assembleRelease task,即简称不一定要是首字母缩写 _(:зゝ∠)_ check task 也有拥有依赖: check lint connectedCheck connectedAndroidTest connectedUiAutomatorTest(尚未实现) deviceCheck 进行测试时才会触发 最后,插件为所有的构建类型(debug, release, test)创建了 install/uninstall task,只要它们是可以被安装的(需要签 名过的)。 Android Tasks Gradle Android Plugin 18Android Tasks Gradle Android Plugin 19Android Tasks Android plugin 提供了大量 DSL 用于直接从构建系统定制大部分事情。 基本的构建定制 Gradle Android Plugin 20基本的构建定制 通过 DSL 可以配置以下 manifest 属性: minSdkVersion targetSdkVersion versionCode versionName applicationId(有效的包名--查看 ApplicationId 与 PackageName 了解更多信息) testApplicationId(测试应用的包名) testInstrumentationRunner(Instrumentation 的 test runner) 例子: android { compileSdkVersion 19 buildToolsVersion "19.0.0" defaultConfig { versionCode 12 versionName "2.0" minSdkVersion 16 targetSdkVersion 16 } } 在 android 元素中的 defaultConfig 定义了所有的配置。 Android Plugin 的早期版本使用 packageName 来配置 manifest 的 packageName 属性。从 0.11.0 版本开始,你应该在 build.gradle 中使用 applicationId 来配置 manifest 的 packageName 属性。这是为了消除应用程序的 packageName(程序 的 ID )和 java 包名所引起的歧义。 在构建文件中定义的强大之处在于它是动态的。 例如,可以从一个文件中或者其它自定义的逻辑代码中读取版本信息: def computeVersionName() { ... } android { compileSdkVersion 19 buildToolsVersion "19.0.0" defaultConfig { versionCode 12 versionName computeVersionName() minSdkVersion 16 targetSdkVersion 16 } } 注意: 不要使用在给定范围内同名的 getter 方法,否则可能引起冲突。例如,在 defaultConfig{...} 中调用 getVersionName() 将会自动调用 defaultConfig.getVersionName() 方法,你自定义的 getVersionName() 方法就不会被 调用。 Manifest 属性 Gradle Android Plugin 21Manifest 属性 如果没有使用 DSL 来设置属性的值,则会使用默认的属性值。下表是可能用到的值: 属性名 在 DSL 对象中的默认值 默认值 versionCode -1 从 manifest 中读取 versionName null 从 manifest 中读取 minSdkVersion -1 从 manifest 中读取 targetSdkVersion -1 从 manifest 中读取 applicationId null 从 manifest 中读取 testApplicationId null applicationId + “.test” testInstrumentationRunner null android.test.InstrumentationTestRunner signingConfig null null proguardFile N/A (set only) N/A (set only) proguardFiles N/A (set only) N/A (set only) 如果你在构建脚本中使用代码获取这些属性,那么第二列的值将非常重要。例如,你可能会写: if (android.defaultConfig.testInstrumentationRunner == null) { // assign a better default... } 如果值一直为 null ,那么在构建的时候将被替换成第 3 列的默认值,但是在 DSL 中没有包含该值,所以你无法查询到该 值。 除非真的有必要去设置属性的值,否则错误的值可能会阻碍 Gradle 解析应用的 manifest 文件。 Gradle Android Plugin 22Manifest 属性 默认情况下,Android Plugin 会自动给项目构建 debug 和 release 版本。两个版本的区别在于能否在安全设备上调试,以及 APK 如何签名。 debug 版采用通用的 name/password 对来自动创建的密钥证书进行签名(为了防止在构建过程中出现认证请求)。release 版在构建过程中不进行签名,需要稍后再进行签名。 这些配置是通过 BuildType 对象来完成的。默认情况下,两个实例都会被创建,分别是 debug 和 release Android plugin 允许像创建其他构建类型一样定制这两个实例。可以在 buildTypes 的 DSL 容器中完成: android { buildTypes { debug { applicationIdSuffix ".debug" } jnidebug.initWith(buildTypes.debug) jnidebug { packageNameSuffix ".jnidebug" jnidebugBuild true } } } 上面的代码片段实现了以下功能: 配置默认的 debug 构建类型: 设置包名为 .debug,以便能够在同一个设备上安装 debug 和 release 版的 apk 创建了名为 jnidebug 的新 BuildType,并且用 debug 构建类型的默认配置来初始化自身。 继续配置 jnidebug,可以构建 JNI 组件,并添加了不一样的包名后缀。 创建一个新的构建类型就是简单的在 buildTypes 标签下添加一个新的元素,并且通过调用 initWith() 或者直接使用闭包来 配置它。 以下是一些可能使用到的属性和默认值: 属性名 debug 类型的默认值 release 或其他类型默认值 debuggable true false jniDebugBuild false false renderscriptDebugBuild false false renderscriptOptimLevel 3 3 applicationIdSuffix null null versionNameSuffix null null signingConfig android.signingConfigs.debug null zipAlign false true runProguard false false proguardFile N/A (set only) N/A (set only) proguardFiles N/A (set only) N/A (set only) 构建类型 Gradle Android Plugin 23构建类型 除了以上属性外,Build Types 还会受项目源码和资源影响。 对于每一个 Build Type 都会自动创建一个匹配的 sourceSet。默认的路径为: src// 这意味着 BuildType 名称不能是 main 或者 androidTest(因为这两个是由 plugin 强制实现的),并且他们都必须是唯一的。 跟其他 sourceSet 设置一样,Build Type 的 source set 路径也可以重新定向: android { sourceSets.jnidebug.setRoot('foo/jnidebug') } 另外,每一个 Build Type 都会创建一个新的 assemble 任务。 assembleDebug 和 assembleRelease 在上面已经提到过,这里要讲的是它们从哪被创建。当 debug 和 release 构建类型 被预创建的时候,它们的 tasks 就会自动创建。 上面提到的 build.gradle 代码片段中也会实现 assembleJnidebug task,并且 assemble 会像依赖于 assembleDebug 和 assembleRelease 一样依赖于 assembleJnidebug。 提示:你可以在终端下输入 gradle aJ 去运行 assembleJnidebug task。 可能会使用到的情况: debug 模式下才用到的权限 自定义的 debug 实现 为 debug 模式使用不同的资源(例如,当资源的值由绑定的证书决定) BuildType 的代码和资源通过以下方式被使用: manifest 将被混合进 app 的 manifest 代码只是换了一个资源文件夹 资源将叠加到 main 的资源中,并替换已存在的资源。 Gradle Android Plugin 24构建类型 签名一个应用程序需要以下文件: keystore keystore密码 key的别名(alias) key密码 存储类型 位置,key 名,两个密码和存储类型一起组成了这个签名配置(SigningConfig) 默认情况下,debug 被配置成使用 debug keystore,debug keystore 使用默认的密码和默认 key 及默认的 key 密码。 debug keystore 的位于 $HOME/.android/debug.keystore ,如果文件不存在,则会自动创建。 debug Build Type(构建类型)会自动使用 debug 的 SigningConfig(签名配置)。 可以通过 signingConfigs DSL 容器来创建其他配置或者自定义内建的默认配置: android { signingConfigs { debug { storeFile file("debug.keystore") } myConfig { storeFile file("other.keystore") storePassword "android" keyAlias "androiddebugkey" keyPassword "android" } } buildTypes { foo { debuggable true jniDebuggable true signingConfig signingConfigs.myConfig } } } 以上代码片段修改了 debug keystore 的路径到项目的根目录下。在这个例子中,这将影响其他用到 debug 构建类型的构建 类型。 这里也创建了一个新的 Single Config(签名配置)和一个使用这个新签名配置的新的 Build Type(构建类型)。 注意:只有默认路径下的 debug keystore 不存在时才会自动创建。改变 debug keystore 的路径并不会在新路径下自 动创建 debug keystore。如果创建不同名的 SigningConfig,并使用默认的 debug keystore 路径,那么还是会在默认 路径下创建 debug keystore。换句话说,会不会自动创建是根据 keystore 的路径来判断,而不是配置的名称。 注意:虽然经常使用项目根目录的相对路径作为 keystore 的路径,但是也可以使用绝对路径,尽管这并不推荐(除了 自动创建出来的 debug keystore) 注意:如果将这些文件添加到版本控制,你可能不希望将密码直接写到这些文件。下面的 Stack Overflow 链接提供从 签名配置 Gradle Android Plugin 25签名配置 控制台或者环境变量中获取密码的方法: http://stackoverflow.com/questions/18328730/how-to-create-a-release- signed-apk-file-using-gradle 我们以后还会在这个指南中添加更多的详细信息。 Gradle Android Plugin 26签名配置 从 Gradle Plugin for ProGuard version 4.10 之后就开始支持 ProGuard。ProGuard 插件是自动添加进来的。如果 Build Type 的 minifyEnabled 属性被设置为 true,对应的 task 将会自动创建。 android { buildTypes { release { minifyEnabled true proguardFile getDefaultProguardFile('proguard-android.txt') } } productFlavors { flavor1 { } flavor2 { proguardFile 'some-other-rules.txt' } } } 发布版本将会使用它的 Build Type 中声明的规则文件,product flavor(定制的产品版本)将会使用对应的 flavor 中声明的规 则文件。 这里有两个默认的规则文件: proguard-android.txt proguard-android-optimize.txt 这两个文件都在 SDK 的路径下。使用 getDefaultProguardFile() 可以获取这些文件的完整路径。它们除了是否要进行优化之 外,其它都是相同的。 运行 ProGuard Gradle Android Plugin 27运行 ProGuard 你也可以通过修改 build.gradle 文件来使得构建过程中自动移除未使用过的资源。查看 Resource Shrinking 文档了解详细 信息。 清理资源 Gradle Android Plugin 28清理资源 Gradle 项目可以依赖于其它组件,这些组件可以是外部二进制包,或者是其它的 Gradle 项目。 依赖、Library 和多项目 Gradle Android Plugin 29依赖、Library 和多项目 包依赖 Gradle Android Plugin 30包依赖 配置一个外部的 jar 包依赖,你需要在 compile 配置中添加一个依赖。 dependencies { compile files('libs/foo.jar') } android { ... } 注意:dependencies DSL 标签是标准 Gradle API 中的一部分,所以它不属于 android 标签。 compile 配置将被用于编译 main application。里面的所有依赖都会被添加到编译 classpath 中,同时也会被打包最终的 APK。以下是添加依赖时可能用到的其他一些配置选项: compile 编译主 moudle androidTestCompile 编译主 moudle 的测试 debugCompile debug 类型的编译 releaseCompile release 类型的编译 因为不可能去构建一个没有关联任何 Build Type(构建类型)的 APK,所以 APK 默认配置了两个或两个以上的编译配 置:compile 和 Compile 。 创建一个新的 Build Type(构建类型)将会自动创建一个基于该名字的新配置。 如果 debug 版要用一个自定义库(为了反馈实例化的崩溃信息等),但 release 版不需要,又或者 debug、release 依赖于 同一个库的不同版本时, Compile 会非常有用。 本地包依赖 Gradle Android Plugin 31本地包依赖 Gradle 支持从 Maven 或 Ivy 仓库中拉取依赖文件。 首先必须将仓库添加到列表中,然后必须在依赖中声明 Maven 或 Ivy 声明的文件。 repositories { mavenCentral() } dependencies { compile 'com.google.guava:guava:11.0.2' } android { ... } 注意:mavenCentral()` 是指定仓库 URL 的简单方法。Gradle 支持远程和本地仓库。 注意:Gradle 会遵循依赖关系的传递性。这意味着如果一个依赖本身依赖于其它东西,这些东西也会一并被拉取回 来。 更多关于设置 dependencies 的信息,请参考 Gradle用户指南 和 DSL 文档。 远程包依赖 Gradle Android Plugin 32远程包依赖 Gradle 项目也可以通过使用多项目配置依赖于其它 Gradle 项目。 多项目配置的实现通常是在一个根项目路径下将所有项目作为子文件夹包含进去。 例如,给定以下项目结构: MyProject/ + app/ + libraries/ + lib1/ + lib2/ 我们可以定义3个项目。Gradle 将会按照以下名字映射它们: :app :libraries:lib1 :libraries:lib2 每一个项目都拥有自己的 build.gradle 文件来声明自己如何被构建。 另外,在根目录下还有一个 setting.gradle 文件用于声明所有项目。 这些文件的结构如下: MyProject/ | settings.gradle + app/ | build.gradle + libraries/ + lib1/ | build.gradle + lib2/ | build.gradle 其中 setting.gradle 的内容非常简单: include ':app', ':libraries:lib1', ':libraries:lib2' 该文件定义了哪一个文件夹下的是 Gradle 项目。 其中 :app 项目可能依赖于这些库,可以通过以下依赖配置声明: dependencies { compile project(':libraries:lib1') } 更多关于多项目配置的信息请参考 这里。 多项目设置 Gradle Android Plugin 33多项目设置 在上面的多项目配置中,:libraries:lib1 和 :libraries:lib2 可能是一个 Java 项目,并且 :app 这个 Android 项目将会使用它 们的 jar 包输出。 但是,如果你想要共享代码来访问 Android API 或者使用 Android 的资源,那么这些 Library 项目就不能是普通的 Java 项 目,而应该是 Android Library 项目。 Library 项目 Gradle Android Plugin 34Library 项目 Library 项目跟常规的 Android 项目很相似,只是有部分不同。 既然构建 Library 跟构建应用不同,那肯定用不同的插件,但是两个插件内部其实共享大部分同样的代码,且由同一个 jar 包 提供: com.android.tools.build.gradle buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.5.6' } } apply plugin: 'android-library' android { compileSdkVersion 15 } 这里创建了一个使用 API 15 编译的 Library 项目,并且 SourceSet、 dependencies(依赖关系)的配置方法与普通项目一 样,且同样支持自定义配置。 创建 Library 项目 Gradle Android Plugin 35创建 Library 项目 Library 项目 main 输出一个 .aar 包,包含编译文件(类似 jar 包或者 .so 文件)和资源文件(manifest,res,assets)。 Library 项目同样也可以独立于应用程序生成一个测试用的 apk 来测试。 标识 Task 同样适用于 Library 项目(assembleDebug,assembleRelease),因此在命令行构建项目没有什么不同。 至于其他的,Library 项目跟应用工程一样,它们都拥有 build type 和 product flavor ,也可以生成多个不同版本的 aar 。 大部分 Build Type 的配置不适用于 Library 项目。但可以根据 Library 项目 是否被其它项目使用 , 是否用来测试 来作为使用自定义 sourceSet 的条件,从而动态使用 Library 项目的资源。 普通项目和 Library 项目的区别 Gradle Android Plugin 36普通项目和 Library 项目的区别 引用 Library 项目与引用其他项目一样: dependencies { compile project(':libraries:lib1') compile project(':libraries:lib2') } 注意: 如果要引用多个 Library,那么引用的先后顺序将非常重要。这类似于旧的构建系统的 project.properties 文件 中的依赖顺序。 引用 Library 项目 Gradle Android Plugin 37引用 Library 项目 一般情况下一个库只会发布它的 release variant(变种)版本。这个版本将会被所有引用它的项目使用,而不管它们本身自 己构建了什么版本。这是由于 Gradle 的限制,我们正在努力解决这个问题,所以这只是临时的限制。 你可以控制哪一个 Variant 版本作为发行版: android { defaultPublishConfig "debug" } 注意这里的发布配置名称引用的是完整的 variant 版本名称。Relesae,debug 只适用于项目中没有其它 flavor(特性)时使 用。如果想要用其它使用了 flavor 的 variant 版本取代默认的发布版本,你可以: android { defaultPublishConfig "flavor1Debug" } 将 Library 项目的所有 variant 版本都发布也是可能的。我们计划在一般的 项目依赖项目 (类似于前面所述)情况下允许这种做 法,但是由于 Gradle 的限制(我们也在努力修复这个问题)现在还不太可能。 默认情况下没有开启发布所有 variant 版本功能,可以通过以下代码启用: android { publishNonDefault true } 发布多个 variant 版本意味着发布多个 aar 文件而不是一个 aar 文件包含所有 variant 版本。每个 aar 包都包含一个 variant 版本。 发布一个 variant 版本意味着构建一个可用的 aar 文件作为 Gradle 项目的输出文件。无论是发布到 maven 仓库,还是其它 项目需要创建该 Library 项目的依赖都可以使用到这个 aar。 Gradle 有 默认文件 的概念。当添加以下配置后就会自动使用: compile project(':libraries:lib2') 创建其它发布文件的依赖,你需要指定具体使用哪一个: dependencies { flavor1Compile project(path: ':lib1', configuration: 'flavor1Release') flavor2Compile project(path: ':lib1', configuration: 'flavor2Release') } 重要:注意已发布的 configuration 是一个完整的 variant 版本,其中包括了 build type,并且需要像上面一样被引用。 重要:当发布配置非默认时,Maven 发布插件将会发布其它 variant 版本作为扩展包(按分类器分类)。这里是指不 能真正的兼容发布到 Maven 仓库。你应该另外发布一个单一的 variant 版本到仓库中,或者允许发布所有配置以支持 跨项目依赖。 Library 项目发布 Gradle Android Plugin 38Library 项目发布 Gradle Android Plugin 39Library 项目发布 测试项目已经被集成到应用项目中,没有必要再专门建立一个测试项目。 测试 Gradle Android Plugin 40测试 Android Studio 1.1 添加了单元测试支持(实验性功能),详细请看 Unit testing support。本章的其余部分描述的是 “instrumentation tests”,利用 Instrumentation 测试框架可以构建一个独立的测试 APK 并运行在真实设备(或模拟器)中以 测试。 单元测试 Gradle Android Plugin 41单元测试 正如前面所提到的,紧邻 main sourceSet 的就是 androidTest sourceSet,默认路径在 src/androidTest/ 下。 在这个测试 sourceSet 中会构建一个使用 Android 测试框架,并且可以部署到设备上的测试 apk 来测试应用程序。这里面包 含单元测试,集成测试,和后续 UI 自动化测试。 节点会包含在测试构建过程中自动生成的测试 AndroidManifest.xml,但是你也可以自己创建一个 src/androidTest/AndroidManifest.xml 文件并添加其他组件。 下面的值可以用来配置测试应用,相当于配置 节点: testPackageName testInstrumentationRunner testHandleProfiling testfunctionalTest 正如前面所看到的,这些配置在 defaultConfig 对象中配置: android { defaultConfig { testPackageName "com.test.foo" testInstrumentationRunner "android.test.InstrumentationTestRunner" testHandleProfiling true testFunctionalTest true } } 在测试应用程序的 manifest 文件中, instrumentation 节点的 targetPackage 属性值会自动使用测试应用的包名设置,即使 这个名称是通过 defaultConfig 或者 Build Type 对象自定义的。这也是 manifest 文件需要自动生成的一个原因。 另外,这个测试 sourceSet 也可以拥有自己的依赖。 默认情况下,应用程序和他的依赖会自动添加到测试应用的 classpath 中,但是也可以通过以下来扩展: dependencies { androidTestCompile 'com.google.guava:guava:11.0.2' } assembleTest 不依赖于主要的 assemble task,所以要手动运行测试。 当测试运行时,assembleTest task 会自动运行, 并生成测试应用。 目前只有一个 Build Type 会被测试。默认情况下是 debug Build Type,可以通过以下代码进行自定义配置: android { ... testBuildType "staging" } 基本知识和配置 Gradle Android Plugin 42基本知识和配置 正如前面提到的,标志性 task connectedCheck 需要一个连接的设备来启动。这个过程依赖于 androidTest task,因此 androidTest task 将会运行。这个 task 将会执行下面内容: 确认应用和测试应用都被构建(依赖于 assembleDebug 和 assembleTest) 安装这两个应用 运行这些测试 卸载这两个应用 如果有多个连接设备,那么测试会并行在所有连接设备上。如果其中一个测试失败,不管在哪个设备都算测试失败。 所有测试结果都被保存为 XML 文档,路径为: build/androidTest-results (这类似于 JUnit 的运行结果保存在 build/test-results 中) 路径同样可以自定义配置: android { ... testOptions { resultsDir = "$project.buildDir/foo/results" } } android.testOptions.resultsDir 的值由 Project.file(String) 获得。 运行测试 Gradle Android Plugin 43运行测试 测试 Android Library 项目类似于测试应用项目。 唯一的不同点在于整个库(包括它的依赖)都是自动作为依赖库被添加到测试应用中。 结果就是测试 APK 不单只包含它的代码,还包含了 Library 项目以及它的所有依赖的代码。 Library 的 manifest 被组合到测试应用的 manifest 中(引用这个 Library 的其他项目作为容器)。 androidTest task 变为只执行安装(或者卸载)测试 APK(因为没有其它 APK 被安装)。 其它的部分都是相同的。 测试 Android Library 项目 Gradle Android Plugin 44测试 Android Library 项目 当运行单元测试的时候,Gradle 会输出一份 HTML 格式的报告以方便查看结果。 Android plugin 则将所有连接设备的测试报告都合并到一个 HTML 格式的报告文件中。 测试报告 Gradle Android Plugin 45测试报告 一个项目将会自动生成测试运行。默认位置为: build/reports/androidTests 类似于 JUnit 的报告所在位置 build/reports/tests ,其它的报告通常位于 build/reports/< plugin >/ 这个路径也可以通过以下方式自定义: android { ... testOptions { reportDir = "$project.buildDir/foo/report" } } 报告将会合并运行在不同设备上的测试结果。 独立项目 Gradle Android Plugin 46独立项目 在一个配置了多个应用项目和多个 Library 项目的多项目里,当同时运行所有测试的时候,只生成一个记录了所有测试报告 的文件可能是非常有用的。 为了实现这个目的,需要在同一个依赖文件(译注:指的是使用 android gradle 插件的依赖文件)中添加另一个插件。可以 通过以下方式添加: buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.5.6' } } apply plugin: 'android-reporting' 必须添加在项目的根目录下,例如,与 settings.gradle 文件同级目录的 build.gradle 文件中。 之后,在命令行中进入项目根目录,输入以下命令就可以运行所有测试并合并所有报告: gradle deviceCheck mergeAndroidReports --continue 注意:这里的 --continue 选项将允许所有测试,即使子项目中的任何一个测试运行失败都不会停止。如果没有这个选 项,其中一个测试失败则会终止所有测试的运行,此时部分项目可能还未执行测试。 多项目报告 Gradle Android Plugin 47多项目报告 Lint 支持,译者注:Lint 是一个可以检查 Android 项目中存在的问题的工具 从 0.7.0 版本开始,你可以为项目中一个特定的 variant(变种)版本运行 lint,也可以为所有 variant 版本都运行 lint。它将 会生成一个报告描述哪一个 variant 版本中存在着问题。 你可以通过以下 lint 选项配置 lint。通常情况下你只需要配置其中一部分,以下列出了所有可使用的选项: android { lintOptions { // set to true to turn off analysis progress reporting by lint quiet true // if true, stop the gradle build if errors are found abortOnError false // if true, only report errors ignoreWarnings true // if true, emit full/absolute paths to files with errors (true by default) //absolutePaths true // if true, check all issues, including those that are off by default checkAllWarnings true // if true, treat all warnings as errors warningsAsErrors true // turn off checking the given issue id's disable 'TypographyFractions','TypographyQuotes' // turn on the given issue id's enable 'RtlHardcoded','RtlCompat', 'RtlEnabled' // check *only* the given issue id's check 'NewApi', 'InlinedApi' // if true, don't include source code lines in the error output noLines true // if true, show all locations for an error, do not truncate lists, etc. showAll true // Fallback lint configuration (default severities, etc.) lintConfig file("default-lint.xml") // if true, generate a text report of issues (false by default) textReport true // location to write the output; can be a file or 'stdout' textOutput 'stdout' // if true, generate an XML report for use by for example Jenkins xmlReport false // file to write report to (if not specified, defaults to lint-results.xml) xmlOutput file("lint-report.xml") // if true, generate an HTML report (with issue explanations, sourcecode, etc) htmlReport true // optional path to report (default will be lint-results.html in the builddir) htmlOutput file("lint-report.html") // set to true to have all release builds run lint on issues with severity=fatal // and abort the build (controlled by abortOnError above) if fatal issues are found checkReleaseBuilds true // Set the severity of the given issues to fatal (which means they will be // checked during release builds (even if the lint target is not included) fatal 'NewApi', 'InlineApi' // Set the severity of the given issues to error error 'Wakelock', 'TextViewEdits' // Set the severity of the given issues to warning warning 'ResourceAsColor' // Set the severity of the given issues to ignore (same as disabling the check) ignore 'TypographyQuotes' } } Lint 支持 Gradle Android Plugin 48Lint 支持 新构建系统的一个目标就是允许为同一个应用创建不同的版本。 这里有两个主要的使用情景: 1. 同一个应用的不同版本。 例如一个免费的版本和一个收费的专业版本。 2. 同一个应用需要打包成不同的 apk 以发布 Google Play Store。 点击此处 查看更多详细信息。 3. 综合 1 和 2 两种情景。 这个目标就是要让在同一个项目里生成不同的 APK 成为可能,以取代以前需要使用一个库项目和两个或以上的应用项目分别 生成不同 APK 的做法。 构建 Variants(变种)版本 Gradle Android Plugin 49构建 Variants(变种)版本 Product flavor 可定义应用的不同定制版本,一个项目可以同时定义多个不同的 flavor 来改变应用的输出。 不同定制版本之间的差异非常小的情况,可以考虑使用 Product flavor。虽然项目最终会生成多个定制版本,但是它们本质上 都是同一个应用。这种做法可能是比使用 Library 项目更好的实现方式。 Product flavor 需要在 productFlavors 这个 DSL 容器中声明: android { .... productFlavors { flavor1 { ... } flavor2 { ... } } } 这里创建了两个flavor,名为 flavor1 和 flavor2。 注意:flavor 的命名不能与已存在的 Build Type 或者与 androidTest 的 sourceSet 有冲突。 产品定制 Gradle Android Plugin 50产品定制 正如前面章节所提到的,每一个 Build Type 都会生成一个新的 APK。 Product Flavors 同样也会做这些事情:项目的输出将会拼接所有可能的 Build Types 和 Product Flavors(如果有定义 Flavor)的组合。 每一种组合(包含 Build Type 和 Product Flavor)就是一个 Build Variant(构建变种版本)。 例如,在之前的 Flavor 声明例子中与默认的 debug 和 release 两个 Build Types 将会生成4个 Build Variants: Flavor1 - debug Flavor1 - release Flavor2 - debug Flavor2 - release 项目中如果没有定义 flavor 同样也会有 Build Variants,只是使用的是 default (默认)的 flavor/config, 同时默认的是没有 名字的,所以生成的 build variant 列表看起来就跟 Build Type 列表一样。 构建类型+产品定制=构建变种版本 Gradle Android Plugin 51构建类型+产品定制=构建变种版本 每一个 flavor 都是通过闭包来配置的: android { ... defaultConfig { minSdkVersion 8 versionCode 10 } productFlavors { flavor1 { packageName "com.example.flavor1" versionCode 20 } flavor2 { packageName "com.example.flavor2" minSdkVersion 14 } } } 注意 ProductFlavor 类型的 android.productFlavors.* 对象与 android.defaultConfig 对象的类型是相同的。就是说着它们 拥有的属性是一样的。 defaultConfig 为所有的 flavor 提供基本的配置,每一个 flavor 都可以重写这些配置的值。在前面的例子中,最终的配置结 果将会是: flavor1 packageName: com.example.flavor1 minSdkVersion: 8 versionCode: 20 flavor2 packageName: com.example.flavor2 minSdkVersion: 14 versionCode: 10 通常情况下,Build Type 的配置会覆盖其它的配置。例如,Build Type 的 packageNameSuffix 会被追加到 Product Flavor 的 packageName 上面。 但有部分设置可以同时在 Build Type 和 Product Flavor 中设置。在这种情况下,按照个别为主的原则决定。 例如,signingConfig 允许通过设置 android.buildTypes.release.signingConfig 来为所有的 release 包共用相同的 SigningConfig。也可以通过设置 android.productFlavors.*.signingConfig 来为每一个 release 包指定它们自己的 SigningConfig。 产品定制的配置 Gradle Android Plugin 52产品定制的配置 与 Build Type 类似,Product Flavor 也会通过它们自己的 sourceSet 提供代码和资源。 上面的例子将会创建4个 sourceSet: android.sourceSets.flavor1 位于 src/flavor1/ android.sourceSets.flavor2 位于 src/flavor2/ android.sourceSets.androidTestFlavor1 位于 src/androidTestFlavor1/ android.sourceSets.androidTestFlavor2 位于 src/androidTestFlavor2/ 这些 sourceSet 用于与 android.sourceSets.main 和 Build Type 的 sourceSet 来构建 APK。 下面的规则用于处理所有的 sourceSet 来构建一个 APK: 多个文件夹中的所有的源代码( src/*/java )都会合并起来生成一个输出。 所有的 Manifest 文件都会合并成一个 Manifest 文件。类似于 Build Type,允许 Product Flavor 可以拥有不同的的组件 和权限声明。 所有使用的资源(Android res 和 assets)遵循的优先级为 Build Type 会覆盖 Product Flavor,最终覆盖 main sourceSet 的资源。 每一个 Build Variant 都会根据资源生成自己的 R 类(或者其它一些源代码)。Variant 互相之间没有什么是共享的。 最终,类似 Build Type,Product Flavor 也可以有它们自己的依赖关系。例如,如果使用 flavor 来生成一个基于广告的应用 版本和一个付费的应用版本,其中广告版本可能需要依赖于广告 SDK,但是付费版不需要。 dependencies { flavor1Compile "..." } 在这个例子中, src/flavor1/AndroidManifest.xml 文件中可能需要声明访问网络的权限。 每一个 Variant 也会创建额外的 sourceSet: android.sourceSets.flavor1Debug 位于 src/flavor1Debug/ android.sourceSets.flavor1Release 位于 src/flavor1Release/ android.sourceSets.flavor2Debug 位于 src/flavor2Debug/ android.sourceSets.flavor2Release 位于 src/flavor2Release/ 这些 sourceSet 拥有比 Build Type 的 sourceSet 更高的优先级,并允许在 Variant 的层次上做一些定制。 源组件和依赖 Gradle Android Plugin 53源组件和依赖 我们前面提到每一个 Build Type 会创建自己的 assemble task,但是 Build Variant 是 Build Type 和 Product Flavor 的 组合。 当使用 Product Flavor 的时候,将会创建更多的 assemble-type task。分别是: 1. assemble 允许直接构建一个 variant 版本,例如 assembleFlavor1Debug。 2. assemble 允许构建指定 Build Type 的所有 APK,例如 assembleDebug 将会构建 Flavor1Debug 和 Flavor2Debug 两个 variant 版本。 3. assemble 允许构建指定 flavor 的所有 APK,例如 assembleFlavor1 将会构建 Flavor1Debug 和 Flavor1Release 两个 variant 版本。 另外 assemble task 会构建所有的 variant 版本。 构建和任务 Gradle Android Plugin 54构建和任务 测试 multi-flavors 项目非常类似于测试简单的项目。 androidTest 的 sourceSet 用于定义所有 flavor 共用的测试,但是每一个 flavor 也可以有它特有的测试。 正如前面提到的,每一个 flavor 都会创建自己的测试 sourceSet: android.sourceSets.androidTestFlavor1 位于 src/androidTestFlavor1/ android.sourceSets.androidTestFlavor2 位于 src/androidTestFlavor2/ 同样的,它们也可以拥有自己的依赖关系: dependencies { androidTestFlavor1Compile "..." } 这些测试可以通过主要的标志性 deviceCheck task 或者主要的 androidTest task(当 flavor 被使用的时候这个 task 相当于 一个标志性 task)来执行。 每个 flavor 也拥有自己的 task 来执行测试: androidTest 。例如: androidTestFlavor1Debug androidTestFlavor2Debug 同样的,每个 variant 版本也会创建对应的测试 APK 构建 task 和 安装或卸载 task: installFlavor1Debug assembleFlavor1Test installFlavor1Test uninstallFlavor1Debug ... 最终的 HTML 报告根据每个 flavor 的报告汇总而成。 下面是测试结果和报告文件的路径,每组第一个是每个 flavor 版本的结果,第二个是汇总结果: build/androidTest-results/flavors/ build/androidTest-results/all/ build/reports/androidTests/flavors build/reports/androidTests/all/ 改变 report 或 results 的输出文件夹都只会改变对应的根目录,构建时仍会创建每个 flavor 的文件夹,并且仍会汇总测试结 果以及报告文件。 测试 Gradle Android Plugin 55测试 某些情况下,应用可能需要基于多个标准来创建多个版本。 例如,Google Play 中的 multi-apk 支持 4 种过滤器。根据每个过滤器来创建不同的 APK 需要使用 Product Flavor 分组。 假如有个游戏有免费版和付费版,并且需要在 multi-apk 支持中使用 ABI 过滤器(译注:ABI,应用二进制接口,优点是不需 要改动应用的任何代码就能够将应用迁移到任何支持相同 ABI 的平台上)。该游戏应用需要 3 个 ABI 和两个特定版本,因此 就需要生成 6 个 APK(忽略不同 Build Types 生成的 variant 版本)。 然而,3 个 ABI 付费版的源代码都是相同的,因此创建 6 个 flavor 来实现并不是一个好办法。 相反的,可以使用两个 flavor 分组,并且让它自动构建所有可能的 variant 组合。 对应的功能实现需要使用 Flavor Dimensions(译注: Flavor Dimensions 对应旧版中的 Flavor Groups ),并将 flavor 分配 到一个指定的 Group 中。 android { ... flavorDimensions "abi", "version" productFlavors { freeapp { flavorDimension "version" ... } x86 { flavorDimension "abi" ... } } } andorid.flavorDimensions 数组按照先后排序定义了可能用到的分组。(示例中)每个 Product Flavor 都被分配到一个分 组中。 示例中将 Product Flavor 分为两组,为别为 abi [x86,arm,mips] 和 version [freeapp,paidapp],再加上默认的 Build Type [debug,release],最后会生成以下的 Build Variant: x86-freeapp-debug x86-freeapp-release arm-freeapp-debug arm-freeapp-release mips-freeapp-debug mips-freeapp-release x86-paidapp-debug x86-paidapp-release arm-paidapp-debug arm-paidapp-release mips-paidapp-debug mips-paidapp-release andorid.flavorDimensions 中元素的顺序非常重要(variant 命名和优先级等)。 每个 variant 版本的配置由几个 Product Flavor 对象决定: android.defaultConfig 多定制的变种版本 Gradle Android Plugin 56多定制的变种版本 一个来自 abi 组中的对象 一个来自 version 组中的对象 flavorDimensions 中的顺序决定了 flavor 的优先级,这对于资源来说非常重要,因为 flavor 中的值会替换定义在低优先级的 flavor 中的值。 flavor dimensions 使用最高的优先级定义,因此前面例子中的优先级为: abi > version > defaultConfig Multi-flavors 项目同样拥有额外的 sourceSet,类似于 variant 的 sourceSet,只是少了 Build Type: android.sourceSets.x86Freeapp 位于 src/x86Freeapp/ android.sourceSets.armPaidapp 位于 src/armPaidapp/ 等等... 这允许在 flavor-combination(组合 flavor)的层次上进行定制。它们拥有比最基本的 flavor 的 sourceSet 更高的优先级,但 是优先级低于 Build Type 的 sourceSet。 Gradle Android Plugin 57多定制的变种版本 高级构建的自定义 Gradle Android Plugin 58高级构建的自定义 构建选项 Gradle Android Plugin 59构建选项 android { compileOptions { sourceCompatibility = "1.6" targetCompatibility = "1.6" } } 默认值是 “1.6” 。该设置将会影响所有需要编译 Java 源代码的 task。 Java 编译选项 Gradle Android Plugin 60Java 编译选项 android { aaptOptions { noCompress 'foo', 'bar' ignoreAssetsPattern "!.svn:!.git:!.ds_store:!*.scc:.*:_*:!CVS:!thumbs.db:!picasa.ini:!*~" } } 这将会影响所有使用 aapt 的 task。 aapt 选项 Gradle Android Plugin 61aapt 选项 android { dexOptions { incremental false preDexLibraries = false jumboMode = false javaMaxHeapSize "2048M" } } 这将会影响到所有使用 dex 的 task。 dex 选项 Gradle Android Plugin 62dex 选项 一般的 Java 项目中有一组有限的 task 用于互相处理并最终生成一个输出。 classes 是一个编译 Java 源代码的 task。 可以在 build.gradle 文件中通过脚本很容易使用 classes task。classes 是 project.tasks.classes 的缩写。 相比之下在 Android 项目中这就有点复杂。因为 Android 项目中会有大量相同的 task,并且它们的名字基于 Build Types 和 Product Flavor 生成。 为了解决这个问题,android 对象有三个属性: applicationVariants(只适用于 app plugin) libraryVariants(只适用于 library plugin) testVariants(app、library plugin 均适用) 这三个属性会分别返回一个 ApplicationVariant 、 LibraryVariant 和 TestVariant 对象的 DomainObjectCollection。 注意,使用这三个 collection 中的其中一个都会触发生成所有对应的 task。这意味着使用 collection 之后不需要更改配置。 DomainObjectCollection 可以直接访问所有对象,或者通过过滤器进行筛选。 android.applicationVariants.each { variant -> .... } 这三个 variant 类都拥有下面的属性: 属性名 属性类型 说明 name String Variant 的名字,唯一 description String Variant 的描述说明 dirName String Variant 的子文件夹名,唯一。可能有不止一个子文件夹, 例如 “debug/flavor1” baseName String Variant 输出的基础名字,必须唯一 outputFile File Variant 的输出,该属性可读可写 processManifest ProcessManifest 处理 Manifest 的 task aidlCompile AidlCompile 编译 AIDL 文件的 task renderscriptCompile RenderscriptCompile 编译 Renderscript 文件的 task mergeResources MergeResources 合并资源文件的 task mergeAssets MergeAssets 合并 assets 的 task processResources ProcessAndroidResources 处理并编译资源文件的 task generateBuildConfig GenerateBuildConfig 生成 BuildConfig 类的 task javaCompile JavaCompile 编译 Java 源代码的 task processJavaResources Copy 处理 Java 资源的 task assemble DefaultTask Variant 的标志性 assemble task 操作 task Gradle Android Plugin 63操作 task ApplicationVariant 类还有以下附加属性: 属性名 属性类型 说明 buildType BuildType Variant 的 BuildType productFlavors List Variant 的 ProductFlavor,一般不为空但允许为空 mergedFlavor ProductFlavor android.defaultConfig 和 variant.productFlavors 的组合 signingConfig SigningConfig Variant 使用的 SigningConfig 对象 isSigningReady boolean 如果是 true 则表明该 Variant 已经具备了所有需要签名的信息 testVariant BuildVariant 将会测试该 Variant 的 TestVariant dex Dex 将代码打包成 dex 的 task。如果该 Variant 是 Library,该值可为空 packageApplication PackageApplication 打包最终 APK 的 task。如果该 Variant 是 Library,该值可为空 zipAlign ZipAlign 对 APK 进行 zipalign 的 task。如果该 Variant 是 Library 或者 APK 不能被签名时,该值可为空 install DefaultTask 负责安装的 task,可为空 uninstall DefaultTask 负责卸载的 task LibraryVariant 类还有以下附加属性: 属性名 属性类型 说明 buildType BuildType Variant 的 BuildType mergedFlavor ProductFlavor 只有 android.defaultConfig testVariant BuildVariant 用于测试 Variant packageLibrary Zip 用于打包 Library 项目的 AAR 文件。如果是 Library 项目,该值不能为空 TestVariant 类还有以下属性: 属性名 属性类型 说明 buildType BuildType Variant 的 Build Type productFlavors List Variant 的 ProductFlavor。一般不为空但允许为空 mergedFlavor ProductFlavor android.defaultConfig 和 variant.productFlavors 的组合 signingConfig SigningConfig Variant 使用的 SigningConfig 对象 isSigningReady boolean 如果是 true 则表明该 Variant 已经具备了所有需要签名的信息 testedVariant BaseVariant TestVariant 测试的 BaseVariant dex Dex 将代码打包成 dex 的 task。如果该 Variant 是 Library,该值可为 空 packageApplication PackageApplication 打包最终 APK 的 task。如果该 Variant 是 Library,该值可为空 zipAlign ZipAlign 对 APK 进行 zipalign 的 task。如果该 Variant 是 Library 或者 APK 不能被签名时,该值可为空 install DefaultTask 负责安装的 task,可为空 uninstall DefaultTask 负责卸载的 task connectedAndroidTest DefaultTask 在连接设备上执行 Android 测试的 task providerAndroidTest DefaultTask 使用扩展 API 执行 Android 测试的 task Gradle Android Plugin 64操作 task Android task 特有类型的 API: ProcessManifest File manifestOutputFile AidlCompile File sourceOutputDir RenderscriptCompile File sourceOutputDir File resOutputDir MergeResources File outputDir MergeAssets File outputDir ProcessAndroidResources File manifestFile File resDir File assetsDir File sourceOutputDir File textSymbolOutputDir File packageOutputFile File proguardOutputFile GenerateBuildConfig File sourceOutputDir Dex File outputFolder PackageApplication File resourceFile File dexFile File javaResourceDir File jniDir File outputFile 直接在 Variant 对象中使用 “outputFile” 可以改变最终的输出文件夹。 ZipAlign File inputFile File outputFile 直接在 Variant 对象中使用 “outputFile” 可以改变最终的输出文件夹。 每个 task 类型的 API 都受 Gradle 的工作方式和 Android plugin 的配置方式限制。 首先,Gradle 中存在的 task 只能配置输入输出的路径以及部分可能使用的选项标识。因此,task 只能定义一些输入或者输 出。 其次,这里面大多数 task 的输入都不是单一的,一般都混合了 sourceSet、Build Type 和 Product Flavor 中的值。保持构建 文件的简洁和可读性,同时让开发者通过 DSL 修改这些对象来影响构建的过程,而不是深入修改输入和 task 的选项。 另外需要注意,上面的 task 中除了 ZipAlign 这个 task 类型,其它类型都要求设置私有数据来让它们运行。这意味着不能手 动创建这些类型的新 task 实例。 这些 API 也可能会被修改。一般来说,目前的 API 是围绕着 task 的输入和输出入口来添加额外的处理(需要的时候)。欢 迎反馈意见,特别是那些没有预见过的需求。 对于 Gradle 的 task(DefaultTask,JavaCompile,Copy,Zip),请参考 Gradle 文档。 Gradle Android Plugin 65操作 task Coming soon. 对于 Gradle 的 task(DefaultTask,JavaCompile,Copy,Zip),请参考 Gradle 文档。 译注:官方的 Coming soon。不是翻译 Coming soon _(:зゝ∠)_ (话说 Android Studio 的 NDK 支持也 Coming soon 2年了) 构建类型和产物定制的属性引用 Gradle Android Plugin 66构建类型和产物定制的属性引用 使用 Android KitKat(API 19 版本的 buildTools)就可以使用 diamond operator,multi-catch,strings in switches,try with resource等等(译注:都是 JDK7 的一些新特性,详情请参考 JDK7 文档)。设置为 1.7 版本,需要修改你的构建文件: android { compileSdkVersion 19 buildToolsVersion "19.0.0" defaultConfig { minSdkVersion 7 targetSdkVersion 19 } compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 } } 你可以将 minSdkVersion 的值设置为 19 之前的版本,只是你只能使用除了 try with resources 之外的其它新语言特性。如果 你想要使用 try with resources 特性,你就需要把 minSdkVersion 也设置为 19。 sourceCompatibility 1.7 需要 Gradle 使用 1.7 或者更高版本的 JDK(Android Gradle plugin 也需要 0.6.1 或者更高的版 本)。 使用 sourceCompatibility 1.7 Gradle Android Plugin 67使用sourceCompatibility 1.7 附录 Gradle Android Plugin 68附录 基于 http://blog.csdn.net/maosidiaoxian/article/details/41719357 校对整理,感谢原文作者 貌似掉线 Android 应用都有自己的包名。包名是设备上每个应用程序的唯一标识,同样也是 Google Play 商店里的唯一标识。就是 说,假如你已经使用某个包名来发布应用,就不能再去改变应用的包名,因为这样做会导致你的应用被视为一个全新的应 用,你现有的用户也不会收到应用的更新通知。 旧版的 Android Gralde 构建系统中,应用的包名由 manifest 中根节点的 package 属性决定: AndroidManifest.xml: 然而,这里所定义的 package 还有另一个作用:用来命名资源类 R(以及用于解析相关的 Activity)。在上面的示例中,最 终生成的 R 类为 com.example.my.app.R,所以如果你在其他包中的代码需要引用资源,对应的 .java 文件需要导入 com.example.my.app.R 。 在新的 Android Gradle 构建系统中,你可以轻松地构建多个不同版本的应用。例如,你可以同时构建免费版和专业版的应用 (使用 flavor),并且它们在 Google Play 上也应该要有不同的包名,这样它们就能够在同一设备上安装并且能够单独购买 使用等等。同样的,你也可以构建 “debug”、“alpha”、“beta” 版的应用(使用 build type),它们也同样可以有唯一的包名。 同时,代码中引用的 R 类要保持不变;在构建不同版本的应用时,对应的(引用了 R 的) .java 源文件也不能改动。 因此,我们将包名的两种作用解耦: “application id” 对应 apk 中 manifest 定义的应用包名,同时用于设备以及 Google Play 的应用唯一标识。 “package” 用于在源码中引用 R 类以及解析注册相关的 activity/service,对应 Java 的包名概念。 你可以在 Gradle 文件中指定 application id,如下所示: app/build.gradle: apply plugin: 'com.android.application' android { compileSdkVersion 19 buildToolsVersion "19.1" defaultConfig { applicationId "com.example.my.app" minSdkVersion 15 targetSdkVersion 19 versionCode 1 versionName "1.0" } ... 像以前一样,你需要像前面的 AndroidManifest.xml 示例在 Manifest 中指定给代码用的 “package”。 关键部分:参照上面的做法,即能解耦 applicationId 和 package。意思是你能够完全自由地重构你的代码,改变用于 Activity 和 Service 的内部包,改变 Manifest 的 package,重构导入语句。这都不会影响到 app 的最终 id,app 的 id 对应 Gradle 文件中 applicationId 的值。 ApplicationId 与 PackageName Gradle Android Plugin 69ApplicationId 与 packageName 你可以通过以下的 Gradle DSL 方法来为不同的 flavor 和 build type 定义不同的 applicationId: app/build.gradle: productFlavors { pro { applicationId = "com.example.my.pkg.pro" } free { applicationId = "com.example.my.pkg.free" } } buildTypes { debug { applicationIdSuffix ".debug" } } .... (在 Android Studio 中,你可以通过 Project Structure 图形化界面来进行这些配置。) 注意:出于兼容性考虑,如果没有在 build.gradle 文件中定义 applicationId,那么 applicationId 将默认为 AndroidManifest.xml 中所指定的 package 的值。在这种情况下,applicationId 和 package 显然未解耦,此时重构代码也将 会更改应用的 id !在 Android Studio 中,新建的项目会指定这两个值。 注意:package 始终必须在默认 AndroidManifest.xml 文件中指定。如果存在多个 manifest(例如一个 flavor 有特定的 manifest 或一个 buildType 有特定的 manifest),package 可不指定,但如果被指定,必须和主 manifest 中指定的 package 完全相同。 Gradle Android Plugin 70ApplicationId 与 packageName

下载文档,方便阅读与编辑

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享文档获得金币 ] 0 人已下载

下载文档

相关文档