网易美学 Android 渠道包打包实践

西西吹雪2018-05-25 11:54


背景

安卓的渠道包分发一直都是比较头疼的问题,项目初期的时候需要的渠道其实并不多,因此并不是很在意这块。

随着业务的增长渠道包的数量也越来越多,导致我们每次发版本和构建的时候都需要花费很长的时间(初步估算了下,五十多个渠道包的构建甚至可以达到了半个小时甚至更多时间)。


方案

网上其实有很多的现成的方案可以供选择,通行的思路就是先打个 release 包,然后写入对应的渠道信息后再重新打包和签名。

例如,以下的几个工具:

上面的工具基本上就已经能满足业务的需要。但是,仔细思考下以后,还是会有很多(潜在的)问题和风险。

  • 无法使用最新的 APK Signature Scheme v2
  • 大部分使用第三方脚本去处理,增加脚本本身的维护成本
  • Android 代码中如何调用渠道包的名字需要自行编写,不保证特例情况

等等这些方案,都没有能够彻底有效的解决渠道包的后续扩展以及维护等问题。

Walle

后来发现,其实美团的技术团队已经在 Android 打渠道包这块有非常深入的研究,他们并编写了个 gradle 插件开源在了 github 上:

https://github.com/Meituan-Dianping/walle

部署的过程就不表了,本身项目的文档就已经很详细。这里主要说下前后的差异,基本上生成五十多个渠道包的时间可以从半个小时压缩至三分钟内

同时,顺便将原先的 apk 签名升级到了 v2 版本(放心吧,向下兼容的)。

注意事项

由于渠道包生成的方式改变了以后,那么针对获取渠道包的相关代码都需要更改。

这里,我们为了兼容老的获取渠道包的方式,截取了部分的相关方法和逻辑,供参考:

@RequiresApi(api = Build.VERSION_CODES.GINGERBREAD)
public static String getChannel(Context context) {
    String channelName;
    try {
        channelName = WalleChannelReader.getChannel(context.getApplicationContext());
        if (channelName == null || channelName.isEmpty()) {
            ApplicationInfo appInfo = context.getPackageManager()
                    .getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
            channelName = appInfo.metaData.getString("DA_CHANNEL_VALUE");
        }
    } catch (PackageManager.NameNotFoundException | RuntimeException e) {
        channelName = CHANNEL_UNKNOWN;
    }

    return channelName;
}

其实还有个比较坑的地方就是 DA 那边的情况。

  1. DA 的统计信息不是同步的,同时针对已有的已经登记过渠道的设备,DA 的后台是不作计数的。
  2. 我们无法拿到 DA SDK 的源代码,不知道 DA 本身获取渠道的逻辑,如果还是使用 manifest 中的 DA_CHANNEL_VALUE,那么肯定不入我们所愿。因此,使用了 Walle 以后,务必在 DATrack 初始化的时候,带入相关的渠道包信息参数。


  本文来自网易实践者社区,经作者吕峰军授权发布。