第二個 Android 11 開發者預覽版現已推出,快來測試并分享您的反饋吧

配置您的版本

Android 構建系統會編譯應用資源和源代碼,然后將它們打包到 APK 中,供您測試、部署、簽名和分發。Android Studio 會使用高級構建工具包 Gradle 來自動執行和管理構建流程,同時也允許您定義靈活的自定義版本配置。每個版本配置均可定義自己的一組代碼和資源,同時重復利用應用各個版本的共用部分。Android Plugin for Gradle 可與該構建工具包搭配使用,來提供專用于構建和測試 Android 應用的流程和可配置設置。

Gradle 和 Android 插件獨立于 Android Studio 運行。這意味著,您可以在 Android Studio 內、計算機上的命令行或未安裝 Android Studio 的計算機(如持續集成服務器)上構建 Android 應用。如果您不使用 Android Studio,可以學習如何通過命令行構建和運行應用。無論您是通過命令行、在遠程計算機上還是使用 Android Studio 構建項目,構建的輸出都是一樣的。

注意:由于 Gradle 和 Android 插件獨立于 Android Studio 運行,因此您需要單獨更新這些構建工具。請閱讀版本說明,了解如何更新 Gradle 和 Android 插件

Android 構建系統非常靈活,可讓您在不修改應用核心源文件的情況下進行自定義版本配置。本部分將介紹 Android 構建系統的工作原理,以及它如何幫助您對多個版本配置進行自定義和自動化處理。如果您只想詳細了解如何部署應用,請參閱在 Android Studio 中構建和運行應用。要立即開始使用 Android Studio 來創建自定義版本配置,請參閱配置版本變體

構建流程

構建流程涉及許多將項目轉換成 Android 應用軟件包 (APK) 的工具和流程。構建流程非常靈活,因此了解它的一些底層工作原理會很有幫助。

圖 1. 典型 Android 應用模塊的構建流程。

如圖 1 所示,典型 Android 應用模塊的構建流程通常按照以下步驟執行:

  1. 編譯器將您的源代碼轉換成 DEX 文件(Dalvik 可執行文件,其中包括在 Android 設備上運行的字節碼),并將其他所有內容轉換成編譯后的資源。
  2. APK 打包器將 DEX 文件和編譯后的資源合并到一個 APK 中。不過,在將應用安裝并部署到 Android 設備之前,必須先為 APK 簽名。
  3. APK 打包器使用調試或發布密鑰庫為 APK 簽名:
    1. 如果您構建的是調試版應用(即專用于測試和分析的應用),則打包器會使用調試密鑰庫為應用簽名。Android Studio 會自動使用調試密鑰庫配置新項目。
    2. 如果您構建的是打算對外發布的發布版應用,則打包器會使用發布密鑰庫為應用簽名。要創建發布密鑰庫,請參閱在 Android Studio 中為應用簽名
  4. 在生成最終 APK 之前,打包器會使用 zipalign 工具對應用進行優化,以減少其在設備上運行時所占用的內存。

構建流程結束時,您將獲得應用的調試版 APK 或發布版 APK,以用于部署、測試或發布給外部用戶。

自定義版本配置

Gradle 和 Android 插件可幫助您完成以下方面的版本配置:

