Android多渠道打包

目錄

一、Python打包及優(yōu)化(美團(tuán)多渠道打包)

二、Gradle打包

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

參考閱讀

早幾個(gè)月前在有心課堂看過(guò)Android多渠道打包的視頻,覺(jué)得蠻有用的,時(shí)至今日卻發(fā)現(xiàn)不少具體的細(xì)節(jié)已經(jīng)忘得差不多,于是重新整理了一篇筆記,順道分享給大家。

一、Python打包及優(yōu)化(美團(tuán)多渠道打包)

既然是Python打包,那么python環(huán)境是必須的,否則無(wú)法運(yùn)行python腳本文件,mac系統(tǒng)下默認(rèn)安裝了Python環(huán)境,而Windows系統(tǒng)下則需要自己安裝了,這個(gè)安裝過(guò)程相對(duì)可以簡(jiǎn)單,大家可以自行谷歌下,記得配好環(huán)境變量。驗(yàn)證是否安裝成功的方式是,打開(kāi)命令行,輸入python,如果安裝成功的話,會(huì)打印python的版本信息。

下面我們以友盟應(yīng)用統(tǒng)計(jì)為例,進(jìn)行相關(guān)的操作。

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

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


xiaomi
360mobile
wandoujia
baidu

另外python腳本文件、ChannelUtil.java這里就不貼代碼了,有點(diǎn)長(zhǎng),但還是比較簡(jiǎn)單容易理解的,大家可以自己下載下來(lái)看看,附上 :傳送門(mén)

使用姿勢(shì):

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


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

生成好以后,將該apk文件和上面所準(zhǔn)備的東西放在同一個(gè)文件夾,打開(kāi)終端命令行,進(jìn)入該文件夾。執(zhí)行命令:

python channel.py apk包名

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

這一條簡(jiǎn)單的命令背后,到底隱藏著什么不為人知的流程呢?請(qǐng)看下圖:

Python打包流程

整理思路來(lái)看,就是通過(guò)python腳本去讀取渠道列表,然后一個(gè)for循環(huán)將簽名好的apk寫(xiě)入渠道號(hào),并在當(dāng)前目錄下,生成一個(gè)release文件夾,將寫(xiě)入好的渠道包放進(jìn)去,那么這個(gè)for循環(huán)內(nèi)部究竟是怎樣的一個(gè)操作呢?它分為以下幾步:

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

這種通過(guò)python打包的方式有什么優(yōu)點(diǎn)和缺點(diǎn)呢?

優(yōu)點(diǎn):

  • 只需要一個(gè)簽名好的apk
  • 速度快(在渠道少的情況下,基本秒開(kāi),如果渠道更多,有100多個(gè)的話應(yīng)該也不會(huì)超過(guò)一分鐘)

缺點(diǎn):

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

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

  • 在Google Play上提交會(huì)失敗(如果你的應(yīng)用要上傳到該市場(chǎng)的話
  • Lollipop系統(tǒng)(Android 5.0.1)安裝可能會(huì)提示解析安裝包錯(cuò)誤

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

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

簡(jiǎn)單提煉為關(guān)鍵詞就是:優(yōu)化工具4字節(jié)邊界對(duì)齊、減少內(nèi)存使用提高效率

何時(shí)需要使用這個(gè)工具?

  • apk簽名之后(在開(kāi)發(fā)過(guò)程中,更多的時(shí)候是eclipse、as自動(dòng)幫我們使用了這個(gè)工具,不需要我們手動(dòng)去使用它的
  • 對(duì)apk進(jìn)行添加或更改的時(shí)候

常用的命令:

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

-c :驗(yàn)證apk是否按照某種對(duì)齊方式對(duì)齊

-f :覆蓋已經(jīng)存在的文件

-v :輸出verbose級(jí)別的信息

<alignment> :對(duì)齊方式,這里我們以4字節(jié)的方式對(duì)齊

existing.apk :需要驗(yàn)證的apk文件

infile.apk :要打包的apk文件

outfile.apk :要輸出的apk文件

第一條命令是用來(lái)驗(yàn)證apk是否有進(jìn)行過(guò)zipalign優(yōu)化;第二條命令是用來(lái)進(jìn)行zipalign優(yōu)化

那么zipalign這個(gè)工具在哪里呢?

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

在使用的時(shí)候,我們通常先用第一條命令判斷我們的apk文件是否已經(jīng)進(jìn)行過(guò)zipalign優(yōu)化,接著再使用第二條命令是優(yōu)化我們的apk文件,快捷命令:

首先是驗(yàn)證apk:

zipalign -c -v 4 demo_channel.apk

進(jìn)行zipalign優(yōu)化:

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

有些同學(xué)可能會(huì)問(wèn),你這一個(gè)apk優(yōu)化還好,那如果有很多個(gè)渠道包,我們應(yīng)該怎么去優(yōu)化呢?這里已經(jīng)在剛剛的傳送門(mén)里,給大家準(zhǔn)備好了兩個(gè)腳本文件,分別是mac系統(tǒng)下的zipalign_batch.sh和windows系統(tǒng)下的zipalign_batch.bat文件,并且已經(jīng)集成到channel.py的python腳本當(dāng)中,我們?cè)谑褂玫臅r(shí)候,可以根據(jù)自己的需要自行開(kāi)啟相關(guān)的代碼即可:


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

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

再次提醒下大家,在開(kāi)啟使用這段代碼的前,要把zipalign工具配置到你系統(tǒng)的環(huán)境變量里,否則在運(yùn)行python腳本過(guò)程中會(huì)提示相關(guān)的文件找不到哈。

二、Gradle打包

相信大部分開(kāi)發(fā)者都已經(jīng)遷移到AS下進(jìn)行開(kāi)發(fā),那么利用gradle進(jìn)行多渠道打包也是我們必須掌握的一個(gè)知識(shí)點(diǎn),下面分別講解下gradle的多渠道打包和多Apk打包。

多渠道打包

多渠道打包,大家應(yīng)該都知道,這里不解釋,同樣以友盟統(tǒng)計(jì)為例,

第一步:

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

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

第二步:

在項(xiàng)目的build.gradle文件中設(shè)置打包簽名信息 signingConfigs:


    android {
        debug {
            // No debug config
        }

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

接著,設(shè)置productFlavors,這里包含你了所需要的渠道號(hào):


    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"]
            }
        }
    }

