首页 > 代码库 > Android官方技术文档翻译——Gradle 插件用户指南(1-3)

Android官方技术文档翻译——Gradle 插件用户指南(1-3)

不知道是什么网络问题,上午一直发不了博客,其他页面基本正常,就是在写博客这里,每次打开都是响应超时。刚才用了VPN,顺便试了一下,居然可以编辑。想是CDN之类的问题吧。

这次翻译的是Gradle 插件用户指南,也就是Gradle上的Android插件的官方文档。文档很长,加上最近激情不够,翻译得有些慢。到昨天为止,才译到第四章。今天先发前三章。

本文译自Android官方技术文档《Gradle Plugin User Guide》,原文地址:http://tools.android.com/tech-docs/new-build-system/user-guide。

翻译不易,转载请注明CSDN博客上的出处:

http://blog.csdn.net/maosidiaoxian/article/details/41944325

翻译工作耗时费神,如果你觉得本文翻译得还OK,请点一下“顶”,我在精神上会倍受鼓励的,谢谢。翻译如有错讹,敬请指正。


Gradle 插件用户指南

目录

  1. 简介
    1. 1.1 新构建系统的目标
    2. 1.2 为什么是 Gradle ?
  2. 要求
  3. 基本项目
    1. 3.1 简单的构建文件
    2. 3.2 项目结构
      1. 3.2.1 配置项目结构
    3. 3.3 构建任务
      1. 3.3.1 常规任务
      2. 3.3.2 Java 项目任务
      3. 3.3.3 Android 任务
    4. 3.4 基本生成的自定义
      1. 3.4.1 清单条目
      2. 3.4.2 Build Types
      3. 3.4.3 签名配置
      4. 3.4.4 执行混淆
  4. 依赖、 Android Library和多项目设置
    1. 4.1 二进制包的依赖
      1. 4.1.1 本地包
      2. 4.1.2 远程文件
    2. 4.2 多项目设置
    3. 4.3 Library项目
      1. 4.3.1 创建一个 Library 项目
      2. 4.3.2 普通项目和Library 项目之间的区别
      3. 4.3.3 引用Library项目
      4. 4.3.4 Library项目的发布
  5. 测试
    1. 5.1 基础知识和配置
    2. 5.2 运行测试
    3. 5.3 测试 Android Library
    4. 5.4 测试报告
      1. 5.4.1 单个项目
      2. 5.4.2 多项目报告
    5. 5.5 Lint 的支持
  6. Build Variants
    1. 6.1 Product flavors
    2. 6.2 Build Type + Product Flavor = Build Variant
    3. 6.3 Product Flavor 配置
    4. 6.4 Sourcesets 和 Dependencies
    5. 6.5 Building 和 Tasks
    6. 6.6 测试
    7. 6.7 Multi-flavor variants
  7. 高级构建自定义
    1. 7.1 构建选项
      1. 7.1.1 Java 编译选项
      2. 7.1.2 aapt 选项
      3. 7.1.3 dex 选项
    2. 7.2 操纵任务
    3. 7.3 BuildType 和 Product Flavor 的属性引用
    4. 7.4 使用 sourceCompatibility 1.7

简介

本文档是 Gradle 插件 0.9 版本的文档。在 1.0 之前,我们所介绍的早期版本可能由于不兼容问题会有所不同。

新构建系统的目标

新的构建系统的目标是:
  • 可以很容易地重用代码和资源
  • 可以很容易地创建应用程序的几个变种,无论是多APK分发还是不同定制版的应用程序
  • 可以很容易地配置、 扩展和自定义构建过程
  • 好的 IDE 集成

为什么是 Gradle ?

Gradle 是一个先进的构建系统和构建工具,它允许通过插件创建自定义的构建逻辑。

基于Gradle的以下特点,我们选择了它: 
  • 域特定语言 (DSL) 来描述和处理构建逻辑
  • 构建文件基于 Groovy ,并允许通过 DSL来混合声明性元素,以及使用代码来处理 DSL 元素以提供自定义逻辑。
  • 基于 Maven 和 Ivy 的内置依赖管理。
  • 非常灵活。允许使用最佳实现,但并不强制自己的实现方式。
  • 插件可以提供自己的 DSL 和API供构建文件使用。
  • 良好的Tooling API 供 IDE 集成

要求

  • Gradle 版本需要 1.10,1.11或 1.12。插件版本需要 0.11.1
  • SDK Build Tools版本要求为 19.0.0。某些功能可能需要更高版本。

基本项目

Gradle 项目在项目的根文件夹里的build.gradle文件中描述它的构建逻辑。

简单的构建文件

最简单的 纯Java项目的build.gradle如下所示:

apply plugin: ‘java‘

