• 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 插件用户指南

    简单介绍

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

    新构建系统的目标

    新的构建系统的目标是:
    • 能够非常easy地重用代码和资源
    • 能够非常easy地创建应用程序的几个变种,不管是多APK分发还是不同定制版的应用程序
    • 能够非常easy地配置、 扩展和自己定义构建过程
    • 好的 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 server上使用的。
    • 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 怎么签名。

    调试版本号使用自己主动创建的密钥/证书签名,而且密钥/证书的username/password是已知的(以防止构建过程中须要相关的信息)的。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 的password
    • 一个 key 的别名
    • 一个 key 的password
    • 存储类型
    签名文件的位置,key的名称,以及这两个password和存储类型,一起构成了一个签名配置 ( SigningConfig类型) 

    默认情况下,有一个debug的配置,配置使用了一个debug keystore。这个keystore使用了一个已知的key和一个已知的password。 
    这个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)。

    注意: 假设您将这些文件增加版本号控制,您可能不希望这些文件里有你的password。以下的 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()将返回的文件的完整路径。它们除了是否启用优化之外,其他都是同样的。

  • 相关阅读:
    【洛谷】NOIP提高组模拟赛Day2【动态开节点/树状数组】【双头链表模拟】
    【10.7校内测试】【队列滑窗】【2-sat】【贪心+栈二分+线段树(noip模拟好题)】【生日祭!】
    【10.6校内测试】【小模拟】【hash+线段树维护覆盖序列】
    【洛谷】NOIP提高组模拟赛Day1【组合数学】【贪心+背包】【网络流判断是否满流以及流量方案】
    【10.5校内测试】【DP】【概率】
    【洛谷】1174:打砖块
    【10.4校内测试】【轮廓线DP】【中国剩余定理】【Trie树+博弈】
    【10.3校内测试【国庆七天乐!】】【DP+组合数学/容斥】【spfa多起点多终点+二进制分类】
    【二分图】性质
    【9.23校内测试】【抽屉原理】【乱搞??(找众数】【Trie】
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4492212.html
Copyright © 2020-2023  润新知