Android 快速多渠道打包上线实践

前言

今天向大家介绍的便是目前我们智课批改项目组使用的App多渠道打包方案,目前这个方案已经经过几个迭代的检验,效率和稳定性都有保障,希望能对大家的多渠道上线打包有所帮助。

传统打包方案

//build.gradle
productFlavors {
    channel{
            manifestPlaceholders =[CHANNEL_ID_VALUE: channel]
    }
}
//AndroidManifest.xml
"CHANNEL_ID"           
    android:value="${CHANNEL_ID_VALUE}" />

这种方式是Google推荐的方式,但这种方式对于几个渠道包是可以支持的, 当我们需要打几十上百个渠道包时,这种方案耗时很长,是项目开发不能忍受的。而且目前我们项目需要进行加固后保障安全,发布市场的app需要进行加固。于是我们需要先打出一个通用包,然后去三方加固平台去加固,加固后再用三方加固平台的多渠道打包,目前公司的渠道大约有20多种,整个过程下来大约需要一个多小时,整个过程繁琐费时,也非常不符合极客精神,于是在这种情况下,我开始研究新的方案来解决打渠道包耗时费力的问题。

全新打包方案

介绍方案前,先说下目前全新打包方案的耗时:整个过程下来大约需要4分钟左右,主要耗时在第一次打未加固包上,时间和项目大小有关,而加固包多渠道打包只需2秒左右搞定,60+分钟VS4分钟,你值得拥有!

1、接入Walle

Walle是美团技术团队开源的基于Android Signature V2 Scheme 签名下的新一代渠道包打包神器,跟Gradle打包不一样,walle是在APK Signature Block区块添加自定义的渠道信息,写渠道时无需解压Apk,所以速度和传统方案不可同日而语。具体接入文档请参看Walle接入文档。

2、打未加固包

首先需要利用walle打一个未加固版的包。

./gradlew clean assembleReleaseChannels

如果接入了公司使用的Thinker热修复,记得保存此时的基准包,并且使用ThinkerbakApk目录下的基准包作为未加固版的包去加固。如果应用不需加固,那么到这一步就可以结束了!

3、将基准包利用三方加固平台加固

这里必须使用V2签名 ,在加固的时候要注意,不能用例如360的签名工具,因为他们使用的签名方式一般还是V1的。这里以360加固为例,可以去360加固网页版生成加固包。

这里再简单普及下V2签名和V1签名的知识。V1(Android Signature V1 Scheme),Apk包在安装的时候,会对META—INF目录下的.RSA.SF.MF依次校验,整个校验过程需要对文件进行解压,所以速度会比较慢。V2(Android Signature V2 Scheme),是Android 7.0推出了新的应用签名方案。新的签名方案会在ZIP文件格式的 Central Directory 区块所在文件位置的前面添加一个APK Signing Block区块。对比V1旧签名方案,它有更快的验证速度和更安全的保护。

由于篇幅有限,这里不做过多介绍,如果你对Android签名机制感兴趣,可以去看下QQ音乐技术团队分享的技术文章,写的很深入:分析 Android V2 新签名打包机制

4、利用脚本打多渠道包

这里需要注意的是,由于三方加固后,渠道包信息丢失,所以需要重新打渠道包,具体原因可以参看官方Wiki的360加固失效?
版块。

由于解决方案涉及zip对齐、apk的重签名、V2签名校验、walle多渠道写入等多个步骤,命令十分繁琐,于是我用python写了一个自动化脚本来整合这些步骤,一条命令即可完美解决加固包导致渠道失效问题。此脚本目前也已被walle团队在官方wiki推荐,脚本项目地址:ProtectedApkResignerForWalle

最后将加固好的未签名的包利用上面的脚本工具打出渠道包发给运营发版即可。

关于渠道统计

由于Walle打包后的渠道信息需要重新手动写入其他三方SDK才可正常统计,下面以友盟为例:

 /**
     * 获取瓦力渠道包
     * @return
     */
    public static String getWalleChannel(Context context){
        String defaultValue = "walleUnknown";
        ChannelInfo channelInfo= WalleChannelReader.getChannelInfo(context);
        if (channelInfo != null) {
            String channel = channelInfo.getChannel();
            if (TextUtils.isEmpty(channel)){
                channel = defaultValue;
            }
            return channel;
        }
        return defaultValue;
    }

  //config umeng in your application
  UMConfigure.init(this, AnalyticsConfig.getAppkey(this), getWalleChannel(),
                UMConfigure.DEVICE_TYPE_PHONE, null);

Feature

目前虽然时间已经降下去了,但是步骤依然还要三步,下一步的目标就是将这些步骤进行整合,然后一条命令搞定~

总结

以上就是目前我们智课批改项目正在使用的打包方案,效率比之前的传统方案要快的多,希望能对大家有所帮助,如果大家有更好的方案和想法,也欢迎大家在下方评论或私信我交流。由于本人能力有限,如有疏漏或错误的地方,望不吝指出。

你可能感兴趣的:(【Android,】进阶之路)