gradle打包的apk复制到另一个目录:Installation did not succeed. The application could not be installed.

项目使用行云加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执行时序:
  1. 首先解析settings.gradle来获取模块信息,为每个module创建对应的 project实例,这是初始化阶段;
  2. 然后配置每个模块,处理所有的模块的 build 脚本,处理依赖,属性等。这个时候每个模块的build.gradle文件会被解析并配置,这个时候会构建整个task的链表(这里的链表仅仅指存在依赖关系的task的集合,不是数据结构的链表),配置的时候并不会执行task;
  3. 配置完了以后,有一个重要的回调project.afterEvaluate,它表示所有的模块都已经配置完了,可以准备执行task了;
  4. 执行指定的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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值