Android Studio分模塊自動化構建實戰

mxw8 9年前發布 | 46K 次閱讀 Android Studio開發工具 Android Studio

@author ASCE1885的 Github 簡書 微博 CSDN

最近在使用Android Studio+Gradle做一個基礎框架SDK項目,該框架主要實現每個app都需要的基礎能力,例如網絡請求,圖片緩存,json解析,日志記錄等等。

眾所周知,AndroidStudio中應該盡量使用Module來進行模塊的劃分,既能達到模塊解耦的目的,也能在必要的時候輕松實現分模塊打包,特別是在SDK項目中。那么什么是分模塊打包呢?就是我們可以根據第三方使用者的需求,自動化的提供SDK的全量版本,部分功能版本以及最小功能版本等等。

我們的項目結構如下所示,每個功能獨立成一個Module:


由于我們的模塊都是純代碼的,沒有包含資源文件,因此不是以aar包的形式而是使用jar包形式對外提供。順便提一句,生成的aar包默認路徑是:

build/output/aar/

而jar包可以到如下路徑尋找:

build/intermediates/bundles/debug/classes.jar
build/intermediates/bundles/release/classes.jar

Jar包的合并

從項目工程截圖中可以看到,我們的project包含多個module,每個基礎功能的module最終編譯生成的都是一個 classes.jar。因此project最終會生成一堆的jar包,而到了對外發布時,我們要提供一個單獨的jar包出去,因此,就需要對jar包進行合并。很不幸,Android Studio沒有提供這樣的功能,因此只能靠自己寫腳本調用jar命令來實現了,打開命令行terminal,輸入jar,就可以打印出jar的用法,如下所示:

