可能大家開發(fā)安卓已經(jīng)很久了,但對Android gradle的使用完全了解了嗎,本篇基于官方文檔整理,希望能幫助你系統(tǒng)的了解Android gradle的原理及使用;
配置構建
Android構建系統(tǒng)會編譯應用資源和源代碼,然后將它們打包到 APK 中,供您測試、部署、簽名和分發(fā)。Android Studio 會使用高級構建工具包 Gradle 來自動執(zhí)行和管理構建流程,同時也允許您定義靈活的自定義構建配置。每個構建配置均可自行定義一組代碼和資源,同時重復利用所有應用版本共用的部分。Android Plugin for Gradle 與該構建工具包搭配使用,提供專用于構建和測試 Android 應用的流程和可配置設置。
Gradle 和 Android 插件獨立于 Android Studio 運行。這意味著,您可以在 Android Studio 內(nèi)、計算機上的命令行或未安裝 Android Studio 的計算機(如持續(xù)集成服務器)上構建 Android 應用。如果您不使用 Android Studio,可以學習如何通過命令行構建和運行應用。無論您是從命令行、在遠程計算機上還是使用 Android Studio 構建項目,構建的輸出都相同。
注意:由于 Gradle 和 Android 插件獨立于 Android Studio 運行,因此您需要單獨更新構建工具。請閱讀版本說明,了解如何更新 Gradle 和 Android 插件。
Android 構建系統(tǒng)非常靈活,讓您能夠在不修改應用核心源文件的情況下執(zhí)行自定義構建配置。本部分將介紹 Android 構建系統(tǒng)的工作原理,以及它如何幫助您對多個構建配置進行自定義和自動化處理。如果您只想詳細了解如何部署應用,請參閱在 Android Studio 中構建和運行應用。如需立即開始使用 Android Studio 來創(chuàng)建自定義構建配置,請參閱配置構建變體。
構建流程
構建流程涉及許多將項目轉(zhuǎn)換成 Android 應用軟件包 (APK) 的工具和流程。構建流程非常靈活,因此了解它的一些底層工作原理會很有幫助。