版本類型
版本類型定義 Gradle 在構建和打包應用時使用的某些屬性,通常針對開發流程的不同階段進行配置。例如,調試版本類型支持調試選項,并使用調試密鑰為 APK 簽名;而發布版本類型則會縮減 APK、對 APK 進行混淆處理,并使用發布密鑰為 APK 簽名以進行分發。要構建應用,您必須至少定義一個版本類型。Android Studio 默認會創建調試和發布兩個版本類型。要開始為應用自定義打包設置,請了解如何配置版本類型
產品變種
產品變種代表您會向用戶發布的應用的不同版本,如應用的免費版和付費版。您可以自定義產品變種來使用不同的代碼和資源,同時共享和重復利用各版應用的共用部分。產品變種是可選的,您必須手動創建。要開始創建應用的不同版本,請了解如何配置產品變種
版本變體
版本變體是版本類型與產品變種的交叉產物,也是 Gradle 用來構建應用的配置。利用版本變體,您可以在開發期間構建產品變種的調試版本,或者構建產品變種的已簽名發布版本以供分發。雖然您無法直接配置版本變體,但可以配置組成它們的版本類型和產品變種。創建額外的版本類型或產品變種也會創建額外的版本變體。要了解如何創建和管理版本變體,請參閱配置版本變體概覽。
清單條目
您可以在版本變體配置中為清單文件的某些屬性指定值。這些版本值會替換清單文件中的現有值。如果您要為模塊生成多個 APK,讓每一個 APK 文件都具有不同的應用名稱、最低 SDK 版本或目標 SDK 版本,便可運用這一技巧。當存在多個清單時,Gradle 會合并清單設置
依賴項
構建系統會管理來自本地文件系統以及來自遠程代碼庫的項目依賴項。這樣一來,您就不必手動搜索、下載依賴項的二進制文件包以及將它們復制到項目目錄中。要了解詳情,請參閱添加構建依賴項
簽名
構建系統允許您在版本配置過程中指定簽名設置,并且可以在構建過程中自動為 APK 簽名。構建系統通過已知憑據使用默認密鑰和證書為調試版本簽名,以避免在構建時提示輸入密碼。除非您為發布版本明確定義簽名配置,否則,構建系統將不會為此版本簽名。如果您沒有發布密鑰,可以按為應用簽名中所述生成一個。
代碼和資源縮減
構建系統允許您為每個版本變體指定不同的 ProGuard 規則文件。在構建應用時,構建系統會應用一組適當的規則來使用其內置的縮減工具(如 R8)縮減您的代碼和資源
多 APK 支持
構建系統支持您自動構建不同的 APK,并使每個 APK 只包含特定屏幕密度或應用二進制接口 (ABI) 所需的代碼和資源。 如需了解詳情,請參閱構建多個 APK

版本配置文件

創建自定義版本配置需要您對一個或多個版本配置文件(即 build.gradle 文件)做出更改。這些純文本文件使用領域特定語言 (DSL) 以 Groovy 來描述和操縱版本邏輯,其中 Groovy 是一種適用于 Java 虛擬機 (JVM) 的動態語言。您無需了解 Groovy 便可開始配置版本,因為 Android Plugin for Gradle 引入了您需要的大多數 DSL 元素。如需詳細了解 Android 插件 DSL,請參閱 DSL 參考文檔

如圖 2 所示,開始新項目時,Android Studio 會自動為您創建其中的部分文件,并為其填充合理的默認值。

圖 2. Android 應用模塊的默認項目結構。

有一些 Gradle 版本配置文件是 Android 應用的標準項目結構的組成部分。您必須了解其中每個文件的范圍和用途及其應定義的基礎 DSL 元素,才能著手配置版本。

Gradle 設置文件

settings.gradle 文件位于項目的根目錄下,用于指示 Gradle 在構建應用時應將哪些模塊包含在內。對大多數項目而言,該文件很簡單,只包含以下內容:

    include ‘:app’
    

不過,多模塊項目需要指定應包含在最終版本中的每個模塊。

頂層版本文件

