标签:
Gradle是一个基于Java(JVM)平台的构建体系(build system),它的一些特性:
讲一个概念closure(闭包),此处不讲Groovy的语法,深入学习Groovy
closure是被包装成对象的一段代码块,它可以像方法那样传入参数并返回一个值; 
表现形式如下:
{ [closureParameters -> ] statements }
1、简单声明
// Groovy object iteration
list.each { item -> /* do something with item */ }
2、利用赋值声明
def printer = { line -> println line }
3、应用方法作为closure
//利用reference.&操作符
class SizeFilter {
    Integer limit
    boolean sizeUpTo(String value) {
        return value.size() <= limit
    }
}
SizeFilter filter6 = new SizeFilter(limit:6)
Closure sizeUpTo6 = filter6.&sizeUpTo
def adder = { x, y -> return x+y }
assert adder(4, 3) == 7
assert adder.call(2, 6) == 8
//在Groovy构建脚本中,方法调用可以写成如下形式
method argOne, keyOne: valueOne, argTwo, keyTwo: valueTwo, argThree
//Groovy‘s runtime将解释为:
method([keyOne: valueOne, keyTwo: valueTwo], argOne, argTwo, argThree)
//最终将会调用有如下签名的方法
def method(Map m, argOne, argTwo, argThree)
/**
*方法void buildscript(Closure configureClosure)将
*closure作为参
*/
buildscript {
        repositories {
        jcenter()
        }
        dependencies {
            /**
            *方法Dependency add(String configurationName,  
            *Object dependencyNotation)接受参数
            */
           classpath ‘com.android.tools.build:gradle:2.1.0‘
        }
    }
Groovy脚本会被编译成类。举例如下: 
相对于传统的Java类,一个包含main方法的Groovy类可以如下书写:
class Main {                                    
    static void main(String... args) {          
        println ‘Groovy world!‘                 
    }
}
和Java一样,程序会从这个类的main方法开始执行,这是Groovy代码的一种写法,实际上执行Groovy代码完全可以不需要类或main方法,所以更简单的写法如下:
println ‘Groovy world!‘
上面这两中写法其实是一样的,具体我们可以通过如下命令进行编译为class文件:
import org.codehaus.groovy.runtime.InvokerHelper
class Main extends Script {                     
    def run() {                                 
        println ‘Groovy world!‘                 
    }
    static void main(String[] args) {           
        InvokerHelper.runScript(Main, args)     
    }
}
可以看见,上面我们写的groovy文件编译后的class其实是Java类,该类从Script类派生而来(查阅API);可以发现,每个脚本都会生成一个static main方法,我们执行groovy脚本的实质其实是执行的这个Java类的main方法,脚本源码里所有代码都被放到了run方法中,脚本中定义的方法(该例暂无)都会被定义在Main类中。
Gradle脚本是配置脚本(configuration scripts),当脚本执行的时候会创建一个关联对象(delegate object of script)。比如说,构建脚本(build script)执行的时候,它会配置关联对象project。
| Type of script | Delegates to instance of | 
|---|---|
| Init script | Gradle | 
| Build script | Project | 
| Settings script | Settings | 
构建初始化时创建,整个构建执行过程中只有这么一个对象,一般很少去修改这个默认配置脚本
每个settings.gradle会转换成一个Settings对象
在Gradle中每个build.gradle对应一个Project对象,每个Project在构建的时候都包含一系列Task。
在脚本中可以使用关联对象(project、Gradle、settings)的属性(properties)和方法(methods),因为Gradle脚本实现了接口Script,所以接口Script的属性和方法也可以在脚本中使用
所谓的我们编写Gradle脚本,实质大多数时候都是在编写构建脚本Build script,所以说 Project和Script对象的属性和方法等API非常重要。
所有的Gradle脚本都会实现Script接口,编译后的Script类会实现这个接口,接口Script的properties和methods可以在Gradle脚本中使用;
通常会有一个关联对象与Script对象关联;举例来说,一个构建脚本会将Project对象与它关联,一个初始化脚本会将Gradle对象与它关联,任何properties或者方法在Script对象中找不到,就需要去它的关联对象中去找。
生命周期(lifecycle)
一个project在构建时都具备如下流程:
创建一个Settings实例。
评估settings.gradle脚本,通过该文件配置刚才创建的Settings实例。
通过创建好的Settings实例创建Project实例的层级结构。
最后通过上面创建的Project实例去执行每个Project对应的build.gradle脚本。
Tasks
project是一个task的集合,每一个task完成一份基本的工作(比如说编译类,进行单元测试)
dependencies
project为完成工作需要建立多个依赖关系,dependencyHandler用来管理dependencies; 
这些依赖关系可以存在于configurations和从repositories中获取。
plugins
插件可以用来模块化和复用project configuration,通过PluginAware.apply()来运用plugin;
properties和methods
在脚本中可以使用接口project的任何方法和属性
Gradle支持单一或多个projects,在初始化的时候,Gradle决定哪些projects参与构建,并为每一个project创建一个Project实例;实质为执行settings.gradle.
在这个时期,Project对象完成配置,将整个build的Project和task的关系确定,建立有向图来确定task间的依赖关系,实质为解析所有参与构建的projects的build.gradle;
Gradle开始执行选定的tasks及其依赖tasks,完成目标的构建;
构建脚本是由语句、代码块组成。
语句包括方法调用、属性赋值、变量定义;
代码块是调用以闭包(closure)为参数的方法;在执行的时候,闭包参数会配置相应的关联对象
Android Plugin for Gradle, Revision 2.1.0
Gradle和Android插件独立于Android Studio运行,也就是说在没有Android studio的情况下你也能构建你的Android App。Android构建体系让你能够自定义构建配置,而不用修改app的源码文件。
 
