Android多渠道打包

目錄

一、Python打包及優化(美團多渠道打包)

二、Gradle打包

三、其他打包方案:修改Zip文件的comment

參考閱讀

早幾個月前在有心課堂看過Android多渠道打包的視頻,覺得蠻有用的,時至今日卻發現不少具體的細節已經忘得差不多,于是重新整理了一篇筆記,順道分享給大家。

一、Python打包及優化(美團多渠道打包)

既然是Python打包,那么python環境是必須的,否則無法運行python腳本文件,mac系統下默認安裝了Python環境,而Windows系統下則需要自己安裝了,這個安裝過程相對可以簡單,大家可以自行谷歌下,記得配好環境變量。驗證是否安裝成功的方式是,打開命令行,輸入python,如果安裝成功的話,會打印python的版本信息。

下面我們以友盟應用統計為例,進行相關的操作。

需要準備的東西:
  • 簽名好的Apk文件
  • channel.py (python腳本文件
  • channel列表文件 (注:必須命名為android_channels.txt,如果不想這樣命名,可自行更改python腳本代碼
  • ChannelUtil.java工具類

其中channel列表文件(android_channels.txt)的格式為每一個渠道號換一行,示例:


xiaomi
360mobile
wandoujia
baidu

另外python腳本文件、ChannelUtil.java這里就不貼代碼了,有點長,但還是比較簡單容易理解的,大家可以自己下載下來看看,附上 :傳送門

使用姿勢:

首先,在簽名打包一個Apk之前,需要在程序的入口處添加如下代碼:


        String channel= ChannelUtil.getChannel(mAppContext);  //獲取渠道號,內存>SharedPreferences>apk的/META-INF/目錄
        MobclickAgent.startWithConfigure(new MobclickAgent.UMAnalyticsConfig(getApplicationContext(),umengAppkey,channel)); //友盟:通過代碼的方式設置渠道號

生成好以后,將該apk文件和上面所準備的東西放在同一個文件夾,打開終端命令行,進入該文件夾。執行命令:

python channel.py apk包名

很快就在當前目錄下生成一個release文件夾,里面生成了各個渠道所需要的渠道包。

這一條簡單的命令背后,到底隱藏著什么不為人知的流程呢?請看下圖:

Python打包流程

整理思路來看,就是通過python腳本去讀取渠道列表,然后一個for循環將簽名好的apk寫入渠道號,并在當前目錄下,生成一個release文件夾,將寫入好的渠道包放進去,那么這個for循環內部究竟是怎樣的一個操作呢?它分為以下幾步:

  1. 復制簽名好的signatured.apk到./release文件夾下
  2. 重命名signatured.spk 為 signatured_channel_xxx.apk
  3. 找到apk/META-INF/目錄
  4. 新建一個文件名為 channel_xxx的空文件

這種通過python打包的方式有什么優點和缺點呢?

優點:

  • 只需要一個簽名好的apk
  • 速度快(在渠道少的情況下,基本秒開,如果渠道更多,有100多個的話應該也不會超過一分鐘)

缺點:

  • 依賴Java的簽名方式(現有的打包方式,在apk的META-INF目錄下添加文件,是不需要重新簽名的,但如果谷歌更改了這套簽名方式,那么這種方法就不適用了)
  • 必須支持只用Java代碼寫入渠道號
zipalign優化:

是否上述的這種打包方式就一定完美了呢?也許你會遇到這樣的問題:

  • 在Google Play上提交會失敗(如果你的應用要上傳到該市場的話
  • Lollipop系統(Android 5.0.1)安裝可能會提示解析安裝包錯誤

所以介紹來要介紹另外一款工具——zipalign,官方的定義是這樣子的:

zipalign is an archive alignment tool that provides important optimization to Android application (APK) files

簡單提煉為關鍵詞就是:優化工具4字節邊界對齊減少內存使用提高效率

何時需要使用這個工具?

  • apk簽名之后(在開發過程中,更多的時候是eclipse、as自動幫我們使用了這個工具,不需要我們手動去使用它的
  • 對apk進行添加或更改的時候

常用的命令:

  • zipalign -c -v <alignment> existing.apk
  • zipalign [-f] [-v] <alignment> infile.apk outfile.apk

-c :驗證apk是否按照某種對齊方式對齊

-f :覆蓋已經存在的文件

-v :輸出verbose級別的信息

<alignment> :對齊方式,這里我們以4字節的方式對齊

existing.apk :需要驗證的apk文件

infile.apk :要打包的apk文件

outfile.apk :要輸出的apk文件

第一條命令是用來驗證apk是否有進行過zipalign優化;第二條命令是用來進行zipalign優化

那么zipalign這個工具在哪里呢?

我們可以打開android sdk的安裝目錄下,在build-tools/版本號文件夾/找到一個zipalign.exe,其實zipalign是在android 1.6之后提供的一個工具,在使用之前我們最好可以把這個路徑配置到環境變量里。

在使用的時候,我們通常先用第一條命令判斷我們的apk文件是否已經進行過zipalign優化,接著再使用第二條命令是優化我們的apk文件,快捷命令:

首先是驗證apk:

zipalign -c -v 4 demo_channel.apk

進行zipalign優化:

zipalign -f -v 4 demo_channel.apk demo_align.apk

有些同學可能會問,你這一個apk優化還好,那如果有很多個渠道包,我們應該怎么去優化呢?這里已經在剛剛的傳送門里,給大家準備好了兩個腳本文件,分別是mac系統下的zipalign_batch.sh和windows系統下的zipalign_batch.bat文件,并且已經集成到channel.py的python腳本當中,我們在使用的時候,可以根據自己的需要自行開啟相關的代碼即可:


    #mac
    #os.system('chmod u+x zipalign_batch.sh')
    #os.system('./zipalign_batch.sh')

    #windows
    #os.system('zipalign_batch.bat')

再次提醒下大家,在開啟使用這段代碼的前,要把zipalign工具配置到你系統的環境變量里,否則在運行python腳本過程中會提示相關的文件找不到哈。

二、Gradle打包

相信大部分開發者都已經遷移到AS下進行開發,那么利用gradle進行多渠道打包也是我們必須掌握的一個知識點,下面分別講解下gradle的多渠道打包和多Apk打包。

多渠道打包

多渠道打包,大家應該都知道,這里不解釋,同樣以友盟統計為例,

第一步:

在AndroidManifest.xml文件中配置渠道ID,${UMENG_CHANNEL_VALUE} 為占位符,其中的UMENG_CHANNEL_VALUE可以自己任意定義

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

第二步:

在項目的build.gradle文件中設置打包簽名信息 signingConfigs:


    android {
        debug {
            // No debug config
        }

        release {
            storeFile file("../yourapp.jks")
            storePassword "your password"
            keyAlias "your alias"
            keyPassword "your password"
        }
    }

接著,設置productFlavors,這里包含你了所需要的渠道號:


    android {
        productFlavors {
            xiaomi {
                manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"]
            }
            360 mobile {
                manifestPlaceholders = [UMENG_CHANNEL_VALUE: "360mobile"]
            }
            wandoujia {
                manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
            }
            baidu {
                manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"]
            }
        }
    }

也有另外一種簡便的寫法,其實就是用Groovy語法執行一個for循環:


    productFlavors {
        xiaomi {}
        360 mobile {}
        wandoujia {}
        baidu {}
    }

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

最后:

在AS的內置終端Terminal工具中執行命令:

./gradlew assembleRelease
(所有生成的apk在項目的build\outputs\apk下)

好了,接下來可以靜靜等待打包完成。

如果不想使用命令行的方式進行打包,AS也為我們提供了圖形界面的方式,點擊菜單欄->Build->Generate Signed APK,輸入相關的簽名證書路徑和密碼即可:

圖形界面打包1
圖形界面打包2

這種打包方式的其中一個好處是可以指定打包后的apk所存放的路徑。

多Apk打包

什么叫多Apk打包?可能很多人不知道,也沒有碰到這樣的需求,多Apk打包其實就是根據特定的需求,生成不同類型的apk,譬如說每個apk的有不同的應用名稱、應用icon或cpu類型等等。

下面以生成不同的cup類型的apk為例,cup的類型大致可以分為分別是arm、mips、X86這三種:

同樣地,我們在build.gradle設置這ProductFlavors即可:


    productFlavors {
        arm {
            ndk{
                abiFilters("armeabi","armeabi-v7a")
            }
        }
        mips {
            ndk{
                abiFilters("mips","mips86")
            }
        }
        x86 {
            ndk{
                abiFilters("x86","x86_64")
            }
        }
    }

這里要插句補充下defaultConfig 跟 productFlavors的關系,defaultConfig相當于一個默認的flavor,如果我們沒有定義productFlavors,gradle在構建過程中就會只讀取defaultConfig的配置信息;如果自定義了productFlavors,那么defaultConfig相當于每一個flavor的基礎配置信息。如果flavor和defaultConfig的某些配置項相同,flavor的配置將會覆蓋defaultConfig。

補充知識點

Gradle常用命令

  • ./gradlew -v :版本號
  • ./gradlew clean :清除項目/app目錄下的build文件夾
  • ./gradlew build 檢查依賴并編譯打包
需要注意的是 ./gradlew build 命令會debug、release環境的包都打出來,如果正式發布只需要打Release的包,可以使用assemble命令
  • ./gradlew assembleDebug :編譯并打Debug包
  • ./gradlew assembleRelease :編譯并打Release的包
  • ./gradlew installRelease :Release模式打包并安裝
  • ./gradlew uninstallRelease :卸載Release模式包

我們執行命令前,都會加上./gradlew./代表當前目錄,gradlew代表gradle wrapper,意思是gradle的一層包裝,可以理解為在這個項目本地就封裝了gradle,即gradle wrapper。在項目名/gradle/wrapper/gralde-wrapper.properties文件中聲明了它指向的目錄和版本.

關于assemble

在上面的assemble命令中,會結合Build Type來創建自己的task,譬如:

  • ./gradlew assembleDebug
  • ./gradlew assembleRelease

除此之外,assemble還能和ProductFlavor 結合創建新的任務,其實assemble是和Build >Variants 一起結合使用的,大家可以這么來理解:

Build Variants = Build Type + Product Flavor

舉個栗子:

如果我們想打wandoujia渠道的Release版本,可以執行如下命令

./gradlew assembleWandoujiaRelease

如果我們只打wandoujia渠道版本,則:

./gradlew assembleWandoujia
(此命令會生成wandoujia渠道的Release和Debug版本)

同理,如果想打全部Release版本:

./gradlew assembleRelease
(這條命令會把Product Flavor下的所有渠道的Release版本都打出來)

基于以上,總結一下assemble創建task有如下用法:

  • 允許直接構建一個Variant版本,例如 assembleFlavor1Debug
  • 允許構建指定Build Type的所有APK,例如assembleDebug將會構建Flavor1Debug和Flavor2Debug兩個Variant版本
  • 允許構建指定flavor的所有APK,例如assembleFlavor1將會構建Flavor1Debug和Flavor1Release兩個Variant版本

關于BuildVariants

在AS中有個BuildVariants的概念,Build Variants = Build Type + Product Flavor,譬如如下代碼:


android {
    productFlavors {
        xiaomi {}
        _360mobile {}
        wandoujia {}
        baidu {}
    }

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

會生成以下的BuildVariants:

AS-BuildVariants

我們就可以看到,productFlavors有多個維度,并且每個Flavor都有debug和release,所以總共生成Build Type*ProductFlavor個不同的apk,也即2*4=8種不同的APK。

最后附上送一個完整的gradle腳本文件:傳送門

三、其他打包方案:修改Zip文件的comment

核心原理:

Android應用使用的APK文件就是一個帶簽名信息的ZIP文件,根據 ZIP文件格式規范 ,每個ZIP文件的最后都必須有一個叫 Central Directory Record 的部分,這個CDR的最后部分叫"end of central directory record",這一部分包含一些元數據,它的末尾是ZIP文件的注釋。注釋包含Comment Length和File Comment兩個字段,前者表示注釋內容的長度,后者是注釋的內容,正確修改這一部分不會對ZIP文件造成破壞,利用這個字段,我們可以添加一些自定義的數據。

所以原理很簡單,就是將渠道信息存放在APK文件的注釋字段中

優點:

  • 沒有解壓縮、壓縮、重簽名過程,打包速度極快,單個包只需要5毫秒左右,甚至可用于網站后臺動態生成渠道包

缺點:

  • 沒有使用Android的productFlavors,無法利用flavor條件編譯的功能

相關工具:

參考閱讀

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android多渠道打包 概述 每當發新版本時,Android客戶端會被分發到各個應用市場,比如豌豆莢,360手機...
    礪雪凝霜閱讀 2,159評論 2 11
  • 我們做Android用戶級應用開發的時候都要考慮這樣的問題,目前的應用市場有很多,我們的安裝包是通過哪個渠道進入用...
    尹star閱讀 8,781評論 11 26
  • 面試的時候,如果面試官突然問到:你們渠道包是怎么打的?如果你說是用gradle一個一個編譯的,然后他很鄙視的說這個...
    lovejjfg閱讀 2,313評論 10 14
  • ###多渠道打包概念 >* 發布到不同渠道上的apk,標記不同的渠道,目的是為了統計該渠道的下載量,留存率等等數據...
    未聞椛洺閱讀 639評論 0 0
  • 一、什么是多渠道 我理解的是:APP發布到不同的應用平臺,監測用戶是從哪個平臺安裝的。 二、為什么要多渠道打包 1...
    LucasAdam閱讀 947評論 0 1