本章将介绍360多渠道打包方法


Android多渠道打包(一):基础多渠道打包
Android多渠道打包(二):友盟多渠道打包
Android多渠道打包(三):美团多渠道打包
Android多渠道打包(四):360多渠道打包
Android多渠道打包(五):360多渠道打包+
Android多渠道打包(六):maven&gradle
Android多渠道打包(七):系列总结及展望


来源

这个打包方法是由奇虎360的工程师开源出来的,这位大神在github的id是seven456

原理

利用的是Zip文件“可以添加comment(摘要)”的数据结构特点,在文件的末尾写入任意数据,而不用重新解压zip文件(apk文件就是zip文件格式);所以该工具不需要对apk文件解压缩和重新签名即可完成多渠道自动打包,高效速度快,无兼容性问题;

实现方式

  • java源码
/*关键代码*/    public static void main(String[] args) throws Exception {//      写入渠道号//      args = "-path D:/111.apk -outdir D:/111/ -contents googleplay;m360; -password 12345678".split(" ");//      查看工具程序版本号//      args = "-version".split(" ");//      读取渠道号//      args = "-path D:/111_m360.apk -password 12345678".split(" ");        long time = System.currentTimeMillis();        String cmdPath  = "-path";        String cmdOutdir  = "-outdir";        String cmdContents  = "-contents";        String cmdPassword  = "-password";        String cmdVersion  = "-version";        String help = "用法:java -jar MCPTool.jar [" + cmdPath + "] [arg0] [" + cmdOutdir + "] [arg1] [" + cmdContents + "] [arg2] [" + cmdPassword + "] [arg3]"                + "\n" + cmdPath + "        APK文件路径"                + "\n" + cmdOutdir + "      输出路径(可选),默认输出到APK文件同一级目录"                + "\n" + cmdContents + "    写入内容集合,多个内容之间用“;”分割(linux平台请在“;”前加“\\”转义符),如:googleplay;m360; 当没有" + cmdContents + "”参数时输出已有文件中的contents"                + "\n" + cmdPassword + "    加密密钥(可选),长度8位以上,如果没有该参数,不加密"                + "\n" + cmdVersion + " 显示MCPTool版本号"                + "\n例如:"                + "\n写入:java -jar MCPTool.jar -path D:/test.apk -outdir ./ -contents googleplay;m360; -password 12345678"                + "\n读取:java -jar MCPTool.jar -path D:/test.apk -password 12345678";        if (args.length == 0 || args[0] == null || args[0].trim().length() == 0) {            System.out.println(help);        } else {            if (args.length > 0) {                if (args.length == 1 && cmdVersion.equals(args[0])) {                    System.out.println("version: " + VERSION_1_1);                } else {                    Map argsMap = new LinkedHashMap();                    for (int i = 0; i < args.length; i += 2) {                        if (i + 1 < args.length) {                            if (args[i + 1].startsWith("-")) {                                throw new IllegalStateException("args is error, help: \n" + help);                            } else {                                argsMap.put(args[i], args[i + 1]);                            }                        }                    }                    System.out.println("argsMap = " + argsMap);                    File path = argsMap.containsKey(cmdPath) ? new File(argsMap.get(cmdPath)) : null;                    String parent = path == null? null : (path.getParent() == null ? "./" : path.getParent());                    File outdir = parent == null ? null : new File(argsMap.containsKey(cmdOutdir) ? argsMap.get(cmdOutdir) : parent);                    String[] contents = argsMap.containsKey(cmdContents) ? argsMap.get(cmdContents).split(";") : null;                    String password = argsMap.get(cmdPassword);                    if (path != null) {                        System.out.println("path: " + path);                        System.out.println("outdir: " + outdir);                        if (contents != null && contents.length > 0) {                            System.out.println("contents: " + Arrays.toString(contents));                        }                        System.out.println("password: " + password);                        if (contents == null || contents.length == 0) { // 读取数据;                            System.out.println("content: " + readContent(path, password));                        } else { // 写入数据;                            String fileName = path.getName();                            int dot = fileName.lastIndexOf(".");                            String prefix = fileName.substring(0, dot);                            String suffix = fileName.substring(dot);                            for (String content : contents) {                                File target = new File(outdir, prefix + "_" + content + suffix);                                if (nioTransferCopy(path, target)) {                                    write(target, content, password);                                }                            }                        }                    }                }            }        }        System.out.println("time:" + (System.currentTimeMillis() - time));    }}
  • 使用方法

1、命令行使用说明:
用法:java -jar MCPTool.jar [-path] [arg] [-contents] [arg] [-password] [arg]
-path APK文件路径
-outdir 输出路径(可选),默认输出到APK文件同一目录
-contents 写入内容集合,多个内容之间用“;”分割,如:googleplay;m360; 当没有“-contents”参数时输出已有文件中的content
-password 加密密钥(可选),长度8位以上,如果没有该参数,不加密
-version 显示版本号
例如:

写入:
java -jar MCPTool.jar -path D:/test.apk -outdir ./ -contents googleplay;m360; -password 12345678
读取:
java -jar MCPTool.jar -path D:/test.apk -password 12345678

2、Android代码中读取写入的渠道号:
导入MCPTool.jar中的MCPTool类,MCPTool.getChannelId(context, mcptoolPassword, defValue)读出写入的渠道号;

3、jenkins、hudson、ant使用说明:
请看MultiChannelPackageTool\build-ant\MCPTool\build.xml文件;

4、Windows下bat脚本运行说明:
拖拽文件即可完成多渠道打包:MultiChannelPackageTool\build-ant\MCPTool\MCPTool.bat;
拖拽文件检查渠道号是否写入成功:MultiChannelPackageTool\build-ant\MCPTool\MCPTool-check.bat;

  • 获取渠道号
/**     * Android平台读取渠道号     * @param context Android中的android.content.Context对象     * @param mcptoolPassword mcptool解密密钥     * @param defValue 读取不到时用该值作为默认值     * @return     */    public static String getChannelId(Object context, String mcptoolPassword, String defValue) {        String content = MCPTool.readContent(new File(getPackageCodePath(context)), mcptoolPassword);        return content == null || content.length() == 0 ? defValue : content;    }
String channelId = MCPTool.getChannelId(context,password,default);

优缺点

没有解压缩、压缩、重签名,没有兼容性问题,速度最快;写入的渠道号数据支持加密,安全可靠;

由于速度极快,我还可以作为服务器端下载apk时动态写入“特定数据”,用户下载到apk后安装启动,读取“特定数据”完成特定的操作;
如:加好友功能,下载前写入用户ID,用户下载后启动apk,读取写入的用户ID,完成加好友操作,用户体验大大提升,没有断裂感;
当然,也可以写入JSON数据,想做什么就做什么;

引用

seven456:MultiChannelPackageTool


更多相关文章

  1. Android多渠道打包(五):360多渠道打包+
  2. webpack 打包多html
  3. vue 打包后,放到tp5框架中总是报错Uncaught TypeError: Cannot re
  4. 纯静态文件打包部署预览链接,来自于vue的cli官方文件,使用的是yarn
  5. NPM包管理工具、webpack模块打包器体验
  6. 如何使用Spark快速将数据写入Elasticsearch
  7. Flink 数据持久化踩过的坑
  8. 【前端】在electron使用ckplayer播放rtmp在开发环境可以播放,打包
  9. dataset与classlist的使用案例

随机推荐

  1. Android(安卓)众多的布局属性详解
  2. 系出名门Android(9) - 数据库支持(SQLite
  3. 从零开始学android开发- layout属性介绍
  4. Netty多语言(Java、Android(安卓)、C#、We
  5. ImageView android:scaleType属性详解
  6. win10 编译 Android(安卓)ffmpeg
  7. Android(安卓)各种音量的获取和设置
  8. Android(安卓)Studio常用快捷键、Android
  9. Android上层启动过程的几个关键点
  10. Android(安卓)android:exported = true