頂層 build.gradle 文件位于項目的根目錄下,用于定義適用于項目中所有模塊的版本配置。默認情況下,頂層版本文件使用 buildscript 代碼塊來定義項目中所有模塊共用的 Gradle 代碼庫和依賴項。以下代碼示例說明了創建新項目后可在頂層 build.gradle 文件中找到的默認設置和 DSL 元素。

    /**
     * The buildscript block is where you configure the repositories and
     * dependencies for Gradle itself—meaning, you should not include dependencies
     * for your modules here. For example, this block includes the Android plugin for
     * Gradle as a dependency because it provides the additional instructions Gradle
     * needs to build Android app modules.
     */

    buildscript {

        /**
         * The repositories block configures the repositories Gradle uses to
         * search or download the dependencies. Gradle pre-configures support for remote
         * repositories such as JCenter, Maven Central, and Ivy. You can also use local
         * repositories or define your own remote repositories. The code below defines
         * JCenter as the repository Gradle should use to look for its dependencies.
         *
         * New projects created using Android Studio 3.0 and higher also include
         * Google's Maven repository.
         */

        repositories {
            google()
            jcenter()
        }

        /**
         * The dependencies block configures the dependencies Gradle needs to use
         * to build your project. The following line adds Android plugin for Gradle
         * version 3.5.2 as a classpath dependency.
         */

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

    /**
     * The allprojects block is where you configure the repositories and
     * dependencies used by all modules in your project, such as third-party plugins
     * or libraries. However, you should configure module-specific dependencies in
     * each module-level build.gradle file. For new projects, Android Studio
     * includes JCenter and Google's Maven repository by default, but it does not
     * configure any dependencies (unless you select a template that requires some).
     */

    allprojects {
       repositories {
           google()
           jcenter()
       }
    }
    

配置項目全局屬性

對于包含多個模塊的 Android 項目,可能有必要在項目層級定義某些屬性并在所有模塊之間共享這些屬性。為此,您可以將額外的屬性添加到頂層 build.gradle 文件內的 ext 代碼塊中。

    buildscript {...}

    allprojects {...}

    // This block encapsulates custom properties and makes them available to all
    // modules in the project.
    ext {
        // The following are only a few examples of the types of properties you can define.
        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 {
      // Use the following syntax to access properties you defined at the project level:
      // rootProject.ext.property_name
      compileSdkVersion rootProject.ext.compileSdkVersion
      ...
    }
    ...
    dependencies {
        implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
        ...
    }
    

注意:雖然 Gradle 可讓您在模塊級別定義項目全局屬性,但您應避免這樣做,因為這樣會導致共享這些屬性的模塊進行耦合。模塊耦合使得以后將模塊作為獨立項目導出更加困難,并實際妨礙 Gradle 利用并行項目執行來加快多模塊構建。

模塊級版本文件

模塊級 build.gradle 文件位于每個 project/module/ 目錄下,用于為其所在的特定模塊配置版本設置。您可以通過配置這些版本設置來提供自定義打包選項(如額外的版本類型和產品變種),以及替換 main/ 應用清單或頂層 build.gradle 文件中的設置。

以下 Android 應用模塊 build.gradle 文件示例簡要說明了您應該了解的一些基礎 DSL 元素和設置。

    /**
     * The first line in the build configuration applies the Android plugin for
     * Gradle to this build and makes the android block available to specify
     * Android-specific build options.
     */

    apply plugin: 'com.android.application'

    /**
     * The android block is where you configure all your Android-specific
     * build options.
     */

    android {

      /**
       * compileSdkVersion specifies the Android API level Gradle should use to
       * compile your app. This means your app can use the API features included in
       * this API level and lower.
       */

      compileSdkVersion 28

      /**
       * buildToolsVersion specifies the version of the SDK build tools, command-line
       * utilities, and compiler that Gradle should use to build your app. You need to
       * download the build tools using the SDK Manager.
       *
       * This property is optional because the plugin uses a recommended version of
       * the build tools by default.
       */

      buildToolsVersion "29.0.0"

      /**
       * The defaultConfig block encapsulates default settings and entries for all
       * build variants, and can override some attributes in main/AndroidManifest.xml
       * dynamically from the build system. You can configure product flavors to override
       * these values for different versions of your app.
       */

      defaultConfig {

        /**
         * applicationId uniquely identifies the package for publishing.
         * However, your source code should still reference the package name
         * defined by the package attribute in the main/AndroidManifest.xml file.
         */

        applicationId 'com.example.myapp'

        // Defines the minimum API level required to run the app.
        minSdkVersion 15

        // Specifies the API level used to test the app.
        targetSdkVersion 28

        // Defines the version number of your app.
        versionCode 1

        // Defines a user-friendly version name for your app.
        versionName "1.0"
      }

      /**
       * The buildTypes block is where you can configure multiple build types.
       * By default, the build system defines two build types: debug and release. The
       * debug build type is not explicitly shown in the default build configuration,
       * but it includes debugging tools and is signed with the debug key. The release
       * build type applies Proguard settings and is not signed by default.
       */

      buildTypes {

        /**
         * By default, Android Studio configures the release build type to enable code
         * shrinking, using minifyEnabled, and specifies the default Proguard rules file.
         */

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

      /**
       * The productFlavors block is where you can configure multiple product flavors.
       * This allows you to create different versions of your app that can
       * override the defaultConfig block with their own settings. Product flavors
       * are optional, and the build system does not create them by default.
       *
       * This example creates a free and paid product flavor. Each product flavor
       * then specifies its own application ID, so that they can exist on the Google
       * Play Store, or an Android device, simultaneously.
       *
       * If you declare product flavors, you must also declare flavor dimensions
       * and assign each flavor to a flavor dimension.
       */

      Add build 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
配置構建系統的本地環境屬性,其中包括:
  • ndk.dir - NDK 的路徑。此屬性已被棄用。NDK 的所有下載版本都將安裝在 Android SDK 目錄下的 ndk 目錄中。
  • sdk.dir - SDK 的路徑。
  • cmake.dir - CMake 的路徑。
  • ndk.symlinkdir - 在 Android Studio 3.5 及更高版本中,創建指向 NDK 的符號鏈接,該鏈接可比 NDK 安裝路徑短。

將 NDK 重新映射到較短的路徑(僅限 Windows)

Windows 長路徑最常見的問題就是 NDK 安裝文件夾中的工具(如 ld.exe)會產生非常深的路徑,但工具對于長路徑的支持并不佳。

local.properties 中,您可以設置 ndk.symlinkdir 屬性來請求 Gradle 插件創建指向 NDK 的符號鏈接。該符號鏈接的路徑可比現有 NDK 文件夾的路徑短。例如,ndk.symlinkdir = C:\ 將生成以下符號鏈接:C:\ndk\19.0.5232133

將項目與 Gradle 文件同步

當您在項目中對版本配置文件進行更改時,Android Studio 會要求您同步項目文件,以便它導入版本配置更改并執行一些檢查來確保您的配置不會造成構建錯誤。

要同步項目文件,請點擊做出更改后顯示的通知欄中的 Sync Now(如圖 3 所示),或者點擊菜單欄中的 Sync Project 圖標 。如果 Android Studio 發現您的配置有任何錯誤(例如,您的源代碼使用了只有在 compileSdkVersion 以上的 API 級別中才會提供的 API 功能),就會顯示 Messages 窗口來說明該問題。

圖 3. 在 Android Studio 中將項目與版本配置文件同步。

源集

Android Studio 按邏輯關系將每個模塊的源代碼和資源分組為源集。模塊的 main/ 源集包含其所有版本變體共用的代碼和資源。其他源集目錄是可選的,在您配置新的版本變體時,Android Studio 不會自動為您創建這些目錄。不過,創建類似于 main/ 的源集有助于更好地組織管理 Gradle 僅在構建特定應用版本時才應使用的文件和資源:

src/main/
此源集包含所有版本變體共用的代碼和資源。
src/buildType/
創建此源集以納入特定版本類型專用的代碼和資源。
src/productFlavor/
創建此源集以納入特定產品變種專用的代碼和資源。

注意:如果將版本配置為組合多個產品變種,則可以為變種維度之間的每個產品變種組合創建源集目錄:src/productFlavor1ProductFlavor2/

src/productFlavorBuildType/
創建此源集以納入特定版本變體專用的代碼和資源。

例如,要生成應用的“fullDebug”版本,構建系統需要合并來自以下源集的代碼、設置和資源:

  • src/fullDebug/(版本變體源集)
  • src/debug/(版本類型源集)
  • src/full/(產品變種源集)
  • src/main/(主源集)

注意:當您在 Android Studio 中使用 File > New 菜單選項新建文件或目錄時,可以針對特定源集進行創建。可供您選擇的源集取決于您的版本配置,如果所需的目錄尚不存在,Android Studio 會自動創建。

如果不同源集包含同一文件的不同版本,Gradle 將按以下優先順序決定使用哪一個文件(左側源集替換右側源集的文件和設置):

版本變體 > 版本類型 > 產品變種 > 主源集 > 庫依賴項

這樣一來,Gradle 便可使用專用于您試圖構建的版本變體的文件,同時重復利用與應用的其他版本共用的 Activity、應用邏輯和資源。在合并多個清單時,Gradle 會使用相同的優先級順序,這樣每個版本變體都能在最終清單中定義不同的組件或權限。要詳細了解如何創建自定義源集,請參閱創建版本變體的源集