在Gradle中配置好签名文件相关信息,就可以实现一键打包,还可以自定义输出路径,修改Apk名称等,减少我们提测时的繁琐步骤。
详情请看:Gradle实现一键签名打包
即使我们配置好了Gradle,我们开发提测时仍需要进行如下三个步骤:
平时偶尔打包倒是没什么,但是到了测试周,测试问题一个接着一个,连续打包很多次的时候就会觉得特别烦。
遇到网络不好传输文件慢的时候还特抓狂,更不要说改的多了可能修改什么的都记不清了。
入职新公司后发现,公司的项目竟然使用了Python脚本一键提测,然后通过钉钉群的机器人通知测试,好不爽哉。
研究一番后,我发现Java虽然可能略微麻烦一些,但是也能实现。
因此本篇文章就是准备教大家:Java代码实现一键打包时自动提交Apk,并上传自己的修改记录。
通过钉钉群的机器人发消息由于开发者账号的原因没有实现,但是我相信看完本文的内容,明白原理后,实现起来肯定不难。
复制如下代码到你的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,否则编译不通过。
结合环境工具,相信你已经大致知道我要做什么了:
我们可以调用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提交代码时,commit日志应该规范统一的。可以参照Git Commit日志风格指南
如果我们每次提交代码的时候都严格规范,进行简短的描述。那么我们Git提交记录完全可以作为提测时的修改记录。
接下来我便来教大家如何使用Git获取提交记录。
由于我们不可能把所有的提交记录提交,我们只需要获取到本次修改的全部提交记录即可。
因此我们可以把本次修改的第一次commit新建一个Tag(在AndroidStudio中只需要对提交记录右键—NewTag即可),以这个Tag开始的提交到最后一次提交作为本次提测的修改记录。(Tag最好不要交叉,重复。)
git rev-list --tags --max-count=1
,可以获取最后一次Tag的Id,得到TagIdgit describe --tags TagId
,可以获取到TagNamegit log -1 --format=%ai TagName
,可以获取到Tag那条commit的提交时间TagTimegit 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中。
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后,你只需要:
Gradle---Tasks---other---aaUploadApk
至此,本文已经全部讲解完毕。主要的核心知识点就是如何使用commandLine方法和git获取提交日志。
明白这个原理,你可以完全根据自己的需求定制自己一键打包黑科技。
如果你是一个会Python等脚本语言的Android开发者,那么你只需要一个脚本文件即可实现,而且可以随意修改。
你甚至可以在代码中接入钉钉机器人发消息给测试,不用跟测试说一句话就完成提测。
GitHub:https://github.com/DeMonLiu623/OneKeyApk