Android客戶端打包方案分享


基本介紹

Android應用的自動化打包是應用持續集成以及多渠道發布的基礎。當前Android客戶端自動化打包的主要有兩種方式,Ant和Maven。兩種方式本質上都是調用Android SDK里面提供的工具,不過各自有各自的特點。

1. Ant腳本

好處:開發成本較低,android sdk默認提供ant的打包腳本,可以根據需要進行修改和擴展。

不足:不天然支持包的依賴管理,需要自己寫代碼控制應用的依賴。

2. Maven

好處:天然支持包的依賴管理,依賴管理不需要寫過多的代碼。Maven插件機制容易擴展和定制,方便實現自己的打包流程。

不足:從頭編寫Maven腳本,或者maven插件,大家對Maven的熟悉程度稍低,門檻稍高。

 

這里介紹一種Ant+shell腳本的自動化打包方案。Ant腳本直接復用sdk提供的腳本並稍作擴展,對應用的包依賴和打包流程自動化控制,選擇使用shell實現。

 

具體實施

打包整體邏輯

Shell腳本(見源碼,感謝@今為幫忙重構)

Shell腳本實現了上圖中的邏輯,比較簡單,這里不再細述,可以看一下源碼。

Ant腳本定制

這里主要描述一下對Android自帶ant腳本的定制。

Android SDK里面自帶的ant腳本(在~/android-sdk-linux_x86/tools/ant/build.xml),如果你的Android主工程沒有支持ant構建,那么可以在主工程根目錄下通過運行

android update project -p . –n projectname

來增加ant構建支持,運行后會在根目錄下生成build.xml(通過<import file="${sdk.dir}/tools/ant/build.xml" />繼承自SDK中的build.xml)

SDK中的build.xml有release task,包括了android打包的完成流程,看代碼如下:

<target name="release"
                depends="-set-release-mode, -release-obfuscation-check, -package, -post-package, -release-prompt-for-password, -release-nosign, -release-sign, -post-build"
                description="Builds the application in release mode.">
 </target>

由代碼可見,release任務依賴了8個其它的任務,其實核心的任務就2個:

l   -package 編譯,生成未簽名APK

l   -release-sign 簽名

總結起來整個過程分解為:編譯生成未簽名包簽名兩個階段。我們要做的就是在這兩個階段中增加一個替換渠道號的步驟,如上圖中描述,主要過程核心流程:

  1. 編譯生成未簽名包
  2. 循環替換每個渠道號到未簽名包
  3. 循環針對替換后的未簽名包生成簽名包

 

步驟1和3其實就是原來release任務的分解,代碼如下:

<target name="release2"
                depends="-set-release-mode, -package, -post-package, -release-prompt-for-password, -release-nosign, -post-build"
                description="Builds the application in unsigned mode.">
    </target>
<target name="signapk"
                depends="-set-release-mode,-release-sign, -post-build"
                description="Sign apk.">

Android應用根目錄下自動生成的build繼承自系統的ant腳本,該腳本中的ant task可以直接復用,因此有了上面自己寫的兩個任務release2和signapk,分別表示了1和3階段的任務。

步驟2的邏輯系統ant腳本里面沒有現成的任務,需要自己編寫,代碼如下:

<target name="modichannel">
        <exec executable="${aapt}" taskName="remove">
            <arg value="remove" />
            <arg value="-v" />
            <arg value="./bin/${appname}-release-unsigned.apk" />
            <arg value="assets/channel" />
        </exec>
        <exec executable="${aapt}" taskName="add">
            <arg value="add" />
            <arg value="-v" />
            <arg value="./bin/${appname}-release-unsigned.apk" />
            <arg value="assets/channel" />
        </exec>
    </target>

這個任務做了兩件事兒,第一,調用android sdk的aapt工具先刪除未簽名包中的默認渠道文件,第二,添加新渠道文件到未簽名包。注意這里一定要用android自帶的aapt工具操作apk壓縮包,如果使用zip會對raw文件進行壓縮,這個似乎並不符合apk打包的規范(aapt對raw文件的壓縮有處理,注:對於zip和aapt壓縮的區別並沒有過多深入的了解,有興趣的可以進一步探討),導致打包出來的apk讀取raw目錄下的資源失敗。

 

總結

整個打包流程,代碼量不大,用shell實現打包流程控制,擴展了三個ant task。用這種方案,可以做到針對多渠道發布,只需要一次編譯,多次渠道替換和簽名,因為android編譯很耗時,這樣可以大大減少渠道的打包時間。

 

源碼

http://code.taobao.org/p/android_build/src/

問題

總的來說還是比較簡單的,當然整個過程也遇到了一些問題和雷區,列舉一下,避免再次犯錯,也算經驗積累。

  1. 需要了解ant的繼承機制,和任務依賴機制,這個是這次改造的基礎,避免重復勞動,直接復用android自帶ant腳本中的任務。
  2. 最糾結的過程是如何拆分release流程,插入渠道替換邏輯。這個過程遇到的問題最多。其實最后總結下來,拆分ant任務最簡單的方式,在於看這個任務的子任務是否有共同的上下文依賴(比如運行時的環境變量依賴,等等),拆分到兩個任務中的子任務之間最好不要有這種依賴,否則運行起來會出現變量值錯誤的問題,當然如果搞清楚整個流程也可以修改代碼,但是工作量比較大。
  3. 對於apk壓縮包的操作請使用android自帶的aapt,避免直接使用zip,直接使用zip會將apk里面的raw資源壓縮,導致有些rom下讀取raw文件失敗。

其實生成未簽名包之后無需解壓替換,直接aapt操作壓縮包替換就好了,這樣可以避免使用zip。

編寫shell時當前路徑要控制好,否則會很麻煩錯誤不斷。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM