Java 构建Gradle 逐渐出如今各个开源软件中,特别是Android平台。虽然工具无对错用的好便可,可是美帝亡我之心不死,从ANT(纯手动)到MAVEN(套餐模式)再到Gradle(半自动步枪),每一次都是赤裸裸的学习成本。为了跟上Google大爷的脚步,也只能委屈本身了。html
本文将从几个方面介绍Gradle:java
Groovy 是JVM上的一门语言,兼容Java,而且具备脚本语言的特性,至关于JAVA的扩展语言。这里将从这几方面介绍Groovy:mysql
Groovy的安装比较简单,仅仅几步就完成了:android
一般在使用Groovy的时候,一份API文档是至关重要的GroovyAPI。git
好比说Groovy的全部对象都集成GroovyObject,经过查看API文档,就能够知道几个很是重要的方法:github
这些方法都是比较重要的,涉及到动态语言的特性。如spring
getProperty(String s) -> Groovy动态属性读取API setProperty(String s,Object o) -> Groovy动态属性设置APIsql
经过这两个API,就能够在运行时动态添加/读取属性,而且也增强了闭包做用域的动态性。shell
Groovy 是一门兼容Java的语言,而且在Java的语言基础上添加了一些动态语言的特性。**Groovy能够当作是Java的扩展集合。**接下来,将会介绍一些Groovy特有的语法特性,这些特性在Gradle中大范围的被使用,了解这些语法,利于对Gradle的学习。编程
Groovy 支持类型推断,也就是定义变量的时候,不须要指定类型,统一使用def便可,如:
def name = "DARKGEM";
固然也能够采用:
String name = "Hello World";
来定义变量了。
Groovy支持语句最后面不用添加分号(;)
def w1 = "Hello World"; def w2 = "Hello World"
这两句语句是等价的。
在Groovy中,函数的参数也能够不定义它的类型,而是采用直接声明变量名便可,如:
void say1(content){ println content; } void say2(String content){ println content; }
上面两个函数是等价的。
Groovy的函数,其实也不须要指定函数返回类型,经过def定义函数便可,如:
def add(a,b){ return a+b; } int add(a,b){ return a + b }
它们是等价的
Groovy 的函数,其实也不须要return关键字,它会将最后一句的运行结果表达式,做为return的结果,如:
def add(a,b){ a + b } def add(a,b){ return a + b }
它们是等价的。
Groovy中对函数的调用,有时候(至少存在一个参数)能够省略括号,这个特性使得Gradle脚本看起来更像是DSL了。如:
println "NO () CALL" println("NO () CALL")
它们是等价的。
可是有时候,是不能省略括号的
def func(){ println 'i am function' } func()//success func//error
由于func函数没有参数,因此调用的时候,若是省略了括号,**则func会被认为是属性。**因此只能采用func()调用方式。
Groovy的注释和Java同样,支持 // 和 /**/ 的写法,如:
// 这是单行注视 /** 这 是 多 行 注 释 */
Groovy 支持Java字符串,也支持动态推断[$表达式],如:
def name = 'DARKGEM' println 'I am $name' println "I am $name" println "I am ${name}" println "1 + 2 = ${1+2}" println ''' SELECT * FROM T_USER '''
输出结果为:
在Java中,最讨厌的就是空指针的处理了,而groovy提供了比较优雅的判断空值的语句(?),如:
option?.call() -> 其中option多是空指针对象
经过这种语句,就能够当option==null的时候,不进行调用call方法,避免抛出NullPointException。
在Groovy中,优化了对集合的操做,避免了一些比较丑陋的语法出现。
经过Groovy的语法特性,能够很是简单的对List进行初始化和操做
def list = [1,2,3,"4"] //初始化为ArrayList对象,而非 Object[] 对象类型 println list[3] == '4' // 直接读取数组元素 println list.join(",") == '1,2,3,4' // 支持join操做 println list.count(2) == 1 // 统计List中数值为2的元素个数 list[99] = '100' //直接赋值到第100的位置 println list.size == 100 // 此时List对象的元素为100个
Groovy对Map类型,提供了很是简单易用的语法特性:
def map = [:] //声明了map对象 def map = [key1 : 'val1' , 'key2' : 'val2'] //初始化map对象 println map.key1 == 'val1' // 读取key1元素 println map["key1"] == 'val1' //读取key1元素,注意[]里面须要为字符串 map.key1 = 'change val1' // 修改key1的元素 map.key3 = 'val3' //添加新元素
若是一个函数的参数为Map类型,那么能够采用以下的方式调用:
def func(Map m){ println m } func key1:'val1', key2:'val2' //免去了() 以及[] func([key1:'val1',key2:'val2']) //完整的调用格式
在Groovy中,支持Range类型,好比说
1..3 // 1-3 1..<5 // 1-4
这种写法,一般和迭代合起来用。
Groovy中最具备表明性的语法特性就是闭包(closure),闭包在Groovy中是一等公民。经过闭包,咱们能够省略不少代码。咱们看一下闭包最基本的写法:
def c = { println "it's closure" } c(); // it's closure
仅仅经过**{}**就编写出一个闭包,很是的方便。而闭包的语法结构为:
{ [param][,param]->code }
的格式。其中,默认参数的关键字为it。如:
def c = { println it } c('hello') // hello
返回的结果和函数同样能够经过return指定,也能够默认采用最后一句表达式的运行结果。如:
def c ={ 1 +2 } def c = { return 1+2 }
是等价的。
而闭包的调用,一般有三种方法:
而若是函数的参数为闭包的话,就造成了以下的语法格式:
def func(Closure c){ c() } func { println 'run closure' }
是否是和Gradle的脚本很是的相似。
Groovy对迭代,提供了很是NB的支持,如:
println '-------------list-----------' def list = [1,2,3,4] list.each { println it } println '-------------map--------------' def map = [k1:'v1',k2:'v2'] map.each{k,v-> println "$k:$v" } println '-----------number range------------' for(def i in 1..4){ println i } println '-----------char range------------' for(def i in 'a'..'d'){ println i }
运行结果:
Groovy是支持类的,而且还具备本身的特性:
见一个类的声明:
class DGM{ def a def b //add def add(){ println "a + b = ${a + b}" } } DGM rhs = new DGM(a:1,b:2) //初始化,注意不能省略括号 rhs.add(); //调用方法 println rhs.a //访问a属性,是经过内置函数getA()实现 println rhs.getA() //访问内置函数getA
运行结果为:
经过javap查看groovyc编译成字节码后的DGM.class文件,能够看到默认的方法:
对象也能够像函数同样被调用 a();
class A{ public Object call(Object... args){ println 'callMe' } } A a = new A() a()
运行结果:
Groovy支持一个重要的特性就是操做符重载了,经过这个特性,能够很是方便的完成一些经常使用的操做,如List读取某个元素的数值等。下面介绍leftShift(<<)的重载:
def list = [1,2,3,4] list << 5 //添加5到list中 list << 6 //添加6到list中 println list
运行结果为:
能够发现,在gradle中常常出现task <<写法,其实就是重载了leftShift函数。
Groovy是一门动态语言,它支持动态属性。
class A{ def prop = [:] void setProperty(String propertyName, Object newValue){ prop[propertyName] = newValue } Object getProperty(String propertyName){ return prop[propertyName] } } A a = new A() a.a = 1; println a.a
运行截图:
能够发现:经过重载GroovyObject#setProperty/getProperty就实现了动态属性的特性。这个特性在Gradle常常被使用。
这个特性,结合闭包的delegate机制,就能够改变闭包的做用域。如:
class A{ def prop = [:] void setProperty(String propertyName, Object newValue){ prop[propertyName] = newValue } Object getProperty(String propertyName){ return prop[propertyName] } def func (Closure c){ c() } } def closure = { //运行函数 func { println 'run closure' } //经过动态属性,设置新的属性 newProperty = 'newValue' } //指向A对象 closure.delegate = new A() //做用域优先采用delegate closure.setResolveStrategy Closure.DELEGATE_FIRST //运行 closure() //读取闭包中设置的属性 println closure.delegate.newProperty
运行结果:
经过这种方法,Gradle就能够动态的加载插件/任务/配置属性,而且能够直接调用方法/属性。
针对调用的语法:
func('arg1','arg2')
也能够省略括号(为函数的时候,参数须要多余一个)
func '1','2'
若函数的时候没有参数,则须要添加括号
func()
若是编写以下格式的语法,则认为是查询属性
func //查询属性,而非调用
这点和shell语法有极大的不一样。
groovy的处理调用方式以下:
三言两语,仍是比较难全面的介绍Groovy语言的,可是经过上面这些语法特性,基本上可让初学者能读通Gradle脚本了。若是要深刻的使用Gradle,那么增强Groovy语言的学习也是有必要的。这里给几点意见:
编写完Groovy脚本后,能够经过groovyc来编译,获取class文件,而后反编译(jd-gui/javap)查看groovy是如何转换为java语言的,加深的groovy语言的理解。
api手册不离手,多看看javadoc。
Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化建构工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各类繁琐配置。
面向Java应用为主。当前其支持的语言限于Java、Groovy和Scala,计划将来将支持更多的语言。
gradle对多工程的构建支持很出色,工程依赖是gradle的第一公民
BY 百度百科
Gradle的安装很是的简单,只须要以下几步既能够完成:
运行截图:
**注意Gradle支持任务简写:**好比说存在两个任务 assembleDebug 和 assembleRelease, 咱们不须要所有输入,只须要输入 gradle assD便可运行 assembleDebug 任务。
Gradle 是一门基于Groovy语言的构建框架。gradle支持ant,maven构建方式,而且和ide能比较完美的整合。
一个 Gradle 构建项目是由若干个project组成,而一个project是由若干个task组成。
Project概念针对某一个构建项目。一个Project包含了若干Task, 依赖关系,配置属性等。一般Project通过一系列过程后会产出构建成品,如jar,war等。注意:Gradle容许项目依赖
**而Task是属于Project的,经过一系列的Task组合,咱们能够构建一个项目。**好比说:Project要输出一个jar,那么task通常有编译,打包等。经过组合task,完成了最终产出jar的构建。
任务之间经过dependsOn来决定构建依赖。好比说debug依赖classes任务,则调用gradle debug的时候,会优先执行classes任务。以下图:
一般咱们说的构建,就是经过指定某一个项目下(多项目)的某个task(build)来执行一系列的构建task,最终获取想要的结果,如jar,war。
一个gradle项目的基本结构为:
其中,setting.gradle 为: include 'ProjectA','ProjectB' 来指示包含的项目
build.gradle 文件是描述项目是如何构建的关键。一般这个文件描述了项目引用的插件(插件包含了某种特定类型的构建任务集合,如java,android),任务配置(源码位置,依赖关系),第三方仓库等信息。
settings.gradle 文件一般是描述项目中的一些基本配置,如通用的task,在多项目构建中settings.gradle 还须要描述被包含的项目。
gradle 的构建流程,通常会按照以下的过程:
在各个阶段,咱们能够经过Gradle提供的Hook API进行截取。如:gradle.taskGraph.whenReady
如今,咱们来实际编写一些gradle脚本,加深理解。
首先,咱们创建一个文件夹命名为gradle 而后,在目录下建立一个build.gradle的文件 最后,在build.gradle中输入:
//定义hello这个任务 task hello << { println 'Hello' } /** 能够发现,上面的task,利用了操做符重载,其重载的API仍是doLast。 task hello { doLast{ println 'Hello' } } */ //定义world任务,而且依赖hello任务 task world(dependsOn:hello) <<{ println 'World' }
咱们能够经过gradle tasks 查看全部被支持的任务,发现咱们刚刚添加的任务已经出如今任务列表中了。 咱们在gradle/目录下,执行** gradle world **命令,运行结果为:
gradle 支持动态任务,也就是说,咱们能够在脚本运行的时候,定义任务:
5.times { task "task$it" <<{ println "$it" } }
运行命令 gradle tasks 查看全部的任务:
咱们能够在task中,添加一些咱们自定义的属性
task hello { ext { mark = 'darkgem' } } println hello.mark
运行结果:
这个实现的原理就是Groovy的动态属性。
咱们能够指定gradle的默认任务,如:
defaultTasks 'run' task compile <<{ println 'compile...' } task run(dependsOn:compile) <<{ println 'run....' }
这样子,咱们直接输入 gradle 就直接执行 run task:
Gradle 在不一样阶段准备完成后,会执行Hook API,让用户能够有机会修改某些流程或者配置等,好比说:
task distribution << { println "We build the zip with version=$version" } task release(dependsOn: 'distribution') << { println 'We release now' } gradle.taskGraph.whenReady {taskGraph -> if (taskGraph.hasTask(release)) { version = '1.0' } else { version = '1.0-SNAPSHOT' } }
运行结果:
能够发现不一样的任务,就出现了不一样的执行结果。
如今,来介绍一下多项目构建。目录结构为:
settings.gradle:
include 'ProjectA','ProjectB'
ProjectA#build.gradle
task taskA <<{ println 'taskA' }
ProjectB#build.gradle
task taskB <<{ println 'taskB' }
执行gradle tasks -all 结果为:
咱们能够发现,gradle 的task语法和以前咱们介绍的groovy语法有些区别,如:
task first<<{ println 'first' } task hello(dependsOn:'first') { println 'hello' }
这种写法,使用groovy语法的标准,没法分析出task究竟是什么东西。其实呢,gradle为了脚本写的好看,作了一些特别的工做。 上述的语句,在gradle分析脚本后,会转换为:
task('first',{ doLast{ println 'hello' } }) task('hello',{ dependsOn 'first' println 'hello' });
这种格式。这样子,一切就真相大白了。**说白了就是gradle实现了本身的语法糖。**而经过后面的闭包,配置了这个task的属性,如依赖,后置处理等。这个原理涉及到Groovy的delegate机制。
经过 repositories{} 能够配置maven,ivy,local仓库。这样子,在dependencies{}声明的依赖就能够经过repositories{}中指定的仓库查询到具体的JAR资源。
configurations{} 记录着项目中各个分组(compile,runtime)的依赖信息。**这些依赖信息来自于:引用的插件,dependencies{第三方库},sourceSets{源码},自定义配置,任务的构建产品(JAR)等。**以下是一个简单的自定义分组信息:
configurations.create('myCompile') dependencies{ myCompile fileTree('lib') }
这样子,咱们就声明了一个名字为myCompile的依赖分组。
configurations{}主要的做用在于:
注意:如compile,runtime 之类的configuration已经默认的被添加到java插件中,因此通常状况下不要使用这几种configuration。
在gradle中dependencies{}是一等公民,它描述了configurations{}中分组依赖的第三方资源。咱们能够把依赖简单的分红两大类:
gradle依赖:主要是gradle运行的时候,须要加载一些插件,如android等,此时须要配置它。
项目编译/运行依赖:编译一个项目,一般须要依赖其余项目或者JAR。
gradle依赖指定,一般在buildscript{}模块中声明,若是是一个多项目构建,则只须要在root目录下的build.gradle中添加gradle依赖便可。好比说,android gradle依赖支持:
buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:1.5.0' } }
这样子就配置好了gradle的运行依赖,在使用的时候,调用 apply plugin: 'android' 既能够引入android插件。
在编译项目的时候,也常常出现依赖外部JAR,项目等状况。此时,咱们只须要配置 dependencies 便可引入JAR。
dependencies { //for dependencies found in artifact repositories you can use //the group:name:version notation compile 'commons-lang:commons-lang:2.6' testCompile 'org.mockito:mockito:1.9.0-rc1' //map-style notation: compile group: 'com.google.code.guice', name: 'guice', version: '1.0' //declaring arbitrary files as dependencies compile files('hibernate.jar', 'libs/spring.jar') //putting all jars from 'libs' onto compile classpath compile fileTree('libs') // dependencies project compile project(':someProject') //dependencies project and select configuration configurationName project(path: ':projectA', configuration: 'someOtherConfiguration') }
一个Java项目,一般依赖的关系如上图描述。值得注意的是,依赖仓库的JAR写法:
这种写法,和MAVEN一致。
在编写gradle脚本的时候,网上的配置有时候不能解决你手头的问题,因此咱们须要求助于Gradle文档。
首先,咱们须要理解,一个gradle脚本通过处理后其实最后就是一个Groovy的脚本,区别点为:
理解了这两点,咱们就基本上能够抱着API编写脚本了。下面将介绍gradle脚本如何和Gradle文档对应起来。
build.gradle //此时做用域链为Project //调用 Project#apply(Map map) 方法 apply plugin: 'java' /** 语法糖 task('hello',{ //此时,做用域链为Task doLast { // 调用Task#doLast方法 println 'hello' } }) */ task hello { doLast{ println 'hello' } }
翻阅Gradle的文档(DSL,Javadoc),咱们能够查询到其余有用的API来支持咱们的gradle编程。
本小节大体的描述了一下gradle这个构建工具,而且和groovy语言作了一下对比。能够发现,gradle脚本就是groovy的脚本。
一个JavaWeb的项目构建和一个普通Java项目的构建最大的区别在于:JavaWeb有固定的目录结构。如图:
因此,咱们只要把项目构建的结果class存放到classes/目录下,就是一个标准的JavaEE项目了。
接下来,咱们来看看Gradle提供的Java plugin的任务流程:
能够发现,咱们其实仅仅须要** classes task **便可完成对编译完成的class输出。
构建项目目录,该项目的目录相似eclipse提供的JavaEE目录结构:
而构建的脚本以下:
//使用Java插件 apply plugin: 'java' //配置编译选项 compileJava { options.encoding = 'UTF-8' sourceCompatibility = "1.6" targetCompatibility = "1.6" } //配置源码信息 sourceSets { main { //指定main的源码输出位置 output.resourcesDir = output.classesDir = 'WebContent/WEB-INF/classes/' //源码目录 java.srcDir('src') //资源文件目录 resources.srcDir('src') } } //配置依赖 dependencies { //LIB依赖 compile fileTree('WebContent/WEB-INF/lib/') //servlet api依赖 compile fileTree('jetty/') } //动态生成任务 ({ //属性配置和 def props = [ JDBC_CLASS_NAME : ['com.mysql.jdbc.Driver', 'com.mysql.jdbc.Driver'], JDBC_URL : ['jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8', 'jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8'], JDBC_USR : ['root', 'root'], JDBC_PASSWD : ['root', 'root'], JDBC_MAX_ACTIVE : [10, 10], JDBC_INITIAL_SIZE: [1, 1], JDBC_MIN_IDLE : [5, 5] ] //动态生成任务的名称,注意 props里面的属性和这个序列对应 ['debug', 'release'].eachWithIndex { val, idx -> task "$val"(dependsOn: 'classes') << { //将配置信息,写入指定文件中 Properties properties = new Properties() File file = new File(sourceSets.main.output.resourcesDir, 'project.properties') OutputStream fos = new FileOutputStream(file) props.each { key, value -> properties.setProperty(key, String.valueOf(value[idx])) } properties.store(fos, String.format("mode=%s", val)); } } })();
经过这个脚本,咱们能够构建出一个JAVAEE的项目,而且该脚本支持生产环境和测试环境不一样配置的特色。而脚本中的API调用都来自于Gradle Java DSL Plugin的描述。
项目地址:javaee-framework
在 Google I/O 2013 大会上,发布了一款新的Android工具--Android Studio 以及 Gradle 后,eclipse 和 ant 逐渐被google 抛弃了。如今android小组的构建工具都采用gradle,而且它对应的插件目前版本已经2.0了。
经过gradle构建android项目是很是简单的。首先建立项目:
android create project -n Demo -a MainActivity -k org.darkgem -v 1.5.0 -t android-15 -g -p .
这样子就建立了一个简单的android gradle 项目。
可是由于gradle的版本兼容性的问题,因此咱们还须要修改一下build.gradle脚本:
//gradle初始化的时候,须要加载的资源指定 buildscript { repositories { mavenCentral() } //加载android gradle 插件JAR dependencies { classpath 'com.android.tools.build:gradle:1.5.0' } } //加载android 插件 apply plugin: 'android' android { //配置android sdk版本 compileSdkVersion 'android-15' //配置编译工具版本 buildToolsVersion '23.0.2' }
而后咱们运行指令gradle build,进行构建。结果发现异常:
能够发现,在运行task lint的时候,发生了异常,查看lint 报告:
能够发现,实际上是由于local.properties文件中关于sdk.dir写法出现问题,咱们修改一下就能够了:
sdk.dir=D:\\Link\\android-sdk -> sdk.dir=D\:\\Link\\android-sdk
再次运行gradle build就能够执行成功了。其输出的apk在:
android lint是一款静态代码检测工具,经过lint能够在编译期就能够发现许多问题,如调用太新的API等。这个检测是至关有必要的。因此不建议在脚本中添加:
android { lintOptions { abortOnError false } }
这会致使lint检测无效。
值得注意的是:在Android Studio中,若是点击Debug按钮进行调试,是不会运行task lint的,因此须要用户手动的调用 task lint,使得在开发的时候,就知道问题出如今哪里。
gradle不像maven同样,源码和目录这些都是固定位置的,咱们能够经过配置,修改默认位置:
sourceSets{ main.setRoot('app') }
这样子就把mian目录,从默认位置的 src/main/ 提取到了 app下面。还能够配置其余的一些文件和目录:
sourceSets { main { //mainifest文件 manifest.srcFile 'AndroidManifest.xml' //源码目录 java.srcDirs = ['src'] //源码资源目录 resources.srcDirs = ['src'] //aidl目录 aidl.srcDirs = ['src'] //layout等资源目录 res.srcDirs = ['res'] //assets目录 assets.srcDirs = ['assets'] //SO文件目录 jniLibs.srcDirs = ['libs'] } }
这样子,就讲该android项目的源码目录结构变成和eclipse同样了。
android gradle的依赖管理和java同样,只须要配置好 repositories{} 和 dependencies{} 便可。如:
//配置仓库 repositories { mavenCentral() } //配置依赖 dependencies { //按照maven名称加载jar compile 'com.google.guava:guava:11.0.2' //加载目录下全部的jar compile fileTree(dir: 'libs', include: ['*.jar']) //多个文件 }
android的构建必不可少的就是签名了,经过签名。通常签名分为两种:DEBUG 和 RELEASE ,因此通常只须要两种类型的签名便可:
android{ signingConfigs { debug { storeFile file("debug.keystore") } release { storeFile file("release.keystore") storePassword "darkgem" keyAlias "release" keyPassword "darkgem" } } buildTypes { //release类型配置 release { //指定使用哪一个签名配置 signingConfig signingConfigs.release } } }
值得注意的是DEBUG签名是固定格式的:
一般,咱们只须要拷贝~/.android/debug.keystore 便可。
为了保护咱们的代码,一般在发布版本的时候进行代码混淆处理:
buildTypes { release { minifyEnabled true proguardFile 'proguard-project.txt' } }
这样子就在release的时候进行代码混淆了。
值得注意的是:
下面给出一个比较完成的脚本,充分的考虑的测试环境和发布环境配置等:
//gradle初始化脚本 buildscript { //第三方仓库 repositories { mavenCentral() } //android gradle plugin 插件依赖 dependencies { classpath 'com.android.tools.build:gradle:1.5.0' } } //使用android 插件 apply plugin: 'android' android { //sdk 版本 compileSdkVersion 'android-15' //构建工具版本 buildToolsVersion '23.0.2' //源码配置 sourceSets{ main.setRoot('app') } //签名配置 signingConfigs { debug { storeFile file("debug.keystore") } release { storeFile file("release.keystore") storePassword "darkgem" keyAlias "release" keyPassword "darkgem" } } //构建类型 buildTypes { //测试版本 debug{ //测试版本对AndroidMainfest.xml 中关键字替换 //UMENG manifestPlaceholders = [UMENG_APPKEY: "56947a48e0f55a0635002c3a", UMENG_CHANNEL : "DARKGEM"] //在 BuildConfig中,添加自定义的属性 //BUILD CONFIG buildConfigField "String", "MAIN_API_URL", "\"http://darkgem.org/api/v1/\"" } //发布版本 release { //开启混淆处理 minifyEnabled true //签名引用 signingConfig signingConfigs.release //混淆文件 proguardFile 'proguard-project.txt' //发布版本对AndroidMainfest.xml 中关键字替换 //UMENG manifestPlaceholders = [UMENG_APPKEY: "56947a48e0f55a0635002c3a", UMENG_CHANNEL : "DARKGEM"] //在 BuildConfig中,添加自定义的属性 //BUILD CONFIG buildConfigField "String", "MAIN_API_URL", "\"http://darkgem.org/api/v1/\"" } } //javac 配置 compileOptions { encoding 'UTF-8' sourceCompatibility JavaVersion.VERSION_1_6 targetCompatibility JavaVersion.VERSION_1_6 } } //依赖 dependencies { compile fileTree(include: ['*.jar'], dir: 'app/libs/') }
项目地址:android-framework
现今,许多android开源项目都开始使用gradle进行构建了。特别是support-v7包中的View类。若是直接进行拷贝引入,你会发现很是的困难。此时,咱们须要借助gradle多项目编译了。其方法和以前介绍的gradle多项目同样。
值得注意的点有:
由于最新的support-v7包是用最新的sdk编译的,因此,若是你使用旧版本的sdk编译项目的话,可能出现资源文件没法解析之类错误。此时,你须要把sdk提供到最新便可。
一般,咱们只须要在root/build.gradle中引入android gradle插件依赖,不须要每个build.gradle都引入一次android gradle plugin的依赖。
多项目中,引入插件的时候,须要区分application和library。
这篇文章断断续续的写了三天,算是把gradle基础概念学习了一遍。获得最重要的经验就是:多看文档。