Android進階:十四、熟悉Android打包編譯的流程

Android丶SE開發 發表於 2019-05-11
Android

Android進階系列性文章最後一篇,之後我會更新其他系列性文章,歡迎關注

從事Android高階研發,怎能不知道Android的打包流程呢?
今天就為大家講解Android打包的流程:

Android 構建系統編譯應用資源和原始碼,然後將它們打包成可測試、部署、簽署和分發的 APK。
一般使用 Android Studio開發的時候使用Gradle構建工具包來自動執行和管理構建流程,同時也可以靈活地自定義構建配置。
Gradle 和 Android 外掛獨立於 Android Studio 執行。所以我們可以在 Android Studio上或者計算機上的命令列構建 Android 應用。 如果您不使用 Android Studio,可以學習如何從命令列構建和執行您的應用,最終構建的輸出都相同。

在瞭解Android打包流程之前,我建議您可以先檢視一個apk包內容,可以知道它裡面都有哪些檔案組成:

  • AndroidManifest.xml 程式全域性配置檔案
  • classes.dex Dalvik位元組碼
  • resources.arsc 資源索引表, 解壓縮resources.ap_就能看到
  • res\ 該目錄存放資原始檔(圖片,文字,xml佈局)
  • assets\ 該目錄可以存放一些配置檔案
  • src\ java原始碼檔案
  • libs\ 存放應用程式所依賴的庫
  • gen\ 編譯器根據資原始檔生成的java檔案
  • bin\ 由編譯器生成的apk檔案和各種依賴的資源
  • META-INF\ 該目錄下存放的是簽名資訊

知道了apk包體的內容,我們應該會更好的理解Android打包流程:
Android進階:十四、熟悉Android打包編譯的流程

以上流程中我們可以看到:

  • 編譯器將原始碼轉換成 DEX(Dalvik Executable) 檔案(其中包括 Android 裝置上執行的位元組碼),將所有其他內容轉換成已編譯資源。
  • APK 打包器將 DEX 檔案和已編譯資源合併成單個 APK。 不過,必須先簽署 APK,才能將應用安裝並部署到 Android 裝置上
  • APK 打包器使用除錯或釋出金鑰庫簽署APK。

注意:
1、如果我們構建的是debug版本的應用,打包器會使用除錯金鑰庫簽署應用。 Android Studio 自動使用除錯金鑰庫配置新專案。
2、如果構建的是打算向外釋出的釋出版本應用,打包器會使用釋出金鑰庫簽署應用。
3、在生成最終 APK 之前,打包器會使用 zipalign 工具對應用進行優化,減少其在裝置上執行時佔用的記憶體。

重點:
如上面的流程所示,是典型 Android 應用模組的構建流程,但如果看的更細緻一點它的流程應該如下:

  • AAPT(Android Asset Packaging Tool)工具,Android資源打包工具。會打包資原始檔(res資料夾下的檔案),並生成R.java和resources.arsc檔案。
  • AIDL工具會將所有的.aidl檔案編譯成.java檔案。
  • JAVAC工具將R.java、AIDL介面生成的java檔案、應用程式碼java檔案編譯成.class檔案。
  • dex指令碼將很多.class檔案轉換打包成一個.dex檔案。
  • apkbuilder指令碼將資原始檔和.dex檔案生成未簽名的.apk檔案。
  • jarsigner對apk進行簽名。

這些構建中使用的工具或者指令碼,在SDK的build-tools或者tools下可以找到
詳細的流程圖如下:

Android進階:十四、熟悉Android打包編譯的流程

這樣就Android打包的流程就明明白白了。

gradle的配置含義
Androidstudio 會與Android Plugin for Gradle 這個構建工具包協作,當我們在Androidstudio建立一個應用的時候,它會幫助我們建立自定義構建配置 build.gradle 檔案,這個檔案裡的內容需要我們自己進行一些簡單的更改。 這些純文字檔案使用域特定語言 (DSL) 以 Groovy 語言描述和操作構建邏輯,其中 Groovy 是一種適用於 Java 虛擬機器 (JVM) 的動態語言。 無需瞭解 Groovy 便可開始配置構建,因為 Android Plugin for Gradle 引入我們開發需要的大多數 DSL 元素

