Android多渠道打包(四):360多渠道打包

来源:互联网 发布:手机数据dns劫持 编辑:程序博客网 时间:2024/04/29 13:54

本章将介绍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<String, String> argsMap = new LinkedHashMap<String, String>();                    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 0
原创粉丝点击