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
相关文章推荐
- 设备的 MAC 地址与预想的不符
- An error occurred while automatically activating bundle com.android.ide.eclipse.adt(259).
- 使用jquery实现的按需加载
- js算法:heap sort 使用堆排序
- 使用 document.onreadystatechange()来判断页面加载完
- mysql 主从复制问题'the master returned an invalid number of fields for SHOW SLAVE HOSTS'
- 一个可以捕获程序崩溃个 然后可以保存本地的方法
- ant编译java 和eclipse编译的差别
- 黑马程序员-JAVA基础面试-获取10个1-20 的随机数,要求获取的随机数不能相同!
- Linux学习-VIM操作
- linux内核函数 ioremap()的原理及意义
- 二级列表
- fir.im Weekly - 2016 年 Android 最佳实践列表
- jquery广告滚动框
- 电子选频率特性
- poj1840
- 常用的正则表达式大全
- 通用的sql语句
- Yixiaohan---005题,更改目录下所有图片的分辨率
- dm6446 VLIB函数