Android進階:十四、熟悉Android打包編譯的流程

如圖,是我們工程中檔案層級,現在我們來講講每個層級gradle的檔案含義:

  • settings.gradle 工程設定Gradle,檔案位於專案根目錄,用於指示 Gradle 在構建應用時應將哪些模組包括在內。 對大多數專案而言,該檔案很簡單,只包括以下內容:
    include ‘:app’
    不過,多模組專案需要指定應包括在最終構建之中的每個模組
  • project build.gradle 是頂級構建檔案, 位於專案根目錄,用於定義適用於專案中所有模組的構建配置。 預設情況下,此頂級構建檔案使用 buildscript 程式碼塊來定義專案中所有模組共用的 Gradle 儲存區和依賴項。 以下程式碼示例描述的預設設定和 DSL 元素可在新建專案後的頂級 build.gradle 檔案中找到。
buildscript {

 buildscript塊是Gradle本身配置儲存庫和依賴項的地方——也就是說,這裡不應該包含模組的依賴項。例如,這個塊包含了Gradle的Android外掛作為一個依賴項,因為它提供了Gradle構建Android應用程式模組所需的額外指令。
    repositories {
        google()
        jcenter()
    }

dependencies 塊配置Gradle需要使用的依賴項來構建專案。下面的程式碼行新增了Gradle的Android外掛版本3.3.2作為類路徑依賴項。

    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.2'
    }
}

allprojects塊是配置專案中所有模組(如第三方外掛或庫)使用的儲存庫和依賴項的地方。但是,你應該在每個模組級別的構建中配置特定於模組的依賴項。gradle檔案。對於新專案,Android Studio預設包含JCenter和谷歌的Maven儲存庫,但它不配置任何依賴項(除非您選擇了一個需要的模板)

allprojects {
   repositories {
       google()
       jcenter()
   }
}
複製程式碼

對於包含多個模組的 Android 專案,在專案級別定義某些屬性,並在所有模組間共享這些屬性可能會非常有用。 為此,您可以將 額外屬性新增到頂級 build.gradle 檔案的 ext 程式碼塊中。

buildscript {...}

allprojects {...}

// 這個塊封裝了自定義屬性,使它們對專案中的所有模組都可用。
ext {
    //下面只是可以定義的屬性型別的幾個示例。
    compileSdkVersion = 28
    // You can also create properties to specify versions for dependencies.
    // Having consistent versions between modules can avoid conflicts with behavior.
    supportLibVersion = "28.0.0"
    ...
}
...
複製程式碼

要從相同專案中的模組訪問這些屬性,請在模組的 build.gradle 檔案(您可以在以下部分了解有關此檔案的詳細資訊)中使用以下語法。

android {
  // 使用以下語法訪問在專案級別定義的屬性:
  // rootProject.ext.property_name
  compileSdkVersion rootProject.ext.compileSdkVersion
  ...
}
...
dependencies {
    implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
    ...
}
複製程式碼
  • module build.gradle是模組級構建檔案
    模組級 build.gradle 檔案位於各 project/module/ 目錄中,用於配置適用於其所在模組的構建設定。 你可以通過配置這些構建設定來提供自定義打包選項(例如附加構建型別和產品風格),以及替換 main/ 應用清單或頂級 build.gradle 檔案中的設定。

此 Android 應用模組 build.gradle 檔案示例概括您應瞭解的某些基本 DSL 元素和設定。

//構建配置中的第一行將Gradle的Android外掛應用於此構建,並使Android塊可用來指定特定於Android的構建選項。

apply plugin: 'com.android.application'

