当前位置 主页 > 服务器问题 > Linux/apache问题 >

    Android使用美团多渠道打包方案详解

    栏目:Linux/apache问题 时间:2019-11-24 20:41

    Andorid渠道市场有多分散呢?分散到比Android碎片化还严重,你还在为多渠道打包而头疼吗?美团提供了速度快到白驹过隙的多渠道打包方案。说的有点夸张,对,虽然夸张,但是确实很快,不夸张不足以形容其快。废话不多说,先讲原理,再讲实践方法。

    新旧打包方法原理对比讲解

    传统方式

    在AndroidManifest定义渠道的年代,多渠道打包无非以下两种方案:

    方案一:完全的重新编译,即在代码重新编译打包之前,在AndroidManifest中修改渠道标示; 方案二:通过ApkTool进行解包,然后修改AndroidManifest中修改渠道标示,最后再通过ApkTool进行打包、签名。

    这两种打包方式,不管是哪种,效率都很低,方案一毫无效率可言,而且打包的渠道规模非常小,第二种方案效率稍微高些,打包的渠道规模也还可以,但是这两种方案速度慢的惊人,如果你打个上百的渠道包试试,估计你的电脑能卡一下午。慢,当然也有好处,你可以不用工作了,喝着咖啡,玩着手机慢慢等也很惬意是不?哈哈……

    美团高效的多渠道打包方案

    美团高效的多渠道打包方案是把一个Android应用程序包当作一个zip文件包进行解压,然后发现在签名生成的目录下添加一个空文件,空文件用渠道名来命名,而且不需要重新签名。这种方式不需要重新签名,编译等步骤,使得这种方法非常高效。

    第一步:解压apk文件

    我们直接解压apk,解压后的根目录会有一个META-INF目录

    如果在META-INF目录内添加空文件,可以不用重新签名应用。因此,通过为不同渠道的应用添加不同的空文件,可以唯一标识一个渠道。

    第二步:用python脚本向apk文件中添加空渠道文件

    我们用python代码来给apk添加空的渠道文件,渠道名的前缀为mtchannel_:

    import zipfile
    zipped = zipfile.ZipFile(your_apk, 'a', zipfile.ZIP_DEFLATED) 
    empty_channel_file = "META-INF/mtchannel_{channel}".format(channel=your_channel)
    zipped.write(your_empty_file, empty_channel_file)

    添加完空渠道文件后的目录,META-INFO目录多了一个名为mtchannel_meituan的空文件

    第三步:用java代码读取渠道名,并动态设置渠道名

    我们用脚本生成了文件之后,文件的名字是用渠道名来命名的,所以我们在启动程序的时候,可以用java代码动态读取渠道名,并动态的去设置。

    java代码读取渠道名的方法:

    public static String getChannel(Context context) {
        ApplicationInfo appinfo = context.getApplicationInfo();
        String sourceDir = appinfo.sourceDir;
        String ret = "";
        ZipFile zipfile = null;
        try {
          zipfile = new ZipFile(sourceDir);
          Enumeration<?> entries = zipfile.entries();
          while (entries.hasMoreElements()) {
            ZipEntry entry = ((ZipEntry) entries.nextElement());
            String entryName = entry.getName();
            if (entryName.startsWith("mtchannel")) {
              ret = entryName;
              break;
            }
          }
        } catch (IOException e) {
          e.printStackTrace();
        } finally {
          if (zipfile != null) {
            try {
              zipfile.close();
            } catch (IOException e) {
              e.printStackTrace();
            }
          }
        }
    
        String[] split = ret.split("_");
        if (split != null && split.length >= 2) {
          return ret.substring(split[0].length() + 1);
    
        } else {
          return "";
        }
      }