Android gradle 学习文档
1. gradle 简介
Gradle是一款非常优秀的的项目自动化构建开源工具,在常用的开发软件Android studio中 默认使用此工具进行构建。在本文档中将介绍gradle常用的语句和命令。(此文档基于mac系统环境描述)
2. 学习准备
1. 安装java jdk
java jdk 的下载地址为:https://www.oracle.com/java/technologies/javase-downloads.html
在选择下载时需注意不可使用14.**jdk版本 ,对应下载如图所示
下载时选择mac系统下载,按其后安装步骤继续即可。
安装完成后在路径/Library/Java/JavaVirtualMechines/下可以查看到我们安装的jdk
2. 配置gradle 环境变量
打开mac命令终端 输入以下指令:
cd $HOME
ls -a (运行此语句是为了查看是否存在.gradle文件夹)
touch .bash_profile
open -e .bash_profile
------------------------
在文件中写入
export PATH=${PATH}:/User/你的用户名/.gradle/wrapper/dists/*****直至延续至bin目录
例如:
保存 关闭
------------------------
souece .bash_profile
gradle -v (查看安装版本)
3.gradle 常用操作
1.groovy基础
1.字符串
在groovy中 单引号和双引号均可作为字符串,但单引号字符串中不能对表达式进行运算 ,例如
task showDiffOfMarks(){
def name = "字符串"
println '单引号输出的是:${name}'
println "双引号输出的是:${name}"
}
运行输出内容如下:
单引号输出的是:${name}
双引号输出的是:字符串
2.集合
1 List
在groovy中,集合可以直接通过下标进行访问,也可以使用复数下表表示从后向前计算。
task sampleList {
def numberList = [0,1,2,3,4,5,6]
println nunmberList[1] //访问第二个元素
println nunmberList[-1] //访问最后一个元素
println nunmberList[-2] //访问倒数第二个元素
println nunmberList[1..3] //访问2-4的元素
numberList.each{
println it
}
}
2 Map
在groovy中,Map也可以类似于数组的访问形式进行访问,只是需替换为键值对的形式,具体如下参考代码。
task sampleMap {
def myMap = ['numberOne':1,'stringOne':'this is String']
println myMap['numberOne']
println myMap.stringOne
myMap.each{
println "Key:${it.key},Value:{it.value}"
}
}
3.返回值
在groovy中return语句是可以被省略的,在没有return语句时,groovy回将最后一行代码作为返回值
task sampleReturn {
def number1 = getMax 10,15
def number2 = getMax 18,6
println "number1:${number2},number2:${number2}"
}
def getMax(int n1,int n2){
if(n1 > n2){
n1
}else{
n2
}
}
4.代码块参数
在groovy中可将代码块作为参数传递给其他函数,请看以下示例
def numberList = [0,1,2,3,4,5]
numberList.each{
println it
}
在实际上 each的定义如下
public static <T> List<T> each(List<T> self, @ClosureParams(FirstGenericType.class) Closure closure) {
return (List)each((Iterable)self, closure);
}
参照方法定义,传统的调用方法应该为
numberList.each({println it})
在groovy中规定了如果最后一个参数为代码块,可以将代码块放到方法外面,因此我们可以将代码块移到方法外面进行传递,同时可省略括号。
5.向闭包传递参数
闭包的概念实际上在第四条就已经涉略,List.each中传递的参数就是一个普通的闭包,但假设闭包需要有参数怎么办,可采用如下的方法:
def chooseMax = {
int numb1,int numb2 -> if(numb1 > numb2){
numb1
}else{
numb2
}
}
task sampleClosure{
println choseMax(1,2)
}
2.常用task介绍
1 Copy
Copy:将文件复制到目标目录。此任务还可以在复制时重命名和过滤文件。该任务实现CopySpec用于指定要复制的内容。
方法名 | 作用 |
---|---|
from | 源目标文件夹 |
into | 将复制至的文件夹 |
include | 包含的文件 |
exclude | 不包含的文件 |
代码示例: |
task sampleCopy(type:Copy){
from 'testDoc/doc/'
into 'testDoc/myDoc/'
include '*.txt'
exclude 'test.txt'
rename 'mytest.*','mytest.txt'
}
2 Delete
Delete:删除文件或目录
方法名 | 作用 |
---|---|
delete | 使用该方法去删除文件或文件集 |
followSymlinks | 返回在删除时是否应遵循符号链接 |
task makePretty(type: Delete) {
delete 'noUseFile', 'ownFile'
followSymlinks = true
}
3 Jar
方法名(6.6前/6.6后) | 作用 |
---|---|
baseName/archiveBaseName | 储存jar包的基本名称 |
excludes | 不包含的文件 |
includes | 包含的文件 |
from | 源文件目录(class文件) |
into | 打抱成的jar包的目录结构 |
代码示例 |
task makeJar(type:org.gradle.api.tasks.bundling.Jar) {
//指定生成的jar名 6.6版本后替换为 archivesBaseName
baseName 'samplesdk'
//从哪里打包class文件
from('build/intermediates/javac/debug/classes/com/example/sdkmod/')
//打包到jar后的目录结构
into('com/example/sdkmod')
//去掉不需要打包的目录和文件
exclude('BuildConfig.class', 'R.class')
//去掉R$开头的文件
exclude{ it.name.startsWith('R$');}
}
4.其他task选项
此处的task并不一一列举,除上述外还有许多其他的task,使用为 org.gradle.api.tasks.** 见下方图片中的类或文件夹中的类
3.gradle 日志
级别 | 作用 | 使用方法 |
---|---|---|
ERROR | 错误消息 | logger.quiet(“quiet”) |
QUITE | 重要消息 | logger.error(“error”) |
WARNING | 警告消息 | logger.warn(“warn”) |
LIFECYCLE | 进度消息 | logger.lifecycle(“lifecycler”) |
INFO | 信息消息 | logger.info(“info”) |
DEBUG | 调试消息 | logger.debug(“debug”) |
log打印的方式 gradle -q task | ||
开关选项 | 输出的日志级别 | |
------ | ------- | |
无选项 | LIFECYCLE 及其更高级别 | |
-q 或者 | –quite QUITE | |
-i 或者 | –info INFO | |
-d 或者 | –debug DEBUG |
task 中的方法 | 作用 |
---|---|
setProperty(“name”,value) | 给相应的变量赋值 |
dependOn(tasks) | 设置依赖的task |
finalizedBy(task1) | 最后执行task1 |
doFirst{ *** } | 在此任务之前执行的代码(只有在传入方法体的时候才会运行) |
doLast{ *** } | 在此任务之后执行的代码(只有在传入方法体的时候才会运行) |
doSelf{ *** } | 任务本身执行的代码 |
shuldRunAfter(taskA) | 应该在taskA之后执行本任务 |
onlyif{ *** } | 当代码块返回值为true时,本任务才会被执行 |
4.gradle 生命周期
初始化阶段
在初始化阶段,Gradle会确定哪些项目参与构建,并且为这些项目创建一个Project实例。
配置阶段
在配置阶段,会构建的所有项目的构建脚本(build.gradle)
执行阶段
Gradle确定要在此期间创建和配置的任务子集。子集由传递给gradle命令和当前目录的任务名称参数确定,其后执行每个选定的任务。
//在project进行配置前调用,子工程必须在主工程中设置才会生效,主工程必须在settings.gradle中设置才会生效
void beforeProject(Closure closure)
//在project配置后调用
afterProject(Closure closure)
//构建开始前调用
void buildStarted(Closure closure)
//构建结束后调用
void buildFinished(Closure closure)
//所有project配置完成后调用
void projectsEvaluated(Closure closure)
//当settings.gradle中引入的所有工程都被创建好后调用,只在该文件设置才会生效
void projectsLoaded(Closure closure)
//settings.gradle配置完后调用,只对settings.gradle设置生效
void settingsEvaluated(Closure closure)
在setting.gradle中添加以下代码:
gradle.settingsEvaluated {
println "settings:执行settingsEvaluated..."
}
gradle.projectsLoaded {
println "settings:执行projectsLoaded..."
}
gradle.projectsEvaluated {
println "settings: 执行projectsEvaluated..."
}
gradle.beforeProject { proj ->
println "settings:执行${proj.name} beforeProject"
}
gradle.afterProject { proj ->
println "settings:执行${proj.name} afterProject"
}
gradle.buildStarted {
println "构建开始..."
}
gradle.buildFinished {
println "构建结束..."
}
执行结果:
settings:执行settingsEvaluated…
settings:执行projectsLoaded…
Configure project :
settings:执行SDKMod beforeProject
settings:执行SDKMod afterProject
Configure project :app
settings:执行app beforeProject
settings:执行app afterProject
settings: 执行projectsEvaluated…
5.常用操作
1 debug和relese包
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug{
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
2 生成可用于动态加载的Jar包
找到找到android sdk的目录 (/Users/你的用户名/Library/Android/sdk/build-tools/30.0.1)并进入到sdk目录中,将dx文件和lib/dx.jar文件一并复制到项目根目录中。并在.gradle文件中 编写
task makeMinifyJar(type:proguard.gradle.ProGuardTask,dependsOn:"build"){
delete './build/libs/mif/minifySdk.jar'
injars './build/libs/mytasksdk.jar'
outjars './build/libs/mif/minifySdk.jar'
configuration 'proguard-rules.pro'
}
String cmd = "./dx --dex --output=./mytestdexsdk.jar ./app/build/libs/mif/minifySdk.jar"
task creatDexJar(type: Delete) {
def cmdResult = cmd.execute().text.trim()
logger.info("cmd 执行结束"+cmdResult)
delete('./build/libs/mif','./build/libs/mytasksdk.jar')
}
task clearJar(type: Delete) {
//删除生成的jar文件
delete 'libs/samplesdk.jar'
}
task makeJar(type:org.gradle.api.tasks.bundling.Jar) {
//指定生成的jar名 6.6版本后替换为 archivesBaseName
baseName 'samplesdk'
//从哪里打包class文件
from('build/intermediates/javac/debug/classes/com/example/sdkmod/')
//打包到jar后的目录结构
into('com/example/sdkmod')
//去掉不需要打包的目录和文件
exclude('BuildConfig.class', 'R.class')
//去掉R$开头的文件
exclude{ it.name.startsWith('R$');}
}
makeJar.finalizedBy(makeMinifyJar,creatDexJar)
在工程根目录终端下输入 gradle makeJar 待运行完成便可在根目录下见到输出的jar文件
生成不带buildconfig或者R.的jar包(非自定义task)
afterEvaluate {
generateReleaseBuildConfig.enabled = false
generateDebugBuildConfig.enabled = false
generateReleaseResValues.enabled = false
generateDebugResValues.enabled = false
}
或者
android{
buildFeatures {
buildConfig = false
}
}