android塊是配置所有android特定構建選項的地方。
android {

compileSdkVersion指定了Gradle應該使用的Android API級別來編譯你的應用程式。這意味著你的應用程式可以使用這個API級別或更低的API特性。

 compileSdkVersion 28

buildToolsVersion指定了用於構建應用程式的SDK構建工具、命令列實用程式和編譯器的版本。需要使用SDK管理器下載構建工具。此屬性是可選的,因為外掛預設使用構建工具的推薦版本。

  buildToolsVersion "28.0.3"

defaultConfig塊封裝了所有構建變體的預設設定和條目,並且可以從構建系統動態地覆蓋main/AndroidManifest.xml中的一些屬性。你可以配置產品口味來覆蓋應用程式不同版本的這些值。

  defaultConfig {

applicationId惟一地標識要釋出的包。但是,我們的原始碼仍然應該引用主/AndroidManifest.xml檔案中的package屬性定義的包名。
    applicationId 'com.example.myapp'

  定義執行應用程式所需的最低API級別。
    minSdkVersion 15

指定用於測試應用程式的API級別。
    targetSdkVersion 28

定義應用程式的版本號。
    versionCode 1

為您的應用程式定義一個使用者友好的版本名稱。
    versionName "1.0"
  }

您可以在buildTypes塊中配置多個構建型別。根據efault,構建系統定義了兩種構建型別:debug和release。除錯構建型別在預設的構建配置中沒有顯式顯示,但是它包含除錯工具,並使用debug鍵進行簽名。release構建型別應用Proguard設定,預設情況下不簽名。

  buildTypes {

預設情況下,Android Studio使用minifyEnabled配置release build型別來啟用程式碼收縮,並指定Proguard設定檔案。

    release {
        minifyEnabled true // Enables code shrinking for the release build type.
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }

可以在productflavor塊中配置多個產品口味。這允許您建立應用程式的不同版本,這些版本可以用自己的設定覆蓋defaultConfig塊。產品風味是可選的,預設情況下構建系統不會建立它們。這個例子建立了一個免費且付費的產品風格。然後,每種產品都指定了自己的應用程式ID,這樣它們就可以同時存在於谷歌Play Store或Android裝置上。如果您宣告產品的風味,您還必須宣告風味維度,並將每種風味分配給風味維度。

  flavorDimensions "tier"
  productFlavors {
    free {
      dimension "tier"
      applicationId 'com.example.myapp.free'
    }

    paid {
      dimension "tier"
      applicationId 'com.example.myapp.paid'
    }
  }


在split塊中,您可以配置不同的APK構建,每個構建只包含支援螢幕密度或的程式碼和資源versionCode不同。

  splits {
   根據螢幕密度設定構建多個apk。
    density {

   啟用或禁用構建多個apk
      exclude "ldpi", "tvdpi", "xxxhdpi", "400dpi", "560dpi"
    }
  }
}

模組級構建配置檔案中的dependencies塊指定僅構建模組本身所需的依賴項。要了解更多資訊,請新增構建依賴項。

dependencies {
    implementation project(":lib")
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation fileTree(dir: 'libs', include: ['*.jar'])
}
複製程式碼
  • Gradle 屬性檔案,Gradle 還包括兩個屬性檔案,均位於專案根目錄中,可用於指定適用於 Gradle 構建工具包本身的設定:

gradle.properties

您可以在其中配置專案範圍 Gradle 設定,例如 Gradle 後臺程式的最大堆大小。如需瞭解詳細資訊,請參閱構建環境。
local.properties
為構建系統配置本地環境屬性,例如 SDK 安裝路徑。 由於該檔案的內容由 Android Studio 自動生成並且專用於本地開發者環境,所以不應手動修改該檔案,或將其納入您的版本控制系統。

以上便是Android打包流程中需要了解的知識。這些知識對我們理解一些比較深入的功能還是很有好處的,比如熱更新,比如外掛化,比如多渠道打包,同時在平時的開發過程中對打包編譯的配置檔案gradle很熟悉,可以大大提高開發的效率,甚至可以自己開發一些小的指令碼幫助自己提高工作效率。