这里配置使用了Gradle内置的 Java 插件。该插件提供用于构建并测试 Java 应用程序所需要的东西。

最简单的 Android 项目的 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"
}

在这个 Android 构建文件中,有3个主要部分: 

buildscript { ... }配置了驱动构建的代码。 
在上面的这种情况中,它声明了使用 Maven 中央库,并且对一个Maven 文件有一个类路径依赖。这个文件是包含 Gradle Android 插件的 0.11.1版本的库 
注: 这只会影响运行构建的代码,不会影响项目的源代码。项目本身需要定义它自己的仓库和依赖关系。稍后会提及这部分。

然后,和先前的提到的 Java 插件一样,这里配置使用了 android插件。 

最后, android { ... }配置了用于 android 构建的所有参数。这是Android DSL的入口。
默认情况下,只需要配置编译目标,以及build-tools的版本。它通过compileSdkVersionbuildtoolsVersion属性来完成。
编译目标相当于旧的构建系统中project.properties 文件内的target属性。这个新的属性可以设置为一个 int 值 (表示api 级别),或者是和以前的target的值一样,设置为字符串。

重要提示:你应该只配置使用这个android插件。如果同时配置使用了java插件也会导致构建错误。

注:您还需要一个local.properties文件,通过sdk.dir属性来设置 SDK 的位置,并且所设置的这个SDK要求存在。 
或者,您也可以设置一个ANDROID_HOME环境变量。这两种方法之间没什么差别,你喜欢,你选择。

项目结构

上述的基本构建文件要求有一个默认的文件夹结构。Gradle 遵循约定大于配置的概念,在可能的情况下提供了合理的默认选项值。

基本项目开始于两个名为“source sets”的组件。即主源代码和测试代码。它们分别在:
  • src/main/
  • src/androidTest/
里面的每个文件夹中都存在对应的源代码组件的文件夹。
对于 Java 和 Android 插件,Java 源代码和 Java 资源的位置如下: 
  • java/
  • resources/
对于Android 插件,Android所特有的额外的文件和文件夹是:
  • AndroidManifest.xml
  • res/
  • assets/
  • aidl/
  • rs/
  • jni/
注: src/androidTest/AndroidManifest.xml是不需要的,因为它会被自动创建。

配置项目结构