也有另外一種簡(jiǎn)便的寫(xiě)法,其實(shí)就是用Groovy語(yǔ)法執(zhí)行一個(gè)for循環(huán):


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

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

最后:

在AS的內(nèi)置終端Terminal工具中執(zhí)行命令:

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

好了,接下來(lái)可以靜靜等待打包完成。

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

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

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

多Apk打包

什么叫多Apk打包?可能很多人不知道,也沒(méi)有碰到這樣的需求,多Apk打包其實(shí)就是根據(jù)特定的需求,生成不同類型的apk,譬如說(shuō)每個(gè)apk的有不同的應(yīng)用名稱、應(yīng)用icon或cpu類型等等。

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

同樣地,我們?cè)赽uild.gradle設(shè)置這ProductFlavors即可:


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

這里要插句補(bǔ)充下defaultConfig 跟 productFlavors的關(guān)系,defaultConfig相當(dāng)于一個(gè)默認(rèn)的flavor,如果我們沒(méi)有定義productFlavors,gradle在構(gòu)建過(guò)程中就會(huì)只讀取defaultConfig的配置信息;如果自定義了productFlavors,那么defaultConfig相當(dāng)于每一個(gè)flavor的基礎(chǔ)配置信息。如果flavor和defaultConfig的某些配置項(xiàng)相同,flavor的配置將會(huì)覆蓋defaultConfig。

補(bǔ)充知識(shí)點(diǎn)

Gradle常用命令

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

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

關(guān)于assemble

在上面的assemble命令中,會(huì)結(jié)合Build Type來(lái)創(chuàng)建自己的task,譬如:

  • ./gradlew assembleDebug
  • ./gradlew assembleRelease

除此之外,assemble還能和ProductFlavor 結(jié)合創(chuàng)建新的任務(wù),其實(shí)assemble是和Build >Variants 一起結(jié)合使用的,大家可以這么來(lái)理解:

Build Variants = Build Type + Product Flavor

舉個(gè)栗子:

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

./gradlew assembleWandoujiaRelease

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

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

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

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

基于以上,總結(jié)一下assemble創(chuàng)建task有如下用法:

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

關(guān)于BuildVariants

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


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

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

會(huì)生成以下的BuildVariants:

AS-BuildVariants

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

最后附上送一個(gè)完整的gradle腳本文件:傳送門(mén)

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

核心原理:

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

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

優(yōu)點(diǎn):

  • 沒(méi)有解壓縮、壓縮、重簽名過(guò)程,打包速度極快,單個(gè)包只需要5毫秒左右,甚至可用于網(wǎng)站后臺(tái)動(dòng)態(tài)生成渠道包

缺點(diǎn):

  • 沒(méi)有使用Android的productFlavors,無(wú)法利用flavor條件編譯的功能

相關(guān)工具:

參考閱讀

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android多渠道打包 概述 每當(dāng)發(fā)新版本時(shí),Android客戶端會(huì)被分發(fā)到各個(gè)應(yīng)用市場(chǎng),比如豌豆莢,360手機(jī)...
    礪雪凝霜閱讀 2,230評(píng)論 2 11
  • 我們做Android用戶級(jí)應(yīng)用開(kāi)發(fā)的時(shí)候都要考慮這樣的問(wèn)題,目前的應(yīng)用市場(chǎng)有很多,我們的安裝包是通過(guò)哪個(gè)渠道進(jìn)入用...
    尹star閱讀 8,825評(píng)論 11 26
  • 面試的時(shí)候,如果面試官突然問(wèn)到:你們渠道包是怎么打的?如果你說(shuō)是用gradle一個(gè)一個(gè)編譯的,然后他很鄙視的說(shuō)這個(gè)...
    lovejjfg閱讀 2,514評(píng)論 10 14
  • ###多渠道打包概念 >* 發(fā)布到不同渠道上的apk,標(biāo)記不同的渠道,目的是為了統(tǒng)計(jì)該渠道的下載量,留存率等等數(shù)據(jù)...
    未聞椛洺閱讀 683評(píng)論 0 0
  • 一、什么是多渠道 我理解的是:APP發(fā)布到不同的應(yīng)用平臺(tái),監(jiān)測(cè)用戶是從哪個(gè)平臺(tái)安裝的。 二、為什么要多渠道打包 1...
    LucasAdam閱讀 1,032評(píng)論 0 1

友情鏈接更多精彩內(nèi)容