记录一次APP试图批量打包问题

前言

APP需要批量打包。之所以有这个需求,还是有几个大的环境前提的,我们公司存在多个渠道,而且呢因为有些应用市场上对CUP支持程度不一样,这么一搞一下,Android 每次打包都要打26个,同时又没有接入第3方的打包策略。我们这么打下来,起码得几个小时,麻了。因为环境变量太多,可能打包成功了环境变量不对,然后需要重新打,还有一个很重要的问题,我们有时候打出来的包百分百崩溃,有的是SO文件丢失,有的直接Native 崩溃了,受限于认知与技术层面,那就只能校验。再我写完工作空间,运行校验之后,突然发现自己路走远了,我可不可做到一键打包呢?

正文

可行性分析

起码在认知层面上,我觉得是可行的。起码有一个Jenkins工具就支持这个调调,但是我们Jenkins好像没有配置这个调调,有一个重要原因就是,有的包会崩溃,clean后重新打包就不崩溃了。同时我们知道:

gradlew assembleALiRelease 

只要终端在rootProject 执行上述命令就可以一个包出来。而且JAVA中:

runtime.exec()

这种函数可以执行脚本命令。那么我们就有了两个方向,1是模仿Jenkins去实现批量打包,2是通过exec() 执行脚本命令。

实践:exec

因为之前APP运行校验也是使用这种模式的,所以说,对我而言是最简单的。先执行Demo:

Runtime.getRuntime().exec("gradlew assembleAliDebug");

执行上述代码,会发现会抛错:

Cannot run program “gradlew”: CreateProcess error=2, 系统找不到指定的文件。

说明找到不gradlew。那么我们就传入gradlew 所在目录:

Runtime.getRuntime().exec("gradlew assembleAliDebug", null, new File("E:\\StudyDemo\\MyApplication"));

但是依旧报错,但是报错信息更详细了:

Cannot run program “gradlew” (in directory “E:\StudyDemo\MyApplication”): CreateProcess error=2, 系统找不到指定的文件。

在使用apkanalyzer的时候,在某位大佬博客上看到一句话:

bat脚本 需要全路径去执行。然后不同的系统的执行命令不一致。比如windows  需要cmd /c 表示执行完关闭,还有一个/k,好像是不关闭。

所以我们再次更改执行代码:

Runtime.getRuntime().exec("cmd /c gradlew assembleAliDebug", null, new File("E:\\StudyDemo\\MyApplication"));

等执行完成后,便可以在目标输出目录中存在编译出来的apk了。

Demo和主工程的差异

我Demo工程中,没有任何第三方maven。所以好像是可行的。但是当我切换到主工程的时候,我发现他会卡在Configure project。结合搜索结果,就是说gradle 没有搞下来,同时maven 会找不到。这是两个问题,但是我通过 Android studio 就没有这个问题,那么问题可能就在于,我不知道 怎么设置gradle 版本号和设置gradle home,也不知道为啥他没有调用root project中的配置。在简单分析了下我们Jenkins配置到信息之后,决定暂时放弃这种思路。因为我认为Jenkins多半不是通过exec去执行命令的。但是我执行gradle 命令,gradle 也会重新走什么周期,好像没有啥问题,为啥没有读取到配置呢?

仿照jenkins

我再gradle官网中找到了一篇文章。https://xy2401.com/local-docs/java.zh/gradle-6.0.1/third_party_integration.html 他上面说。

Gradle提供了一个称为Tooling API的编程API,可用于将Gradle嵌入到自己的软件中。该API允许您执行和监视构建,并向Gradle查询构建的详细信息。该API的主要受众是IDE,CI服务器和其他UI作者;但是,该API对需要将Gradle嵌入其应用程序的任何人都是开放的。

那么,jenkins 是不是使用了这种思路呢?

tooling Demo

 ProjectConnection connection = GradleConnector.newConnector()
                .useInstallation(project.getGradle().getGradleHomeDir())
                .forProjectDirectory(project.getRootDir())
                .connect();
// 执行task                 
connection.newBuild().forTasks("assemble").setStandardOutput(System.out).run(); 

好像代码可以正常执行。包也打出来,他会Configure project。因为是通过文件创建的,生命周期会重新执行,这很符合逻辑。

主工程实战

当我把上面代码拖拽到主工程的时候,为啥gradle 找不到,为啥还是maven 会继续找不到?这使得我开始仔细去思考上面遗留下来的问题。

在 https://docs.gradle.org/current/javadoc/org/gradle/tooling/GradleConnector.html 找到了答案。需要使用useBuildDistribution函数。

 connection = GradleConnector.newConnector()
                .useInstallation(appProject.getGradle().getGradleHomeDir())
                .forProjectDirectory(appProject.getRootDir())
                .useGradleVersion(appProject.getGradle().getGradleVersion())
                .useGradleUserHomeDir(appProject.getGradle().getGradleUserHomeDir())
                .useBuildDistribution()
                .connect();

在forTasks 函数中,我发现 task 的class和gradle中project的task的class是不一致。所以目前只能通过task 名称去执行task。还有一个问题,那就是每次run 都会Configure project。我们项目每次配置都需要3分钟左右,有点麻。

结束

其实代码很简单,逻辑也很简单,主要是认知上的改变吧。单纯的记录一下。当我们可以执行一个task的时候,那么执行多个task 便成为了可能。因为最终代码涉及到APP校验,安装等等。就不贴了。

参考资料:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值