guhaoxindeMacBook-Pro:~ guhaoxin$ jar
用法: jar {ctxui}[vfm0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...
選項包括: 
    -c  創建新的歸檔文件
    -t  列出歸檔目錄
    -x  從檔案中提取指定的 (或所有) 文件
    -u  更新現有的歸檔文件
    -v  在標準輸出中生成詳細輸出
    -f  指定歸檔文件名
    -m  包含指定清單文件中的清單信息
    -e  為捆綁到可執行 jar 文件的獨立應用程序
        指定應用程序入口點
    -0  僅存儲; 不使用情況任何 ZIP 壓縮
    -M  不創建條目的清單文件
    -i  為指定的 jar 文件生成索引信息
    -C  更改為指定的目錄并包含其中的文件
如果有任何目錄文件, 則對其進行遞歸處理。
清單文件名, 歸檔文件名和入口點名稱的指定順序
與 'm', 'f' 和 'e' 標記的指定順序相同。

示例 1: 將兩個類文件歸檔到一個名為 classes.jar 的歸檔文件中: jar cvf classes.jar Foo.class Bar.class 示例 2: 使用現有的清單文件 'mymanifest' 并 將 foo/ 目錄中的所有文件歸檔到 'classes.jar' 中: jar cvfm classes.jar mymanifest -C foo/ .</pre>

使用jar命令,主要實現兩個功能:

  • 將所有jar包的class文件解壓到某個目錄中
  • 將解壓后所有class文件的重新壓縮為一個單獨的jar包
  • </ul>

    由于jar命令不能指定最終輸出的目錄,因此我們需要首先cd到用于存放解壓后class文件的一個臨時目錄,然后依次對所有jar包進行解壓操作,解壓命令如下所示:

    jar -xvf ../../hfasynchttp/build/intermediates/bundles/debug/classes.jar

    當所有的jar包都解壓完畢后,接著執行壓縮命令,這樣就得到一個單獨的jar包了:

    jar -cvfM AndroidHyperion_${version}_debug.jar .

    分模塊自動化構建

    自動化構建包括本地構建和Jenkins構建兩部分,本地構建主要用于開發自己調試使用,Jenkins構建主要用于測試,產品等取包以及跑Monkey使用。

    本地構建

    本地構建腳本文件位于工程根目錄下的build_local.sh,該腳本的主要功能有:

    • 調用gradlew命令執行gradle編譯,生成各個Module的jar包
    • 解壓各個Module生成的jar包,并把解壓后的class文件重新打包成單獨的一個jar包
    • 分模塊打包功能通過定義Boolean變量值進行控制
    • 輸出目錄是output
    • </ul>

      build_local.sh文件內容如下:

      #!/bin/sh

      使用Gradle編譯各個module

      ./gradlew clean ./gradlew build --stacktrace --debug

      進入輸出目錄

      cd output

      清空輸出目錄

      rm -rf *

      創建輸出子目錄

      mkdir temp mkdir debug mkdir release

      定義sdk版本號

      version="1.0.0"

      定義模塊是否打包標識

      is_include_hfasynchttp=true is_include_bitmapfun=true is_include_hfjson=true is_include_hflogger=true

      省略其他...

      解壓所有debug版本的jar包到temp目錄中

      cd temp

      if $is_include_hfasynchttp; then jar -xvf ../../hfasynchttp/build/intermediates/bundles/debug/classes.jar fi

      if $is_include_bitmapfun; then jar -xvf ../../hfbitmapfun/build/intermediates/bundles/debug/classes.jar fi

      if $is_include_hfjson; then jar -xvf ../../hfjson/build/intermediates/bundles/debug/classes.jar fi

      if $is_include_hflogger; then jar -xvf ../../hflogger/build/intermediates/bundles/debug/classes.jar fi

      壓縮所有debug版本的class文件到一個獨立的jar包中

      jar -cvfM AndroidHyperion_${version}_debug.jar .

      拷貝文件

      mv AndroidHyperion_${version}_debug.jar ../debug

      清空temp目錄

      rm -rf *

      解壓所有release版本的jar包到temp目錄中

      if $is_include_hfasynchttp; then jar -xvf ../../hfasynchttp/build/intermediates/bundles/release/classes.jar fi

      if $is_include_bitmapfun; then jar -xvf ../../hfbitmapfun/build/intermediates/bundles/release/classes.jar fi

      if $is_include_hfjson; then jar -xvf ../../hfjson/build/intermediates/bundles/release/classes.jar fi

      if $is_include_hflogger; then jar -xvf ../../hflogger/build/intermediates/bundles/release/classes.jar fi

      壓縮所有release版本的class文件到一個jar包中

      jar -cvfM AndroidHyperion_${version}_release.jar .

      拷貝文件

      mv AndroidHyperion_${version}_release.jar ../release

      刪除temp目錄

      cd .. rm -rf temp</pre>

      Jenkins構建

      Jenkins編譯腳本文件位于工程根目錄下的build_jenkins.sh,該腳本的主要功能有:

      • 調用gradlew命令執行gradle編譯,生成各個Moudle的jar包
      • 解壓各個Module生成的jar包,并把解壓后的class文件重新打包成單獨的一個jar包
      • 分模塊打包功能通過Jenkins上面配置的參數化構建參數進行控制
      • 輸出目錄是output
      • </ul>

        可以看到,和本地構建唯一的區別就是分模塊的參數化構建參數是定義在Jenkins上的,而不是定義在本地腳本中的,為了完整清晰起見,我們還是把完整的腳本文件貼出來:

        #!/bin/sh

        ./gradlew clean ./gradlew build --stacktrace --debug

        進入輸出目錄

        cd output

        清空輸出目錄

        rm -rf *

        創建輸出子目錄

        mkdir temp mkdir debug mkdir release

        cd temp

        解壓所有debug版本的jar包

        if $is_include_hfasynchttp; then jar -xvf ../../hfasynchttp/build/intermediates/bundles/debug/classes.jar fi

        if $is_include_bitmapfun; then jar -xvf ../../hfbitmapfun/build/intermediates/bundles/debug/classes.jar fi

        if $is_include_hfjson; then jar -xvf ../../hfjson/build/intermediates/bundles/debug/classes.jar fi

        if $is_include_hflogger; then jar -xvf ../../hflogger/build/intermediates/bundles/debug/classes.jar fi

        壓縮所有debug版本的class文件到一個jar包中

        jar -cvfM AndroidHyperion_${version}_debug.jar .

        移動生成的jar包到debug目錄

        mv AndroidHyperion_${version}_debug.jar ../debug

        清空temp目錄

        rm -rf *

        解壓所有release版本的jar包

        if $is_include_hfasynchttp; then jar -xvf ../../hfasynchttp/build/intermediates/bundles/release/classes.jar fi

        if $is_include_bitmapfun; then jar -xvf ../../hfbitmapfun/build/intermediates/bundles/release/classes.jar fi

        if $is_include_hfjson; then jar -xvf ../../hfjson/build/intermediates/bundles/release/classes.jar fi

        if $is_include_hflogger; then jar -xvf ../../hflogger/build/intermediates/bundles/release/classes.jar fi

        壓縮所有release版本的class文件到一個jar包中

        jar -cvfM AndroidHyperion_${version}_release.jar .

        移動生成的jar包到release目錄

        mv AndroidHyperion_${version}_release.jar ../release

        刪除temp目錄

        cd .. rm -rf temp</pre>

        local和Jenkins參數化構建參數定義

        類型 名稱 默認值 描述
        String version 1.0.0 Hyperion sdk版本號
        Boolean is_include_hfasynchttp true 是否打包hfasynchttp
        Boolean is_include_bitmapfun true 是否打包hfbitmapfun
        Boolean is_include_hfjson true 是否打包hfjson
        Boolean is_include_hflogger true 是否打包hflogger
 本文由用戶 mxw8 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!