项目使用行云加Jenkins打包,自定义了Apk打包目录,结果造成使用Android studio 上的运行按钮找不到安装的apk
报错如下:
Installation did not succeed.
The application could not be installed.
List of apks:
[0] '...\app\build\outputs\apk\Mobile\release\app-Mobile-release.apk'
Installation failed due to: 'Invalid File: ...\app\build\outputs\apk\Mobile\release\app-Mobile-release.apk'
gradle 版本 :gradle:4.0.1和gradle-6.1.1-all.zip
原来的配置
android {
// 配置输出apk的名称
android.applicationVariants.all { variant ->
variant.getPackageApplicationProvider().get().outputDirectory = new File("../build/outputs/apk/" + variant.versionName + "/" + variant.flavorName + "/" + System.getenv("BUILD_NUMBER"))
variant.outputs.all {
outputFileName = "Apk_name_${variant.productFlavors[0].name}_${variant.productFlavors[0].versionName}_${buildType.name}.apk"
}
}
}
或者
gradle 版本 :gradle:3.1.1和gradle-4.10.1-all.zip
//配置输出apk的名称
android.applicationVariants.all { variant ->
variant.getPackageApplication().outputDirectory = new File(project.rootDir.absolutePath + "/build/outputs/apk/" + variant.versionName + "/" + variant.flavorName + "/" + System.getenv("BUILD_NUMBER"))
variant.getPackageApplication().outputScope.apkDatas.forEach { apkData ->
//这个修改输出APK的文件名
apkData.outputFileName = "Apk_name_v" +
variant.versionName + "_" +
variant.flavorName + "_" +
variant.buildType.name +
".apk"
}
}
上面是直接修改了apk的输出路径和apk名称
解决思路:不修改apk输出路径只修改apk名称,打包完成后将Apk拷贝到Jenkins打包需要的路径
修改后的配置
gradle 版本 :gradle:4.0.1和gradle-6.1.1-all.zip
android {
// 配置输出apk的名称
android.applicationVariants.all { variant ->
// variant.getPackageApplicationProvider().get().outputDirectory = new File("../build/outputs/apk/" + variant.versionName + "/" + variant.flavorName + "/" + System.getenv("BUILD_NUMBER"))
variant.outputs.all {
outputFileName = "Apk_name_${variant.productFlavors[0].name}_${variant.productFlavors[0].versionName}_${buildType.name}.apk"
}
}
//拷贝apk到Jenkins打包需要的路径
tasks.whenTaskAdded { task ->
if (task.name.startsWith("assemble")) {
// 如果是assemble开始任务,在最后执行拷贝apk
task.doLast {
android.applicationVariants.all { variant ->
File outputPath = new File("../build/outputs/apk/" + variant.versionName + "/" + variant.flavorName + "/" + System.getenv("BUILD_NUMBER"))
copy {
from variant.outputs[0].outputFile
into outputPath
}
}
}
}
}
}
流程分析:每次运行打包apk,实际执行的是assembleProductFlavorBuildType的task;gradle的task执行是先执行依赖的task(如资源打包,java编译等);所以assemble task反而是最后执行,这个时候再执行拷贝命令,apk是已经打包好的,不会出现拷贝命令执行了,apk没有拷贝过来
下图是点击Android Studio 的运行按钮的Build输出 ,可以在Build窗口的Build Output 中看到打包步骤(记得选中 旁边的眼睛图标的Show Successful Steps),开始是执行的assembleMobileRelease,最后一步是assembleMobileRelease
相关知识点:
- Gradle执行时序:
- 首先解析settings.gradle来获取模块信息,为每个module创建对应的 project实例,这是初始化阶段;
- 然后配置每个模块,处理所有的模块的 build 脚本,处理依赖,属性等。这个时候每个模块的build.gradle文件会被解析并配置,这个时候会构建整个task的链表(这里的链表仅仅指存在依赖关系的task的集合,不是数据结构的链表),配置的时候并不会执行task;
- 配置完了以后,有一个重要的回调project.afterEvaluate,它表示所有的模块都已经配置完了,可以准备执行task了;
- 执行指定的task,根据task链表来执行某一个特定的task,这个task所依赖的其他task都将会被提前执行。
备注:如果注册了多个project.afterEvaluate回调,那么执行顺序等同于注册顺序;
- Gradle task执行时的回调:
一个Task包含若干Action。所以,Task有doFirst和doLast两个函数,用于添加需要最先执行的Action和需要和需要最后执行的Action。Action就是一个闭包。
参考文档:
https://www.jianshu.com/p/9d5ca80a989a
https://blog.csdn.net/singwhatiwanna/article/details/78797506?utm_source=blogkpcl7###
https://www.jianshu.com/p/cd1a78dc8346