前段时间在搞Android自动化打包的事情。
我们的library是需要提供给其他团队使用的,所以在使用Jenkins自动化打包过程中,需要将library打包成aar并发布到maven仓库上。
所以对于我们gradle,就需要先将myLibrary打包成aar并发布到maven仓库上,再清空app的缓存,并将app打包成apk
对应gradle命令如下
gradlew myLibrary:clean myLibrary:uploadArchives app:clean app:assembleRelease
按原先的理解来说,gradle在执行命令的时候,会顺序执行,会先执行myLibrary:clean,再执行myLibrary:uploadArchives,然后执行app:clean,最后执行app:assembleRelease
在项目的依赖没有问题的时候,确实是没有问题的。
但是,由于我们是先上传myLibrary到maven仓库,然后app再去获取最新的myLibrary 的 maven依赖,这个过程中,当myLibrary上传maven 仓库成功后,会自动将myLibrary的maven依赖的版本号+1。
这个具体看我的另一篇博客 Android Maven仓库搭建 - 实现自动化打包自动拉取最新maven依赖
这个时候就出问题了,会发现直接就报找不到依赖的错误了
FAILURE: Build failed with an exception.
* What went wrong:
Could not determine the dependencies of task ':app:lintVitalRelease'.
> Could not resolve all artifacts for configuration ':app:debugCompileClasspath'.
> Could not find com.heiko.test:myLibrary:2.0.99.
Required by:
project :app
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
这是为什么呢 ?
按gradle执行命令的顺序,按之前的理解是会先执行myLibrary:uploadArchives将aar上传到maven仓库,这时候再去执行app:assembleRelease 应该已经可以取到最新的依赖了才对呀 ?
百思不得其解之际,写了一个gradle的demo,对task的相关方法进行了打印
task myTask1 {
configure {
println("myTask1:configure")
}
doFirst {
println("myTask1:doFirst")
}
doLast {
println("myTask1:doLast")
}
}
task myTask2 {
configure {
println("myTask2:configure")
}
doFirst {
println("myTask2:doFirst")
}
doLast {
println("myTask2:doLast")
}
}
task myTask3 {
configure {
println("myTask3:configure")
}
doFirst {
println("myTask3:doFirst")
}
doLast {
println("myTask3:doLast")
}
}
然后我们使用命令行来执行myTask1、 myTask2 、myTask3
gradlew myTask1 myTask2 myTask3
可以看到执行结果
Starting a Gradle Daemon, 1 busy Daemon could not be reused, use --status for details > Configure project : myTask1:configure myTask2:configure myTask3:configure > Task :myTask1 myTask1:doFirst myTask1:doLast > Task :myTask2 myTask2:doFirst myTask2:doLast > Task :myTask3 myTask3:doFirst myTask3:doLast BUILD SUCCESSFUL in 5s 3 actionable tasks: 3 executed
这时,可以发现gradle会先去执行所有task的configure方法,再去真正依次执行各个task
gradle的生命周期这就引申出gradle的生命周期了
- initialization:初始化阶段
- 执行工程的setting.gradle文件
- 解析整个工程下的所有Project,构建所有的Project对应的project对象
- Configuration:配置阶段
- 解析所有的Projects对象中的task,构建好所有task的依赖图 (执行的先后顺序)
- Excution:执行阶段
- 执行具体的task及依赖task (先执行目标Task依赖的Task,再执行目标Task)
这里说明一下
Project : 每个build.gradle 就对应一个project,Project里可以有多个Task
Task : 主要的工作执行者,每个Task由多个Action组成
我们在settings.gradle中打印一句日志
再执行一下gradlew myTask1 myTask2 myTask3,可以看到执行顺序
知道了这个概念我们就可以知道,所有gradle task在执行之前,都会先执行所有task的configure,进行配置。
所以,我们必须要把上面的这个gradle命令进行拆分。
步骤一 : 清空myLibrary的缓存,并将myLibrary打包成aar并发布到maven仓库上
gradlew myLibrary:clean myLibrary:uploadArchives
步骤二 : 清空app的缓存,并将app打包成apk
gradlew app:clean app:assembleRelease
这样子执行,就不存在最初说的那个问题了。
Jenkins是支持创建多个gradle执行命令的,所以是不需要把gradlew命令杂糅在一起,是可以拆分开来分步骤执行的,这个也是我们前期踩坑的地方。
重新配置好Jenkins,就可以继续搞我们的自动化打包了,详见 Android Maven仓库搭建 - 实现自动化打包自动拉取最新maven依赖