When the default project structure isn’t adequate, it is possible to configure it. 根据 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 插件使用类似的语法,但因为它使用它自己的sourceSets,所以在android对象里面来实现。 
这里有一个例子,使用旧的项目结构的主源码并重新映射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和 java 资源) 都放在相同的文件夹中,我们需要重新映射sourceSet的所有这些新组件到相同的src文件夹中。
注意: setRoot()会将整个sourceSet (和它的子文件夹) 移到一个新的文件夹中。这将移动src/androidTest/*tests/*
下。这是 Android 专用的,不适用于 Java sourceSets。 

这也是一个“迁移”的例子。

构建任务

常规任务

在构建文件中配置使用一个插件,将自动创建一系列要运行的构建任务。Java 插件和 Android 插件都是。
约定的任务如下:
  • assemble
    组装项目的输出的任务
  • check
    运行所有检查的任务。
  • build
    这个任务将执行assemblecheck
  • clean
    这个任务将清理项目的输出
assemblecheckbuild这些任务,实际上不做任何事情。他们是锚记任务,用于让插件添加实际的任务去做这些事情。这允许您能够调用同样的任务,无论项目的类型是什么,或者是配置使用了什么插件 


例如,配置使用findbugs插件将创建一个新的任务和使check任务依赖于它,使得每当调用check任务时都会调用到它。

您可以从命令行中运行下面的命令来获取更高级别的任务: 
gradle tasks

下面的命令可以得到一个完整的任务列表,并且看到任务运行之间的依赖关系:
gradle tasks --all

注: Gradle 会自动监视一个任务所声明的输入和输出。
在没有变化的情况下,运行两次build会使 Gradle 报告所有任务为UP-TO-DATE状态,这个状态意味着没有任何事情需要执行。这允许任务正确地相互依赖而无需不必要的构建操作。

Java 项目任务

Java 插件主要创建两个任务,它们是主要锚记任务的依赖任务:
  • assemble
    • jar
      这个任务将创建输出。
  • check
    • test
      这个任务将运行测试。
jar任务本身会直接或间接地依赖其他任务: 例如,classes任务用于编译 Java 代码。
testClasses任务用于编译测试,但它很少会被调用,因为test任务依赖于它 (以及classes任务)。

一般情况下,你将可能永远只调用assemblecheck,而无视其他任务。 

在这里,你可以看到Java 插件的所有任务和对它们的描述。

Android 任务

Android 的插件使用相同的约定配置以兼容其他插件,并添加了另外的锚记任务:
  • assemble
    组装项目的输出的任务
  • check
    运行所有检查的任务。
  • connectedCheck
    运行需要一个已连接的设备或模拟器的检查。它们将在所有已连接的设备上并行运行。
  • deviceCheck
    使用 API 连接到远程设备运行检查。这一个是在 CI 服务器上使用的。
  • build
    这项任务将执行assemble 和 check
  • clean
    这个任务将清理项目的输出
新的锚记任务是有必要的,以便能够运行定期的检查而无需连接的设备。
注意到,build任务不依赖于deviceCheckconnectedCheck

Android 项目具有至少两个输出: debug版本的APK 和release版本的 APK。这里的每一个输出都有自己的锚记任务,以便单独构建它们: 
  • assemble
    • assembleDebug
    • assembleRelease
它们两个都依赖于执行构建一个 APK所需的多个步骤的其他任务。assemble任务取则依赖于这两个任务,所以调用 assemble 将会构建出这两个 APKs。

提示:在命令行上,Gradle 支持任务名称的驼峰命名法的简写。例如: 
gradle aR
相当于输入
gradle assembleRelease
只要没有其他任务匹配 “aR” 

check锚记任务有它们自己的依赖项: 
  • check
    • lint
  • connectedCheck
    • connectedAndroidTest
    • connectedUiAutomatorTest (暂未实现)
  • deviceCheck
    • 这个任务依赖于当其他插件实现了测试扩展点时创建的任务。
最后,该插件为所有构建类型 (debugreleasetest)创建了omstal/uninstall 任务,只要他们可以被安装(需要签名)。

基本的构建定制

Android 插件提供了大量的 DSL,以通过构建系统直接地自定义大部分事情。

清单条目

通过 DSL 可以配置以下清单条目:
  • minSdkVersion
  • targetSdkVersion
  • versionCode
  • versionName
  • applicationId (有效的包名 —— 更多的信息请参阅ApplicationId 与packageName)
  • 用于测试应用程序的包名
  • Instrumentation test runner
示例:

android {
    compileSdkVersion 19
    buildToolsVersion "19.0.0"

    defaultConfig {
        versionCode 12
        versionName "2.0"
        minSdkVersion 16
        targetSdkVersion 16
    }
}

android元素的内部的defaultConfig元素是定义所有这些配置的地方。

以前版本的 Android 插件使用packageName来配置清单的“packageName”属性。
从 0.11.0开始,你应该在 build.gradle 中使用 applicationId 来配置清单中的“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() 的 getter 方法,而不是自定义的方法。

如果一个属性未通过 DSL 来设置,它将使用默认值。下表描述了对于未设置的属性的处理方式。
 属性名称 DSL 对象中的默认值 默认值
 versionCode -1 如果在清单中存在,则使用清单中的值
 versionName null 如果在清单中存在,则使用清单中的值
 minSdkVersion -1 如果在清单中存在,则使用清单中的值
 targetSdkVersion -1 如果在清单中存在,则使用清单中的值
 applicationId null 如果在清单中存在,则使用清单中的值
 testApplicationId null applicationId + “.test”
 testInstrumentationRunner null android.test.InstrumentationTestRunner
 signingConfig null null
 proguardFile N/A (只设置) N/A (只设置)
 proguardFiles N/A (只设置) N/A (只设置) 


第二列的值是很重要的,如果您在构建脚本中使用自定义逻辑查询这些属性的话。例如,您可以编写:
if (android.defaultConfig.testInstrumentationRunner == null) {
    // assign a better default...
}

如果值仍然为null,那么在构建的时候它将会被设为第三列中的实际默认值,但是由于 DSL 元素不包含此默认值,因此您无法查询它。
这是为了防止解析应用程序的清单,除非真的很需要。

构建类型

默认情况下,Android 插件自动将项目设置为生成应用程序的的debug和release版本。
这两个版本的不同,大多是围绕在调试一个安全的(非开发版的)设备的能力,以及 apk 怎么签名。

调试版本使用自动创建的密钥/证书签名,并且密钥/证书的用户名/密码是已知的(以防止构建过程中需要相关的信息)的。release版本在构建的时候不会进行签名,需要在之后进行签名。

这个配置是通过一个叫BuildType的对象来完成的。默认情况下,2 个实例会被创建,分别是debug版和release版。

Android 插件允许自定义这两个实例,以及创建其他的构建类型。它通过buildTypes DSL 容器来实现:

android {
    buildTypes {
        debug {
            applicationIdSuffix ".debug"
        }

        jnidebug.initWith(buildTypes.debug)
        jnidebug {
            packageNameSuffix ".jnidebug"
            jniDebuggable true
        }
    }
}

上面的代码段可实现以下操作:
  • 配置默认的Debug Build Type
    • 设置包名为<app appliationId>.debug,以便能够在相同的设备上安装debugrelease两个版本的apk
  • 创建一个叫jnidebug的新的BuildType对象 ,并将其配置为debug生成类型的一个副本。
  • 通过启用 JNI 组件的debug构建,并添加不同的包后缀,继续配置jnidebug
创建新的 Build Types 就是简单地在buildTypes下添加一个新的元素,然后调用 initWith()或者是使用一个闭包来配置。

以下是可能用到的属性和它们的默认值: 

 属性名称 用于 debug的默认值 用于 release/其他 的默认值
 debuggable true false
 jniDebuggable false false
 renderscriptDebuggable false false
 renderscriptOptimLevel 3 3
 applicationIdSuffix null null
 versionNameSuffix null null
 signingConfig android.signingConfigs.debug null
 zipAlignEnabled false true
 minifyEnabled false false
 proguardFile N/A (只设置) N/A (只设置)
 proguardFiles N/A (只设置) N/A (只设置)


除了这些属性,Build Types还会影响到构建的代码和资源。
对每个Build Type都会创建一个自动匹配的sourceSet,默认位置为 
src/<buildtypename>/
这意味着Build Type的名字不能为main或者是androidTest (这是插件所强制的),并且它们之间必须是唯一的。

与任何其他source set一样,生成类型的source set的位置也是可以重新设置的: 
android {
    sourceSets.jnidebug.setRoot(‘foo/jnidebug‘)
}
此外,对于每个Build Type,会创建一个新的assemble<BuildTypeName>任务。 

已经提到过的assembleDebugassembleRelease这两个任务,这里也会讲一下它们是怎么来的。当debugreleaseBuild Types被预创建的时候,他们的任务也会被自动创建。然后,

上面的build.gradle片段也会生成一个assembleJnidebug任务,并且assemble将会依赖于它,就像它依赖于assembleDebugassembleRelease任务一样。 

提示: 请记住您可以输入gradle aJ来运行assembleJnidebug任务。

可能会用到的情况: 
  • release模式下不需要,但debug模式下需要的权限
  • 自定义的debug实现
  • 为调试模式使用不同的资源 (例如某个资源的值与签名证书相绑定时)。
BuildType的代码和资源通过以下方式被使用:
  • manifest将被合并到应用程序的manifest中
  • 代码只是作为另一个源文件夹来起作用
  • 资源将覆盖main里面的资源,并替换已经存在的值。

签名配置

对应用程序进行签名,要求如下:
  • 一个 keystore
  • 一个 keystore 的密码
  • 一个 key 的别名
  • 一个 key 的密码
  • 存储类型
签名文件的位置,key的名称,以及这两个密码和存储类型,一起构成了一个签名配置 ( SigningConfig类型) 

默认情况下,有一个debug的配置,配置使用了一个debug keystore。这个keystore使用了一个已知的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的位置修改为在项目的根位置下。这会自动影响到任何设置为使用它的Build Types,在这里,影响到的是debug Build Type

代码的代码还创建了一个新的Signing Config和使用新配置的新的Build Type 。

注:只有位于默认位置下的debug keystores才会被自动创建。如果debug keystore的位置被更改了,它将不会在需要时自动创建。创建一个使用一个不同的名称SigningConfig,但使用了默认的debug keystore的路径,它也会被自动创建。换句话说,会不会被自动创建与keystore的路径有关,而与配置名称无关。

注: keystore的路径通常使用项目根目录的相对路径,但也可以是使用绝对路径,尽管这不推荐 (除了自动创建的debug keystore)。

注意: 如果您将这些文件加入版本控制,您可能不希望这些文件中有你的密码。下面的 Stack Overflow 链接显示了如何从控制台或环境变量中读取值的方法。
http://stackoverflow.com/questions/18328730/how-to-create-a-release-signed-apk-file-using-gradle
我们会在以后更新本指南补充更详细的信息。

运行ProGuard

ProGuard 是通过 Gradle plugin for ProGuard version 4.10来进行支持的。ProGuard 插件会被自动配置使用,并且如果Build Type通过minifyEnabled属性配置为运行ProGuard,对应的任务将被自动创建。

android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFile getDefaultProguardFile(‘proguard-android.txt‘)
        }
    }

    productFlavors {
        flavor1 {
        }
        flavor2 {
            proguardFile ‘some-other-rules.txt‘
        }
    }
}

变种使用他们的构建类型中所声明的规则文件,product flavors(定制版本)则使用flavor中声明的规则文件。

这里有 2 个默认的规则文件
  • proguard-android.txt
  • proguard-android-optimize.txt
它们位于 SDK 中。使用getDefaultProguardFile()将返回的文件的完整路径。它们除了是否启用优化之外,其它都是相同的。

Android官方技术文档翻译——Gradle 插件用户指南(1-3)