如圖 1 所示,典型 Android 應用模塊的構建流程通常按照以下步驟執(zhí)行:
編譯器將您的源代碼轉(zhuǎn)換成 DEX 文件(Dalvik 可執(zhí)行文件,其中包括在 Android 設備上運行的字節(jié)碼),并將其他所有內(nèi)容轉(zhuǎn)換成編譯后的資源。
APK 打包器將 DEX 文件和編譯后的資源合并到一個 APK 中。不過,在將應用安裝并部署到 Android 設備之前,必須先為 APK 簽名。
-
APK 打包器使用調(diào)試或發(fā)布密鑰庫為 APK 簽名:
- 如果您構建的是調(diào)試版應用(即專用于測試和分析的應用),則打包器會使用調(diào)試密鑰庫為應用簽名。Android Studio 會自動使用調(diào)試密鑰庫配置新項目。
- 如果您構建的是打算對外發(fā)布的發(fā)布版應用,則打包器會使用發(fā)布密鑰庫為應用簽名。如需創(chuàng)建發(fā)布密鑰庫,請參閱在 Android Studio 中為應用簽名。
在生成最終 APK 之前,打包器會使用 zipalign 工具對應用進行優(yōu)化,以減少其在設備上運行時所占用的內(nèi)存。
構建流程結束時,您將獲得應用的調(diào)試版 APK 或發(fā)布版 APK,以用于部署、測試或發(fā)布給外部用戶。
自定義構建配置
Gradle 和 Android 插件可幫助您完成以下方面的構建配置:
構建類型
構建類型定義 Gradle在構建和打包應用時使用的某些屬性,通常針對開發(fā)生命周期的不同階段進行配置。例如,調(diào)試構建類型支持調(diào)試選項,并使用調(diào)試密鑰為 APK 簽名;而發(fā)布構建類型則會縮減 APK、對 APK 進行混淆處理,并使用發(fā)布密鑰為 APK 簽名以進行分發(fā)。如需構建應用,您必須至少定義一個構建類型。Android Studio 默認會創(chuàng)建調(diào)試和發(fā)布兩個構建類型。如需開始為應用自定義打包設置,請了解如何配置構建類型。產(chǎn)品變種
產(chǎn)品變種代表您可以向用戶發(fā)布的應用的不同版本,如應用的免費版和付費版。您可以自定義產(chǎn)品變種來使用不同的代碼和資源,同時共享和重復利用所有應用版本共用的部分。產(chǎn)品變種是可選的,您必須手動創(chuàng)建。如今日頭條的正常版本和極速版等。構建變體
構建變體是構建類型與產(chǎn)品變種的交叉產(chǎn)物,也是 Gradle 用來構建應用的配置。利用構建變體,您可以在開發(fā)期間構建產(chǎn)品變種的調(diào)試版本,或者構建產(chǎn)品變種的已簽名發(fā)布版本以供分發(fā)。雖然您無法直接配置構建變體,但可以配置組成它們的構建類型和產(chǎn)品變種。創(chuàng)建額外的構建類型或產(chǎn)品變種也會創(chuàng)建額外的構建變體。清單條目
您可以在構建變體配置中為清單文件的某些屬性指定值。這些構建值會替換清單文件中的現(xiàn)有值。如果您要為模塊生成多個 APK,讓每一個 APK 文件都具有不同的應用名稱、最低 SDK 版本或目標 SDK 版本,便可運用這一技巧。當存在多個清單時,Gradle 會合并清單設置。依賴項
您可以在構建變體配置中為清單文件的某些屬性指定值。這些構建值會替換清單文件中的現(xiàn)有值。如果您要為模塊生成多個 APK,讓每一個 APK 文件都具有不同的應用名稱、最低 SDK 版本或目標 SDK 版本,便可運用這一技巧。當存在多個清單時,Gradle 會合并清單設置。簽名
您可以在構建變體配置中為清單文件的某些屬性指定值。這些構建值會替換清單文件中的現(xiàn)有值。如果您要為模塊生成多個 APK,讓每一個 APK 文件都具有不同的應用名稱、最低 SDK 版本或目標 SDK 版本,便可運用這一技巧。當存在多個清單時,Gradle 會合并清單設置。代碼和資源壓縮
構建系統(tǒng)讓您能夠為每個構建變體指定不同的 ProGuard 規(guī)則文件。在構建應用時,構建系統(tǒng)會應用一組適當?shù)囊?guī)則來使用其內(nèi)置的縮減工具(如 R8)縮減您的代碼和資源。多 APK 支持
構建系統(tǒng)讓您能夠自動構建不同的 APK,并且每個 APK 只包含特定屏幕密度或應用二進制接口 (ABI) 所需的代碼和資源。
構建配置文件
Gradle 設置文件
settings.gradle 文件位于項目的根目錄下,用于指示 Gradle 在構建應用時應將哪些模塊包含在內(nèi)。對大多數(shù)項目而言,該文件很簡單,只包含以下內(nèi)容:
include ‘:app’
不過,多模塊項目需要指定應包含在最終構建中的每個模塊。
頂層構建文件
頂層 build.gradle 文件位于項目的根目錄下,用于定義適用于項目中所有模塊的構建配置。默認情況下,頂層構建文件使用 buildscript 代碼塊來定義項目中所有模塊共用的 Gradle 代碼庫和依賴項。以下代碼示例說明了創(chuàng)建新項目后可在頂層 build.gradle 文件中找到的默認設置和 DSL 元素。
/**
* 在buildscript塊中,您可以配置存儲庫和Gradle本身的依賴關系,意味著,您不應包含依賴關系用于此處的模塊。例如,此塊包含
* 用于Gradle作為依賴項,因為它提供了Gradle的附加說明需要構建Android應用模塊。
*/
buildscript {
/**
* 存儲庫塊配置Gradle用來存儲的存儲庫搜索或下載依賴項。Gradle預配置對遠程的支持存儲庫,
* 例如JCenter,Maven Central和Ivy。您也可以使用本地存儲庫或定義自己的遠程存儲庫。
* 下面的代碼定義將JCenter、google()和自定義的作為Gradle的存儲庫來查找其依賴項。
*/
repositories {
google()
jcenter()
maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' }
}
/**
* 依賴關系塊配置Gradle需要使用的依賴關系建立您的項目。以下行為Gradle添加了Android插件版本4.0.0作為類路徑依賴項。
*/
dependencies {
classpath 'com.android.tools.build:gradle:4.0.0'
/**
* 注意:不要將您的應用程序依賴項放在這里;它們屬于在單獨的模塊build.gradle文件中
*/
}
}
/**
* allprojects塊是您配置存儲庫和項目中所有模塊使用的依賴項,例如第三方插件或庫。但是,您應該在每個模塊級的build.gradle文件。
* 對于新項目,Android Studio默認情況下包括JCenter和Google的Maven存儲庫。
*/
allprojects {
repositories {
google()
jcenter()
maven {
url "http://mvn.gt.igexin.com/nexus/content/repositories/releases/"
}
maven { url "https://jitpack.io" }
}
}
配置項目全局屬性
對于包含多個模塊的 Android 項目,可能有必要在項目層級定義某些屬性并在所有模塊之間共享這些屬性。為此,您可以將額外的屬性添加到頂層 build.gradle 文件內(nèi)的 ext 代碼塊中。
buildscript {...}
allprojects {...}
// 此塊封裝了自定義屬性,并使它們對所有module可用項目中的模塊。
ext {
// 以下僅是您可以定義的屬性類型的幾個示例。
compileSdkVersion = 28
// 您還可以創(chuàng)建屬性以指定依賴項的版本。模塊之間具有一致的版本可以避免與行為發(fā)生沖突。
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}"
...
}
注意:雖然 Gradle 可讓您在模塊級別定義項目全局屬性,但您應避免這樣做,因為這樣會導致共享這些屬性的模塊進行耦合。模塊耦合使得以后將模塊作為獨立項目導出更加困難,并實際妨礙 Gradle 利用并行項目執(zhí)行來加快多模塊構建。
模塊級構建文件
模塊級 build.gradle 文件位于每個 project/module/ 目錄下,用于為其所在的特定模塊配置構建設置。您可以通過配置這些構建設置來提供自定義打包選項(如額外的構建類型和產(chǎn)品變種),以及替換 main/ 應用清單或頂層 build.gradle 文件中的設置。
以下 Android 應用模塊 build.gradle 文件示例簡要說明了您應該了解的一些基礎 DSL 元素和設置。
/**
* 構建配置的第一行將Android插件應用于 擴展到此版本,并使android塊可用于指定 特定于Android的構建選項。
*/
apply plugin: 'com.android.library'
/**
* android塊是您配置所有特定于Android的地方構建選項。
*/
android {
/**
* compileSdkVersion指定Gradle應該使用的Android API級別編譯您的應用程序。這意味著您的應用可以使用其中包含的API功能和此API級別及更低。
*/
compileSdkVersion 29
/**
* buildToolsVersion指定SDK生成工具的版本,命令行Gradle用于構建應用程序的實用程序和編譯器。你需要使用SDK Manager下載構建工具。
* 此屬性是可選的,因為插件默認情況下使用推薦的版本為構建工具。
*/
buildToolsVersion "29.0.2"
/**
* defaultConfig塊封裝了所有的默認設置和條目構建變體,并且可以覆蓋main / AndroidManifest.xml中的某些屬性
* 。您可以配置產(chǎn)品變體以覆蓋這些值適用于您應用的不同版本。
*/
defaultConfig {
/**
* applicationId唯一標識要發(fā)布的包。 但是,您的源代碼仍應引用程序包名稱由main / AndroidManifest.xml文件中的package屬性定義。
*/
applicationId 'com.example.myandroidxdemo'
/**
* 定義運行應用程序所需的最低API級別。
*/
minSdkVersion 21
/**
* 指定用于測試應用程序的API級別。
*/
targetSdkVersion 29
/**
* 定義您的應用程序的版本號。
*/
versionCode 1
/**
* 為您的應用定義用戶友好的版本名稱。
*/
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
/**
* 您可以在buildTypes塊中配置多種構建類型。默認情況下,構建系統(tǒng)定義兩種構建類型:調(diào)試和發(fā)布。默認版本配置中未明確顯示
* 調(diào)試版本類型,但其中包含調(diào)試工具,并使用調(diào)試密鑰進行了簽名。發(fā)布構建類型適用Proguard設置,并且默認情況下未簽名。
*/
buildTypes {
/**
* 默認情況下,Android Studio將發(fā)布版本類型配置為啟用代碼使用minifyEnabled縮小,并指定默認的Proguard規(guī)則文件。
*/
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
/**
* 您可以在productFlavors塊中配置多種產(chǎn)品變種。這使您可以創(chuàng)建應用的不同版本,用自己的設置覆蓋defaultConfig塊。
* 產(chǎn)品維度是可選的,系統(tǒng)默認不會創(chuàng)建它們。需要我們手動創(chuàng)建
* 此示例創(chuàng)建了免費和付費的產(chǎn)品樣式。每種產(chǎn)品的變體指定其自己的應用程序ID,以便它們可以在Google上存在同時存放
* Play商店或Android設備。如果聲明產(chǎn)品變體,則還必須聲明變體維度,并將每種變體分配給變體維度。
*/
/**
* 指定該項目的產(chǎn)品變種維度的名稱
* 使用Android插件3.0.0及更高版本配置產(chǎn)品變種時,您必須使用flavorDimensions屬性至少指定一個變種維度,
* 然后將每個變種分配給一個維度。否則,您將收到以下構建錯誤:
* Error:All flavors must now belong to a named flavor dimension.
* The flavor 'flavor_name' is not assigned to a flavor dimension.
*/
flavorDimensions 'api', 'version'
/**
* 默認情況下,當您僅指定一個維度時,您配置的所有樣式都會自動屬于該維度。如果指定多個維度,則需要手動將每種產(chǎn)品變種分配給
* 一個維度,如下面的示例所示。
* flavorDimensions允許您創(chuàng)建可以與其他flavorDimensions的flavor組合的productFlavors組。
* 例如,您可以具有一個維度,其中包括應用程序的“免費”和“付費”版本,而另一個維度用于支持不同API級別的變體
* (例如“ minApi21”和“ minApi24”)。然后,Android插件可以結合這些方面的特點(包括其設置,代碼和資源)來創(chuàng)建變體,
* 例如“ debugFreeMinApi21”和“releasePaidMinApi24”等。下面的示例向您展示如何指定flavorDimension以及如何向
* 其中添加productFlavor。
*/
productFlavors {
demo {
// 將此產(chǎn)品變種分配給“version”組
dimension 'version'
}
full {
dimension 'version'
}
minApi24 {
// 將此產(chǎn)品變種分配給“api”組
dimension 'api'
minSdkVersion '24'
versionNameSuffix "-minApi24"
}
minApi21 {
dimension "api"
minSdkVersion '21'
versionNameSuffix "-minApi21"
}
}
/**
* 您可以在splits塊中配置不同的APK版本, *每個僅包含代碼和資源以實現(xiàn)受支持的屏幕密度,或者ABI。您還需要配置構建,
* 以便每個APK都有一個不同的versionCode。
*/
splits {
// 用于根據(jù)屏幕密度構建多個APK的設置。
density {
// 啟用或禁用構建多個APK。
enable false
// 構建多個APK時,請排除這些密度。
exclude "ldpi", "tvdpi", "xxxhdpi", "400dpi", "560dpi"
}
}
}
/**
* 模塊級構建配置文件中的依賴項塊指定僅構建模塊本身所需的依賴項。 要了解更多信息,請轉(zhuǎn)到添加構建依賴項。
*/
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
}
Gradle 屬性文件
Gradle 還包含兩個屬性文件,它們位于項目的根目錄下,可用于指定 Gradle 構建工具包本身的設置:
gradle.properties:您可以在其中配置項目全局 Gradle 設置,如 Gradle 守護進程的最大堆大小。
local.properties:為構建系統(tǒng)配置本地環(huán)境屬性,其中包括:
- ndk.dir - NDK 的路徑。此屬性已被棄用。NDK 的所有下載版本都將安裝在 Android SDK 目錄下的 ndk 目錄中。
- sdk.dir - SDK 的路徑。
- cmake.dir - CMake 的路徑。
- ndk.symlinkdir - 在 Android Studio 3.5 及更高版本中,創(chuàng)建指向 NDK 的符號鏈接,該鏈接可比 NDK 安裝路徑短。
將 NDK 重新映射到較短的路徑(僅限 Windows)
Windows 長路徑最常見的問題就是 NDK 安裝文件夾中的工具(如 ld.exe)會產(chǎn)生非常深的路徑,但工具對于長路徑的支持并不佳。
在 local.properties 中,您可以設置 ndk.symlinkdir 屬性來請求 Gradle 插件創(chuàng)建指向 NDK 的符號鏈接。該符號鏈接的路徑可比現(xiàn)有 NDK 文件夾的路徑短。例如,ndk.symlinkdir = C:\ 將生成以下符號鏈接:C:\ndk\19.0.5232133
將項目與 Gradle 文件同步
當您在項目中對構建配置文件進行更改時,Android Studio 會要求您同步項目文件,以便它導入構建配置更改并執(zhí)行一些檢查來確保您的配置不會造成構建錯誤。
要同步項目文件,請點擊做出更改后顯示的通知欄中的 Sync Now(如圖 3 所示),或者點擊菜單欄中的 Sync Project 圖標

。如果 Android Studio 發(fā)現(xiàn)您的配置有任何錯誤(例如,您的源代碼使用了只有在 compileSdkVersion 以上的 API 級別中才會提供的 API 功能),就會顯示 Messages 窗口來說明該問題。

源代碼集
Android Studio 按邏輯關系將每個模塊的源代碼和資源分組為源代碼集。模塊的 main/ 源代碼集包含其所有構建變體共用的代碼和資源。其他源代碼集目錄是可選的,在您配置新的構建變體時,Android Studio 不會自動為您創(chuàng)建這些目錄。不過,創(chuàng)建類似于 main/ 的源代碼集有助于更好地組織管理 Gradle 僅在構建特定應用版本時才應使用的文件和資源:
src/main/:此源代碼集包含所有構建變體共用的代碼和資源。
src/buildType/:創(chuàng)建此源代碼集可加入特定構建類型專用的代碼和資源。
src/productFlavor/:創(chuàng)建此源代碼集可加入特定產(chǎn)品變種專用的代碼和資源。
注意:如果配置構建以組合多個產(chǎn)品變種,則可以為變種維度之間的每個產(chǎn)品變種組合創(chuàng)建源代碼集目錄:src/productFlavor1ProductFlavor2/
src/productFlavorBuildType/:創(chuàng)建此源代碼集可加入特定構建變體專用的代碼和資源。
例如,如需生成應用的“fullDebug”版本,構建系統(tǒng)需要合并來自以下源代碼集的代碼、設置和資源:
-
src/fullDebug/:(構建變體源代碼集) -
src/debug/:(構建類型源代碼集) -
src/full/:(產(chǎn)品變種源代碼集) -
src/main/:(主源代碼集)
注意:當您在 Android Studio 中使用 File > New 菜單選項新建文件或目錄時,可以針對特定源代碼集進行創(chuàng)建??晒┠x擇的源代碼集取決于您的構建配置,如果所需的目錄尚不存在,Android Studio 會自動創(chuàng)建。
如果不同源代碼集包含同一文件的不同版本,Gradle 將按以下優(yōu)先順序決定使用哪一個文件(左側源代碼集替換右側源代碼集的文件和設置):
構建變體 > 構建類型 > 產(chǎn)品變種 > 主源代碼集 > 庫依賴項
這樣一來,Gradle 便可使用專用于您試圖構建的構建變體的文件,同時重復利用與應用的其他版本共用的 Activity、應用邏輯和資源。在合并多個清單時,Gradle 會使用相同的優(yōu)先順序,這樣每個構建變體都能在最終清單中定義不同的組件或權限。