1. 程式人生 > >Android 快速多渠道打包上線實踐

Android 快速多渠道打包上線實踐

前言

今天向大家介紹的便是目前我們智課批改專案組使用的App多渠道打包方案,目前這個方案已經經過幾個迭代的檢驗,效率和穩定性都有保障,希望能對大家的多渠道上線打包有所幫助。

傳統打包方案

//build.gradle
productFlavors {
    channel{
            manifestPlaceholders =[CHANNEL_ID_VALUE: channel]
    }
}
//AndroidManifest.xml
<meta-data            
    android:name="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熱修復,記得儲存此時的基準包,並且使用Thinker

bakApk目錄下的基準包作為未加固版的包去加固。如果應用不需加固,那麼到這一步就可以結束了!

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

目前雖然時間已經降下去了,但是步驟依然還要三步,下一步的目標就是將這些步驟進行整合,然後一條命令搞定~

總結

以上就是目前我們智課批改專案正在使用的打包方案,效率比之前的傳統方案要快的多,希望能對大家有所幫助,如果大家有更好的方案和想法,也歡迎大家在下方評論或私信我交流。由於本人能力有限,如有疏漏或錯誤的地方,望不吝指出。