Android一键打包,上传,提交修改记录的黑科技

前言

在Gradle中配置好签名文件相关信息,就可以实现一键打包,还可以自定义输出路径,修改Apk名称等,减少我们提测时的繁琐步骤。
详情请看:Gradle实现一键签名打包

即使我们配置好了Gradle,我们开发提测时仍需要进行如下三个步骤:

  1. 修改版本号,重新编译,打包成新的Apk
  2. 复制粘贴Apk,QQ、钉钉等发送给测试
  3. 写几条修改记录,好让测试知道改了什么

平时偶尔打包倒是没什么,但是到了测试周,测试问题一个接着一个,连续打包很多次的时候就会觉得特别烦。
遇到网络不好传输文件慢的时候还特抓狂,更不要说改的多了可能修改什么的都记不清了。

入职新公司后发现,公司的项目竟然使用了Python脚本一键提测,然后通过钉钉群的机器人通知测试,好不爽哉。
研究一番后,我发现Java虽然可能略微麻烦一些,但是也能实现。
因此本篇文章就是准备教大家:Java代码实现一键打包时自动提交Apk,并上传自己的修改记录。
通过钉钉群的机器人发消息由于开发者账号的原因没有实现,但是我相信看完本文的内容,明白原理后,实现起来肯定不难。

所需环境及工具

  1. Java环境变量。
  2. Git。
  3. IDEA,用来编写Java代码及打Jar包。
  4. fir.im账号及认证后的API_Token。

Gradle中一个重要的方法

复制如下代码到你的Gradle文件里。

task aaTest(type: Exec) {
    commandLine "java", "-version"
}

Sync Now后,双击Gradle---Tasks---other---aaTest

控制台的Run中会输出你的JDK版本信息:

> Task :aaTest

BUILD SUCCESSFUL in 422ms
1 actionable task: 1 executed
java version "1.8.0_231"
Java(TM) SE Runtime Environment (build 1.8.0_231-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode)
15:23:02: Task execution finished 'aaTest'.

没错,Gradle中commandLine方法可以执行CMD命令。

注意:task方法的type必须是Exec才可以使用commandLine,否则编译不通过。

结合环境工具,相信你已经大致知道我要做什么了:

  1. 使用commandLine执行jar程序
  2. jar程序中上传Apk到fir.im中
  3. fir.im中传入修改记录的参数

fir.im

我们可以调用fir.im的接口发布应用,文档见:https://www.betaqr.com/docs/publish

