您的位置:首页 > 其它

gradle打包简介

2016-06-27 11:08 288 查看

一、gradle特点

ANT是最早的构建工具,基于idea,好象是2000年有的,当时是最流行java构建工具,不过它的XML脚本编写格式让XML文件特别大。对工程构建过程中的过程控制特别好。

Maven它是用来给Ant补坑的,Maven第一次支持了从网络上下载的功能,仍然采用xml作为配置文件格式,它的问题是不能很好的相同库文件的版本冲突。Maven专注的是依赖管理,构建神马的并不擅长。

Gradle属于结合以上两个的优点,它继承了Ant的灵活和Maven的生命周期管理,它实际上是Maven+Ant的一套更加用户友好的界面。不考虑IDE辅助的情况下,基于Groovy的DSL相比XML配置文件可以少写不少代码。此外因为是基于Groovy的DSL,可以更细致地控制编译过程。比如,Ant要做if-else条件选择特别麻烦,换做gradle的话可以直接套用java的编程风格 if(){}else{}。

总之,gralde 简单,高效,灵活

二、gradle 配置

(app/build.gradle)

apply plugin: 'com.android.application'

android {
compileSdkVersion 23
buildToolsVersion "23.0.2"

defaultConfig {
applicationId "gradlecomple.ndh.com.gradlecomplie"
minSdkVersion 9
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
}


我们都知道一个app工程下build.gradle第一句:apply plugin: ‘com.android.application’ 表示我们需要使用该插件的一些功能。弱弱问一句:

1、你怎么知道这里引用的插件是com.android.application?

2、android 下的各种配置是什么意思?

3、android下还有些什么配置?

一开始我也是一头雾水,完全搞不明白,需要用什么功能网上一顿乱搜,完全使用别人的经验,直到我访问了以下网址:

http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Tasks

页面上有一句让你链接到android gradle 详细的DSL(domain specific language/领域专用语言)

Please see the [Android Plugin DSL Reference](http://google.github.io/android-gradle-dsl/current/) for a complete list of build properties that can be configured and their default values.


进入到页面你会看到:



这里就告诉你android用的有三种插件。

点开AppExtension瞧瞧:



这些就是android下可以配置的属性。

比如说你想看defaultConfig里面还有些什么配置:

点击defalutConfig一项:



再次点开ProductFlavor:



看看这些是不是你想要的?

三、gradle打包

需求:打包一个sdk(带布局文件),并将jar包命名为mylib.jar,并将生成的文件拷贝到app工程

步骤分析:

1 打包资源文件生成R.java文件

2 依赖生成的R.java 打包java源码

3 拷贝资源文件和jar包到app工程

打包资源文件使用aapt命令,然而我没有找到对应的taskType,因此只好使用命令行方式。

1.1打资源包

(mylibrary/build.gradle)

#定义一个变量baseDir,表示当前目录
def basedir = rootDir.getAbsolutePath()
#定义编译资源的task
task compileRes() {
doLast {
#这里表示 执行命令行
exec {
commandLine gradle.aapt,
'package',
'-f',
'-m',
'-J',
"${basedir}/mylibrary/gen",
'-M',
"${basedir}/mylibrary/src/main/AndroidManifest.xml",
'-S',
"${basedir}/mylibrary/src/main/res",
'-A',
"${basedir}/mylibrary/src/main/assets",
'-I',
gradle.home,
'-F',
"${basedir}/mylibrary/gen/${resName}"
}
}
}


ps:taskType简介

gadle脚本中可执行的东西叫task ,gradle定义了一系列的task类型-taskType。其文档在这:https://docs.gradle.org/current/dsl/index.html#N10335

打开后可以看到:



1.2 编译class

java编译class刚好gradle有提供任务类型 JavaCompile:https://docs.gradle.org/current/dsl/org.gradle.api.tasks.compile.JavaCompile.html:

其相关可配置属性如下:



具体编译任务如下:

(mylibrary/build.gradle)

task compileLib(type: JavaCompile, dependsOn: 'compileRes') {
//保证build_new一定存在,因为生成的class文件需要放到该目录下
doFirst {
def file = new File("${basedir}/mylibrary/build_new")
if (!file.exists()) {
file.mkdir()
}
}
//配置java代码
source "${basedir}/mylibrary/src/main/java"
//配置工程引用的R.java文件(R.java文件由任务compileRes生成到gen目录下)
source "${basedir}/mylibrary/gen/hotfix"
//设置编译好的class文件存放目录
destinationDir = new File("${basedir}/mylibrary/build_new")
//这里用到的gradle.home 配置到local.property里,具体如何引用请看下面介绍 3.2
FileCollection fc = files(new File(gradle.home))
//设置classpath(包括所有依赖jar)
classpath = fc
}


1.3打jar包

通过寻找,我们看到gradle自带有jar任务类型https://docs.gradle.org/current/dsl/org.gradle.api.tasks.bundling.Jar.html



baseName:表示 将生成的jar重命名

encoding:表示使用的编码规则

另外在文档下方方法区里有这么一个方法:



这里配置当前Jar任务类型需要的sourcePaths

具体任务如下:

(mylibrary/build.gradle)

task compileJar(type: Jar, dependsOn: 'compileLib') {
baseName = "${jarName}"
encoding = "utf-8"
from "${basedir}/mylibrary/build_new"
//    into "${basedir}/mylibrary/out"
}
执行完该任务会在build/libs下生成一个mylib.jar(系统默认是classes.jar,因为上边配置的baseName的原因更改了默认文件名)


1.4 拷贝编译的资源文件,jar包到app目录

(mylibrary/build.gradle)

//拷贝jar包到app/libs
task copyLibFile(type: Copy, dependsOn: 'compileJar') {
copyFile("${basedir}/mylibrary/build/libs/${jarName}.jar", "${basedir}/app/libs")
}
//拷贝aapt打包的资源到app工程assets目录
task copyResFile(type: Copy, dependsOn: 'copyLibFile') {
//这里copyFile为定义在util.gradle的函数,目的就为了代码复用,外部gradle的引用请看下文TODO
copyFile("${basedir}/mylibrary/gen/${resName}", "${basedir}/app/src/main/assets")
}


三、gradle 扩展

3.1 gradle任务的两种写法

task ma( description="开始打包",group="MA",dependsOn: 'mb'){
doLast{
printlnx "this is task ma"
}
}
task mb(){
printlnx "this is task mb"
}
以上也可写成这样:
//<< 表示doLast
task ma<<{
printlnx "this is task ma"
}
//可以单独为ma配置属性,(很类似js的对象属性配置)
ma{
dependsOn "mb"//依赖mb任务
description="开始打包"//任务描述
group="MA"//为当前ma任务分组
}
task mb(){
printlnx "this is task mb"
}
但请注意 以下写发错误:
task ma(description="开始打包",group="MA",dependsOn: 'mb')<<{
printlnx "this is task ma"
}
也就是<< 前面不能带()


3.2 gradle获取配置文件属性

上文有一个属性为 gradle.home,这个home属性其实是定义在根目录下local.properties里:



解析该属性在((mylibrary/setting.gradle):

//通过gradle.ext 将sdk.api属性导出为api
gradle.ext.api = properties.getProperty('sdk.api')
gradle.ext.aapt=properties.getProperty('sdk.aapt')
gradle.ext.home=properties.getProperty('sdk.home')
gradle.ext.jar=properties.getProperty('jar')


在mylibrary/build.gradle中想使用这些属性先引用setting.gradle文件:

apply from: rootProject.getRootDir().getAbsolutePath() + "/mylibrary/settings.gradle"


然后直接通过gradle.api(这里不再是gradle.ext.api)就可以获取到local.properties配置的属性

3.3 引用外部gradle方法

在build.gradle中我只想做和打包相关的逻辑,其他辅助逻辑(比如文件拷贝)我想抽取到外部,一方面使各个gradle文件逻辑干净整洁,一方面也可以代码复用。上面提到mylibrary/build.gradle引用到了mylibrary/utils.gradle中的copyFile方法

copyFile在utils.gradle中定义如下:

def copyFile(srcPath, desPath) {
def File src = file(srcPath)
def File des = file(desPath)
//文件拷贝到文件夹
if (src.isFile() && des.isDirectory()) {
def des1 = file(des.absolutePath + "/" + src.getName())
des1.createNewFile()
des1.withOutputStream {
os ->
src.withInputStream {
is -> os << is
}
}
}
}
//通过ext将当前文件的copyFile函数导出为copyFile函数供外部使用
ext {
copyFile = this.©File
}

解释一下这段代码
//将文件流写入到des1中
des1.withOutputStream {//这里是第一个闭包
//1
os ->
src.withInputStream {//这里是第二个闭包
//2
is -> os << is
}
}
这段通过goovy编写,闭包是groovy中一个特别重要的概念,也是gradle构建中的基础。  闭包中的->左边表示参数,箭头右边是使用到该参数的函数
因此上边第一处箭头-> 左边的os表示第一个闭包的参数,对该参数的操作则是在第二个闭包中进行。
在第二个闭包中箭头->is是其参数,对is的操作,是在函数 os<<is中进行,这里的<<为groovy中的语法 表示流的读写(将<<右边的is 读取到左边的os中,groovy中读写就是真么叼)


在build.gradle中使用copyFile先引用utils.gradle

apply from: rootProject.getRootDir().getAbsolutePath() + "/mylibrary/utils.gradle"


然后像调用本文件方法一样使用copyFile

task copyLibFile(type: Copy, dependsOn: 'compileJar') {
copyFile("${basedir}/mylibrary/build/libs/${jarName}.jar", "${basedir}/app/libs")
}


示例代码下载:https://github.com/killer8000/GradleSample
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: