Android Packaging

国内市场因为 android 的发布渠道比较多,所以一般我们会想要追踪一下用户使用的包是从哪里下载安装的。

Android 打包支持 buildTypes ,一般这个会用来区分不同的环境,比如 dev,beta,prod 等,不同环境可能会有一些不同的设置,比如 dev 会打开更多的日志输出什么的。

    android{
        buildTypes {
            debug {
                ...
            }
            release {
                ...
            }
            beta {
                ...
            }
        }
    }

还有一个支持是 productFlavors,一般用这个来区分不同的渠道,不同渠道也可以有一些不同的设置,类似上面的 buildTypes。

    android {  
        productFlavors {
            xiaomi {}
            baidu {}
            wandoujia {}
            x360 {}
        }

        productFlavors.all {
            flavor -> flavor.manifestPlaceholders = [CHANNEL_ID: name]
        }
    }

配合 AndroidManifext.xml 文件的配置

   <meta-data android:name="CHANNEL_ID" android:value="${CHANNEL_ID}" />

在代码里面取到这个,然后设置渠道。

这样就可以打渠道包了 ./gradlew assembleWandoujiaRelease 编译 wandoujia 这个渠道的 releases 包。这个方式有一个问题是,每一个渠道包都需要从头编译一次,一个渠道 10 分钟,那所有渠道下来,就可能需要一个小时了,关键是很多无用功。

受不了这个,然后发现了美团的思路。有一个民间的方案 https://github.com/GavinCT/AndroidMultiChannelBuildTool

这个方案的主要思路是 apk 只编译一次,编译好之后,通过在 apk 里面增加不同名字的文件的方式来区分不同的渠道。app 运行的时候,读这个文件名字,然后设置对应的渠道。

对于 v1 签名的 apk,在 META-INF 下面增加空文件不需要重新签名,所以只需要再次 zip 压缩就可以。

对于 v2 签名的 apk,需要重新签名,可以使用 apksigner 这个程序,这个是 android sdk 带的。我的 mac 系统路径是 ~/Library/Android/sdk/build-tools/*/apksigner ,因为会安装多个 build-tools 版本,所以会有多个,用哪个都可以。

    cmd = [apksigner, "sign", "--ks", "your_key_store_path", "--ks-pass", "pass:your_pass", "--ks-key-alias", "your_alias", apk]
    check_call(cmd)

这样就可以了。

我看美团似乎弄了一个新的版本 https://github.com/Meituan-Dianping/walle 看着挺复杂的,没研究过。