我们在IDEA中创建一个Java项目,然后实现fir.im的接口的调用。
这里贴出main函数的代码,详细代码可以访问文末的Github查看。
main函数的args字符串数组可以接受命令行传入的参数,所以对于一些参数我们直接在args中传入,这样打出来的jar包可以多个项目使用,而不用重复造轮子。

 public static void main(String[] args) {
        String bundle_id = args[0]; //包名
        String api_token = args[1];//fir.im的api_token
        String filePath = args[2]; //apk走到打包的路径
        String name = args[3]; //App名
        String version = args[4]; //版本号
        String build = args[5]; //版本Code
        /**
         * 修改记录,这里不用从命令行中传入
         * 而是可以直接取git的提交记录,先注释掉卖下关子
         */
        String changelog = ""; //修改记录
        File file = new File(filePath);
        if (!file.exists()) {
            System.out.println("Apk does not exist, please check the path and naming!");
            return;
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("type", "android");
        map.put("bundle_id", bundle_id);
        map.put("api_token", api_token);
        //获取上传凭证
        JSONObject jsonObject = HttpUtil.getInstance().getTokenInfo("http://api.bq04.com/apps", map);
        if (jsonObject != null) {
            JSONObject json = jsonObject.getJSONObject("cert").getJSONObject("binary");
            Map<String, Object> upLoadMap = new HashMap<String, Object>();
            upLoadMap.put("key", json.getString("key"));
            upLoadMap.put("token", json.getString("token"));
            upLoadMap.put("file", file);
            upLoadMap.put("x:name", name);
            upLoadMap.put("x:version", version);
            upLoadMap.put("x:build", build);
            upLoadMap.put("x:changelog", changelog);
            //上传文件
            if (HttpUtil.getInstance().upLoadApk(json.getString("upload_url"), upLoadMap)) {
                //因为AndroidStudio控制台输出中文会乱码,所以这里输出日志都改成英文
                System.out.println("Apk Uploaded successfully! Please visit the link below to view:");
                String url = "http://" + jsonObject.getString("download_domain") + "/" + jsonObject.getString("short");
                System.out.println(url);
                //浏览器打开fir.im的应用发布页面
                openUrl(url);
            }
        } else {
            System.out.println("Failed to obtain upload information! Please check the parameters!");
        }
    }

从Git中获取修改记录

作为一个合格的程序员,使用Git提交代码时,commit日志应该规范统一的。可以参照Git Commit日志风格指南
如果我们每次提交代码的时候都严格规范,进行简短的描述。那么我们Git提交记录完全可以作为提测时的修改记录。
接下来我便来教大家如何使用Git获取提交记录。

由于我们不可能把所有的提交记录提交,我们只需要获取到本次修改的全部提交记录即可。
因此我们可以把本次修改的第一次commit新建一个Tag(在AndroidStudio中只需要对提交记录右键—NewTag即可),以这个Tag开始的提交到最后一次提交作为本次提测的修改记录。(Tag最好不要交叉,重复。)

  1. 运行:git rev-list --tags --max-count=1,可以获取最后一次Tag的Id,得到TagId
  2. 根据TagId,运行:git describe --tags TagId,可以获取到TagName
  3. 根据TagName,运行:git log -1 --format=%ai TagName,可以获取到Tag那条commit的提交时间TagTime
  4. 根据TagTime,运行git log --no-merges --pretty="- (%an,%cr) - %s" --since=" TagTime ",便可以获取到Tag开始的提交到最后一次提交之间的所有提交记录。

Java中我们可以使用如下代码,执行命令行并且获取执行命令行之后的内容。

public static String exeCmd(String commandStr) {
        BufferedReader br = null;
        try {
            Process p = Runtime.getRuntime().exec(commandStr);
            br = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line = null;
            StringBuilder sb = new StringBuilder();
            while ((line = br.readLine()) != null) {
                sb.append(line + "\n");
            }
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return "";
    }

因此main函数中卖关子的代码,就为:

  String logTag = exeCmd("git rev-list --tags --max-count=1");
        String tagName = exeCmd("git describe --tags " + logTag);
        String tagTime = exeCmd("git log -1 --format=%ai " + tagName);
        String changelog = exeCmd("git log --no-merges --pretty=\"- (%an,%cr) - %s\" --since=\"" + tagTime + "\"");

接下来你只需要将Java代码打成可执行jar包,复制到任意目录下,命令行使用时指向jar的绝对路径即可。

Module的build.gradle

复制如下代码到你的Module的build.gradle中。

task aaBuildApk() {

}
task aaUploadApk(type: Exec) {
    def applicationId = project.android.defaultConfig.applicationId //包名
    def api_token = "fir.im api_token" //fir.im的api_token
    def filePath = "build/outputs/apk/release/app-release.apk" //apk打包的原始路径
    def name = "OneKey" //App名
    def versionName = project.android.defaultConfig.versionName //版本号
    def versionCode = project.android.defaultConfig.versionCode //版本Code
    def jarPath = project.rootDir.toString() + "/BuildApk.jar" //jar的路径
    commandLine "java", "-jar", "$jarPath", "$applicationId", "$api_token", "$filePath", "$name", "$versionName", "$versionCode"
}

aaBuildApk.dependsOn('assembleRelease')
aaUploadApk.dependsOn('clean', 'aaBuildApk')
aaBuildApk.mustRunAfter('clean')

Sync Now后,你只需要:

  1. 提交代码,新建一个Tag(不要交叉,重复)
  2. 双击Gradle---Tasks---other---aaUploadApk
  3. 放开双手喝咖啡,等待网页打开
  4. @通知测试

最终效果

Android一键打包,上传,提交修改记录的黑科技_第1张图片

总结

至此,本文已经全部讲解完毕。主要的核心知识点就是如何使用commandLine方法和git获取提交日志。
明白这个原理,你可以完全根据自己的需求定制自己一键打包黑科技。
如果你是一个会Python等脚本语言的Android开发者,那么你只需要一个脚本文件即可实现,而且可以随意修改。
你甚至可以在代码中接入钉钉机器人发消息给测试,不用跟测试说一句话就完成提测。

源码

GitHub:https://github.com/DeMonLiu623/OneKeyApk

你可能感兴趣的:(#,Android笔记)