关闭

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

标签: Android官方文档Android技术文档Gradle插件用户指南Gradle Android用户指南Gradle Android教程
16832人阅读 评论(9) 收藏 举报
分类:

不知道是什么网络问题,上午一直发不了博客,其他页面基本正常,就是在写博客这里,每次打开都是响应超时。刚才用了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 插件用户指南

简介

本文档是 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 链接显示了如何从控制台或环境变量中读取值的方法。
我们会在以后更新本指南补充更详细的信息。

运行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()将返回的文件的完整路径。它们除了是否启用优化之外,其它都是相同的。

27
1

猜你在找
深度学习基础与TensorFlow实践
【在线峰会】前端开发重点难点技术剖析与创新实践
【在线峰会】一天掌握物联网全栈开发之道
【在线峰会】如何高质高效的进行Android技术开发
机器学习40天精英计划
Python数据挖掘与分析速成班
微信小程序开发实战
JFinal极速开发企业实战
备战2017软考 系统集成项目管理工程师 学习套餐
Python大型网络爬虫项目开发实战(全套)
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:1776064次
    • 积分:12675
    • 等级:
    • 排名:第985名
    • 原创:128篇
    • 转载:3篇
    • 译文:74篇
    • 评论:807条
    QQ群
    博客专栏
    最新评论
    欢迎访问我的博客
    我的公众号
    微信关注我的公众号
    站长统计