典型的构建过程如图所示:
新建一个工程,Android Studio会自动创建一些文件,如下图 

位于project的根目录下,所有模块(整个project)的构建文件
/**
*buildscript {} 为Gradle配置仓库和依赖,例如将Android插件添加为依赖,
*modules自己的依赖不在这里配置。
*/
buildscript {
    /**
    *repositories {}配置repositories,Gradle用它来搜索或者下载依赖。
    *Gradle支持远程仓库(JCenter,Maven Central和Ivy),你也可以用本地的
    *仓库,代码中定义了JCenter作为仓库,Gradle需要用它来查找依赖。
    */
    repositories {
        jcenter()
    }
    dependencies {
        /**
        *dependencies {}配置依赖,Gradle用它来构建project,下面的代码将
        *2.1.0版Android插件作为路径依赖。
        */
        classpath ‘com.android.tools.build:gradle:2.1.0‘
    }
}
    /**
    *allprojects {}配置project中所有modules的repositories
    *和dependencies(例如第三方插件和库函数);
    *单个模块自己的依赖不能在这里配置,而是在module-level的build.gradle文件
    *中配置;
    *下面的代码将JCenter和mavenCentral作为仓库。
    */
    allprojects {
        repositories {
            jcenter()
            mavenCentral()
        }
}
module-level build.gradle文件,配置module的构建。
/**
*第一行配置Android插件运用于构建,使得android {}可用于Android-specific的
*构建选项
*/  
apply plugin: ‘com.android.application‘
/**
*android {} 是配置Android-specific构建选项的地方
*/
android {
    /**
    * compileSdkVersion规定了Gradle编译使用的Android API版本
    * 即你可以使用比他低的API版本
    * buildToolsVersion规定了SDK build tools的版本
    * /
    compileSdkVersion 21
    buildToolsVersion "21.1.2"
    /**
    *defaultConfig {}包含了所有构建版本的默认设置和条目,在动态构建的过程中
    *可以override掉main/AndroidManifest.xml一些属性
    */
    defaultConfig {
            /**
            * applicationId唯一的标识发布的package
            * /
            applicationId "io.rong.app"
            //app要求的最低的API版本
            minSdkVersion 9
            //测试app时使用的API版本
            targetSdkVersion 19
            //版本号
            versionCode 1
            //版本的名字
            versionName "2.4.10 Dev"
    }
    //配制project的结构
    sourceSets {
        main {
            jni.srcDirs = []
            jniLibs.srcDirs = [‘src/main/libs‘]
        }
    }
    signingConfigs {
        config {
            storeFile file("rong.key")
            storePassword "Amigo123"
            keyAlias "RongCloud"
            keyPassword "Amigo123"
        }
    }
    /**
    *buildTypes {}配置多个构建类型,默认的,构建体系定义了debug和release的
    *构建类型,构建类型设置Proguard是否可用
    */
    buildTypes {
        release {
            /**
            *默认的,Android Studio在release构建类型中使用Proguard
            *设置minifyEnabled为true
            */
            minifyEnabled true
            //签名的配置
            signingConfig signingConfigs.config
            //从Android SDK中运用默认的ProGuard的设置
            proguardFiles getDefaultProguardFile(‘proguard-android-optimize.txt‘),‘proguard-rules.pro‘
        }
        debug {
            minifyEnabled false
            shrinkResources false
            /**
            *将debug的构建类型的报名设为<app appliationId>.debug,
            *这样能够同时安装debug和release版的APK到相同的Android设备中
            */
            applicationIdSuffix ".debug"
        }
    }
    /**
    *productFlavors {}配置多个project flavors
    *它允许你创建不同版本的app,它可以override defaultConfig {} 中的设置
    *Product flavors是可选的设置,默认不配置
    *下面创建了免费和付费的product flavor,每一个product flavor会定义自己的
    *application ID,这样它们可以同时安装或者发布
    */
    productFlavors {
        free {
            applicationId ‘com.example.myapp.free‘
        }
        paid {
            applicationId ‘com.example.myapp.paid‘
        }
    }
    /**
    *lint工具的配置选项,Lint工具检查Android project的源文件中潜在
    *的bugs、改善优化correctness
    */
    lintOptions {
        checkReleaseBuilds false
    // Or, if you prefer, you can continue to check for errors in release builds,
    // but continue the build even when errors are found:
        abortOnError false
    }
}
//配置当前模块的依赖
dependencies {
    //告诉Gradle将所有JAR文件添加到app/libs folder
    compile fileTree(dir: ‘libs‘, include: [‘*.jar‘])
    compile ‘com.android.support:appcompat-v7:19.1.0‘
    compile ‘com.android.support:support-annotations:21.0.2‘
    compile project(‘:kit‘)
    compile files(‘libs/TencentSearch1.1.2.16095.jar‘)
    compile files(‘libs/TencentMapSDK_Raster_v1.1.2.16281.jar‘)
}
配置project-wide的Gradle设置
配置构建系统的本地环境,例如SDK的安装路径,它是Android Studio自动生成的,不要手动修改。
gradle.settings文件告诉Gradle哪些modules需要参与构建app。
//这个文件引用了工程所有的模块
include ‘:app‘, ‘:lib‘, ‘:kit‘,‘thirdparty‘,‘:push‘,‘:toollib‘
构建自定义配置要求改变build.gradle文件,而这些文本文件使用DSL来描述和操作构建逻辑 
,使用的脚本语言是Groovy,而你不需要掌握Groovy,你只需要掌握Android插件提供的DSL元素。
构建类型定义了Gradle构建和打包app的特定properties; 
默认的情况下,Android插件自动构建debug和release版的app; 
debug构建类型用debug key来签名APK;而release的构建类型使用release key来进行发布; 
你可以自定义其他类型的Build type;
android {
    ...
    defaultConfig {...}
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile(‘proguard-android.txt‘), ‘proguard-rules.pro‘
        }
        debug {
            applicationIdSuffix ".debug"
        }
        /**
         * ‘initWith‘属性允许你复用其他构建类型的配置,你只需要修改你想改变的
         * 配置,下面的例子中‘jnidebug’就使用了debug的build type,只是改变了
         * applicationIdSuffix和versionNameSuffix的设置
         */
        jnidebug {
            /** 
            * This copies the debuggable attribute and debug signing
            * configurations.
            * /
            initWith debug
            applicationIdSuffix ".jnidebug"
            jniDebuggable true
        }
    }
}
除了修改build的properties外,build types也可以添加特殊的sourceSet和resource。比如说每一个build type,其sourceSet被创建了,它的默认位置在src//,比如src/debug/java目录将被添加到debug版的APK
Product flavors代表你要发布的不同版本,比如说免费和付费的版本,你可以添加sourceSet来增加一些特殊的属性;一个project可以有不同的flavors来构建不同的应用
android {
    ...
    defaultConfig {...}
    buildTypes {...}
    productFlavors {
        demo {
            applicationId "com.example.myapp.demo"
            versionName "1.0-demo"
        }
        full {
            applicationId "com.example.myapp.full"
            versionName "1.0-full"
        }
    }
}
Build Type + Product Flavor = Build Variant
默认的,Android Studio创建的main/ source set包含了所有build variants所共有的部分,然而build types和product flavors可以创建新的source set来控制Gradle编译和打包过程。举例来说,你可以在main/ sourceset中实现基本的功能,而用product flavor的sourceset来改变不同客户端的应用名以及debug build type的build variants的一些特殊的权限和日志功能。 
build type,product flavor的sourceSet的结构与main/ sourceSet一样,除了根目录的名字是build type,product flavor的名字;举例来说,你在debug build type的sourceSet中创建manifest.xml文件:
MyProject/
    app/
        src/
            main/
            debug/
                java/
                res/
                // This manifest is only used with build variants that use
                // the debug build type.
                AndroidManifest.xml
Gradle根据build types和product flavors自动创建build variants,并且按照方式命名。例如,如果你创建了‘demo’和‘full’的product flavors,结合默认的‘debug’和‘release’构建类型,Gradle创建了下面的build variants:
demoDebug 
demoRelease 
fullDebug 
fullRelease
你在构建demoDebug的build variant时,Gradle会找到这些目录,并且优先级从高到低: 
src/demoDebug/ (build variant source set) 
src/debug/ (build type source set) 
src/demo/ (product flavor source set) 
src/main/ (main source set) 
这样做的原因是:demoDebug/ sourceSet中可能有build variant一些特殊的设置,demoDebug/和debug/中有相同的文件时,优先使用demoDebug/ sourceSet中的文件. 
在构建过程中构建规则是:
下面的例子展示了app/ module’s build.gradle三种不同类型的依赖
android {...}
...
dependencies {
    // The ‘compile‘ configuration tells Gradle to add the dependency to the
    // compilation classpath and include it in the final package.
    // Dependency on the "lib" module from this project
    compile project(":lib")
    // Remote binary dependency
    compile ‘com.android.support:appcompat-v7:19.0.1‘
    // Local binary dependency
    compile fileTree(dir: ‘libs‘, include: [‘*.jar‘])
}
/**
*将本地的Android library module添加为依赖,要求
*构建系统在构建app时将这个module包含进来并编译。
*/
compile project(":lib")
/**
*通过JCenter的协助将22.0.1版的Android support library
*添加为依赖,默认的,Android Studio在top-level的构建文件
*中使用JCenter仓库来配置projects,在你同步projects时Gradle
*会自动从JCenter中拉取dependency
*/
compile ‘com.android.support:appcompat-v7:22.0.1‘
/**
*告诉构建体系将app/libs/目录下的JAR文件添加到
*app的包中,如果你的module建立本地的binary 
*dependencies,将此JAR文件复制到<moduleName>/libs中。
*/
compile fileTree(dir: ‘libs‘, include: [‘*.jar‘]) 
Gradle需要明确地为release build’s APK签名,请阅读用Android Studio签名release build type
debug mode: 
开发时使用,Android SDK工具自动生成,证书(certificate)有一个private key和已知的password,每次app的改变和调试不需要输入password; 
当你在Android Studio中运行或者调试project时自动以debug mode运行的 
debug的配置使用debug keystore,位置在$HOME/.android/debug.keystore,debug build type默认使用这个。
release mode: 
发布app时使用,使用自己的certificate:
...
android {
    ...
    defaultConfig {...}
    signingConfigs {
        release {
            storeFile file("myreleasekey.keystore")
            storePassword "password"
            keyAlias "MyReleaseKey"
            keyPassword "password"
        }
    }
    buildTypes {
        release {
            ...
            signingConfig signingConfigs.release
        }
    }
}
Signing Your App in Android Studio
用来精简代码和resources,ProGuard可检测和移除无用的classes,fields,methods和属性;你可以自定义ProGuard规则,默认的该文件放在module的根目录下。
android {
    buildTypes {
        release {
            //使得ProGuard可用
            minifyEnabled true
            /**
            *getDefaultProguardFile(‘proguard-android.txt‘)从
            *Android SDK tools/proguard/文件中获取ProGuard的设置
            *proguard-rules.pro文件为自定义的的ProGuard文件,默认放在
            *module的根目录下
            */
            proguardFiles getDefaultProguardFile(‘proguard-android.txt‘),
                    ‘proguard-rules.pro‘
        }
    }
    ...
}
Lint工具检查Android project的源文件中潜在的bugs、改善优化correctness、security、performance、usability、accessiblility。
android {
    lintOptions {
        // 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‘
    }
}
构建文件中的插件会自动创建出一系列的任务,通常会有以下四种: 
* assemble:负责project输出的task 
* check:运行所有检查(checks)的task 
* build:执行assemble和check的task 
* clean:清除project输出的task 
assemble、check、build task只是起到了’anchor’ tasks的作用,实际上不做任何事,添加与之关联的task来执行具体的任务。 
这样做的原因是不管是什么样project、用什么样插件,只要执行assemble、check、build task,那么与之关联的task都会执行。
Library project和常规的Android project相似,但不同的地方在于Library project使用了不同的插件。
apply plugin: ‘com.android.library‘
android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"
}
...
Library project的主要输出是一个.arr包(代表着Android archive),它包含编译代码(a jar and/or native.so文件)和资源文件 (manifest, res, assets)。
dependencies {
    compile project(‘:libraries:lib1‘)
    compile project(‘:libraries:lib2‘)
}标签:
原文地址:http://blog.csdn.net/carryoner/article/details/51548395