Android多渠道打包技术对比

Posted by 程序亦非猿 on 2017-01-16

前言

本文整理自我去年在公司内部做的一次分享,去掉了公司的信息,整理出来分享一下。
希望对读者有所帮助。

加入公司后,就一直负责App的多渠道打包,今天来分享一下多渠道打包技术的介绍与对比,以及我们最后的选择。

什么是多渠道打包技术

我们知道,由于某种黑暗力量,Android的亲爹市场 GooglePlay 不能进入大陆,导致大陆 Android 市场众多,如:小米、豌豆荚、华为等等等。

当新版本发布,我们需要通过渠道号来区分不同的市场,为不同市场生成不同的包,再把对应的包上传到各个市场。这种为App打出不同渠道包的技术称为多渠道打包技术

怎么去做多渠道打包

多渠道打包实现有多种,但是有两点不会变:

  1. 渠道区分
  2. 打包

接下去介绍一下现今的多渠道打包技术,以及它们之间的对比。

Umeng+Gradle

我们 App 集成了 Umeng 的服务,所以就拿它举例了,事实上,不用 Umeng 也没有丝毫关系。

渠道的区分

AndroidManifest.xml中配置一个meta-data

1
2
3
<meta-data
android:name="UMENG_CHANNEL"
android:value="${CHANNEL_NAME}"/>

然后在app/build.gradle里配置productFlavors

1
2
3
4
5
6
7
8
productFlavors {
def path = "channels.txt"
file(path).eachLine { channel ->
"$channel" {
manifestPlaceholders = [CHANNEL_NAME: channel]
}
}
}
PS:channels.txt 是渠道列表文件,每一行代表一个渠道,这样方便管理。

打包方法

使用 ./gradlew assembleRelease命令,就可以打出多渠道的包了。

原理

该种方式的打包原理是利用了 Gradle 的flavors功能来实现的,渠道的获取是通过如下代码方式获取。

1
2
ApplicationInfo appInfo = cxt.getPackageManager().getApplicationInfo(cxt.getPackageName(), PackageManager.GET_META_DATA);
String channel = String.valueOf(appInfo.metaData.get("UMENG_CHANNEL"));

优缺点

优点:

  1. 简单,易懂,没什么门槛,也不需要依赖其他工具与插件。
  2. Gradle强大的flavor功能,可以实现不同渠道拥有不同的代码实现,可以给渠道做定制包。
  3. 扩展性强大,没有兼容性问题。

缺点:

  1. 打包速度极慢,因为每个渠道包都是从“0到1”,渠道一多,打包时间以小时为单位。

PS:我们 App 几百个渠道,用这种方式打包需要2多个小时,怎么受得了?。

所以,该方式适合渠道不多的时候使用,或者不同渠道需要使用不同的代码。

美团的打包方案

上面说到,每个渠道包都是从“0到1”,然而实际上,渠道包之间的唯一差别仅仅在于一个渠道号(这里暂时只考虑不同渠道的代码相同),如果能拿已经打好的包,拿来修改一下渠道号,变成另一个渠道包,那这速度就能大幅度提高了。

美团的打包方案,利用META-INF(解压APK可以看到)不参与 APK 签名的原理,在META-INF新增空的文件来代表渠道,实现了这个功能,极大的提高了打包的速度。

渠道的区分

META-INF目录下新增空文件,再在代码中读取文件名获取()。

PS:可以去市场下载一个美团 APP 来解压一下看看。

打包方法

由于美团并没有给出具体的实现代码,所以我当时尝试的是开源实现:安卓多渠道打包工具

原理

上面已经提到了,META-INF不参与 APK 签名。

META-INF目录下新增一个空的文件来代表渠道名。

这样就可以只打一次签名包,后续只需拷贝,新增渠道文件即可。

优缺点

优点:

  1. 速度极快,每打一个包就只需要复制一个APK,并新增一个空文件即可。(900个包一分钟,我天)
  2. 可以利用已存在的包打新的渠道包。(可多个)

第2点其实也是非常棒的优点,当需要一个新的渠道包时,不再需要停下工作,去保存代码,切分支,build,打包,只要一个已存在的包,一个命令就好,非常方便。

缺点:

  1. 不安全,由于不需要签名,所以任何人都可以拿到已有的包,修改成任意其他渠道的包,可能会被恶意利用污染渠道数据。
  2. 扩展性较差。(暂时没有Gradle的实现方案,相对来说选择余地较小,扩展性也差一些)
  3. 不支持 flavors
  4. 潜在风险,现在META-INF不参与APK签名,万一以后参与了,那么这套方案就失效了,当然这个概率估计很小。
  5. 似乎不支持 android 7.0?issue(没亲测,未知)
  6. 需要修改代码,修改渠道的获取方式(Umeng配置修改)

美团打包方式是一次大创新,最吸引人的就是速度快,真心快,就是打包的时间喝杯水再也不够了。

packer-ng-plugin

名字太长,简称为 packer 吧。号称『下一代Android打包工具』,拥有与美团的方案相媲美的打包速度。

原理

我们知道,其实 APK 是一个 Zip 文件,所以 APK 拥有 Zip 格式的特点。

该方法利用 Zip 格式的特点,修改Comment LengthFile Comment两个字段,不会对ZIP文件造成破坏,将渠道信息放入其中,达到修改渠道的目的。由于修改以上内容也不需要重新签名打包,所以拥有与美团的方案相媲美的打包速度。

更多详情,见原项目Github。

渠道区分

渠道信息存放在APK文件的注释字段File Comment,在代码中使用 packer 提供的方法获取。

打包方法

提供了三种实现方式,Gradle、Java、Python,都可以使用。

优缺点

优点:

  1. 打包速度极快。(与美团方案速度差不多)
  2. 选择性更多,作者很良心,提供了Gradle,Java,Python三种实现。
  3. 扩展性强大,由于有 Gradle 的实现方案,所以扩展性有了保障。

缺点:

  1. 不支持 flavors
  2. 需要修改代码,修改渠道的获取方式。(Umeng配置修改)
  3. 有潜在兼容性问题,具体可见 兼容性问题(已经解决)
  4. 潜在风险,Zip 格式万一修改,那么该方式失效,这概论应该也非常低。
  5. 已知360加固后,重新签名Apk后会抹去渠道信息。

小结

packer 利用 Zip 格式,又一个多渠道打包的创新,速度极快,又安全,非常棒!

对比

对比项 Gradle 美团 packer
是否支持 flavors
打包速度 极快 极快
安全性 有风险
扩展性 较低 较高
兼容性问题
风险 极低 极低
加固影响 未测试 丢失渠道信息(360加固)

如何选择?

目前只有Gradle支持flavors功能,所以如果这个需求强烈,那么就只能选择Gradle。

如果没有这个需求,那么相对于美团打包的方式,第三种方式packer更加安全一些,速度方面也令人满意。

当然如果使用美团方式,可以在服务端过滤非法的渠道,也是可以的!~(看了美团的 APK,渠道是明文的,所以估计也是在服务端处理的,如果用的是 Umeng 统计,那么就不行喽)。

最后我们的选择是,以packer为主,Gradle为辅。

资料

美团Android自动化之旅—生成渠道包
安卓多渠道打包工具