什么是Gradle?
Gradle 是一個開源的構建自動化系統。它擁有基於 Groovy 的 DSL 的便利以及 Ant 和 Maven 的優勢。
使用 Gradle,您可以輕松地操縱構建過程及其邏輯,以創建應用程序的多個版本。與單獨使用 Ant 或 Maven 相比,它更易於使用,更加簡潔和靈活。
入門
新建一個 Android project,將以該項目進行講解。
在開始處理項目之前,讓我們在 Android Studio 的 "project" 選項中查看其結構:

注意帶有綠色 Gradle 圖標和擴展名 .gradle 的文件。這些文件由Android Studio在項目創建過程中自動生成。他們負責處理項目的構建。它們包含有關項目結構,庫依賴項,庫版本以及在構建過程中將獲得的應用程序版本的必要信息。
Project 層的 build.gradle
在項目的根目錄中找到 build.gradle 文件。它稱為頂級(項目級別)build.gradle 文件。它包含適用於項目所有模塊的設置。
// 1 buildscript { // 2 repositories { google() jcenter() } // 3 dependencies { classpath 'com.android.tools.build:gradle:3.0.0' classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.51' } } // 4 allprojects { repositories { google() jcenter() } }
這是逐步進行的操作:
-
在 buildscript 塊中,定義執行項目構建所需的設置。
-
在 repositories 塊中,添加 Gradle 應搜索使用的庫的存儲庫名稱。
-
該 dependencies 塊包含必要的插件依賴性,在這種情況下為 Gradle 和 Kotlin 插件。不要將模塊依賴項放在此塊中。
-
該 allprojects 塊的結構類似於該 buildscript 塊,但是在這里您為所有模塊定義存儲庫,而不是為 Gradle 本身定義存儲庫。通常,您不會為定義該 dependencies 部分 allprojects。每個模塊的依賴關系都不同,並且應位於模塊級 build.gradle 中。
Moudle 層的 build.gradle
現在轉到應用程序模塊目錄中的build.gradle文件。它包含依賴項(模塊所依賴的庫)以及構建過程的說明。每個模塊定義其自己的build.gradle文件。
// 1 apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' // 2 android { // 3 compileSdkVersion 27 // 4 buildToolsVersion "26.0.2" // 5 defaultConfig { // 6 applicationId "com.raywenderlich.socializify" // 7 minSdkVersion 21 // 8 targetSdkVersion 27 // 9 versionCode 1 // 10 versionName "1.0" } } // 11 dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'org.jetbrains.kotlin:kotlin-stdlib-jre7:1.1.51' implementation 'com.android.support:appcompat-v7:27.0.1' implementation 'com.android.support.constraint:constraint-layout:1.0.2' }
上面的代碼執行以下操作:
-
指定構建模塊所需的插件列表。該 com.android.application 插件對於設置構建過程的 Android 特定設置是必需的。com.android.library 如果要創建庫模塊,也可以在這里使用。在 kotlin-android 和 kotlin-android-extensions 插件允許你使用 kotlin 語言和相關插件到您的模塊中。
-
在該 android 塊中,放置模塊的所有具體平台參數的選項。
-
該 compileSdkVersion 選項指示您的應用將使用的 API 級別。換句話說,您不能使用 API 中高於此值的功能。在這里,您已設置了使用 Android Oreo API 的值。
-
該 buildToolsVersion 選項指示編譯器的版本。從 Gradle 插件 3.0.0 開始,此字段是可選的。如果未指定,則 Android SDK 使用構建工具的最新下載版本。
-
該 defaultConfig 塊包含默認情況下將應用於您應用的所有構建版本(例如,調試,發行等)的選項。
-
該 applicationId 是你的應用程序的標識。它應該是唯一的,以便在 Google Play 商店中成功發布或更新您的應用。
-
為了設置支持的最低API級別,請使用 minSdkVersion。在 API 級別較低的設備上,您的應用將無法在 Google Play 商店中使用。
-
該 targetSdkVersion 參數定義了您的應用經過測試的最大 API 級別。也就是說,您確定您的應用程序可以在具有此 SDK 版本的設備上正常運行,並且不需要任何向后兼容行為。最好的方法是使用最新的API徹底測試應用,並保持您的 targetSdkVersion 等於 compileSdkVersion。
-
versionCode 是應用程序版本的數值。
-
versionName 是應用程序版本的用戶友好字符串。
- 該 dependencies 塊包含此模塊所需的所有依賴關系。
settings.gradle
根目錄中的 settings.gradle 文件。其內容應如下所示:
include ':app'
在此文件中,應按名稱定義項目的所有模塊。在這里,我們只有一個模塊 — app。在大型,多模塊的項目中,此文件會有更長的列表。
Gradle 命令
要執行Gradle命令,您可以同時使用命令行和 Android Studio。最好從命令行開始,以更深入地了解正在發生的事情。那么,如何開始使用 Gradle 命令呢?非常簡單:使用 gradlew。
什么是 gradlew
gradlew 是 Gradle 包裝器。您無需擔心在計算機上安裝 Gradle,包裝程序將為您完成此操作。甚至更多,它使您可以使用不同版本的 Gradle 構建不同的項目。
打開命令行並移至入該項目的根目錄,之后,執行以下命令:
./gradlew tasks
您將看到一個包含所有可用任務的列表:
> Task :tasks ------------------------------------------------------------ All tasks runnable from root project ------------------------------------------------------------ Android tasks ------------- androidDependencies - Displays the Android dependencies of the project. signingReport - Displays the signing info for each variant. sourceSets - Prints out all the source sets defined in this project. Build tasks ----------- assemble - Assembles all variants of all applications and secondary packages. assembleAndroidTest - Assembles all the Test applications. assembleDebug - Assembles all Debug builds. assembleRelease - Assembles all Release builds. ... Build Setup tasks ----------------- init - Initializes a new Gradle build. wrapper - Generates Gradle wrapper files. Help tasks ---------- ... Install tasks ------------- ... Verification tasks ------------------ ... lint - Runs lint on all variants. ... To see all tasks, run gradlew tasks --all To get more detail about task, run gradlew help --task <task>
這些命令可以幫助您完成項目初始化,構建,測試和分析等任務。如果您忘記了一個特定的命令,只需執行 ./gradlew tasks 來找到自己需要的任務。
gradlew assemble
現在,再次瀏覽命令列表,並在該部分下找到以 “assemble” 開頭的命令 Build tasks。運行第一個命令:
./gradlew assemble
以下是執行此命令的輸出
> Task :app:compileDebugKotlin Using kotlin incremental compilation > Task :app:compileReleaseKotlin Using kotlin incremental compilation BUILD SUCCESSFUL in 29s 52 actionable tasks: 52 executed
從輸出中,這是顯而易見的是搖籃的編譯應用程序的兩個版本 - debug 和 release。
通過更改到構建輸出目錄來驗證此內容:
cd app/build/outputs/apk/
要查看目錄的內容,請運行以下命令:
ls -R
該 ls 命令顯示當前目錄中的所有文件和目錄。該 -R 參數強制此命令以遞歸方式執行。換句話說,您不僅會看到當前目錄的內容,還會看到子目錄的內容。
您將獲得以下輸出:
debug release ./debug: app-debug.apk output.json ./release: app-release-unsigned.apk output.json
如您所見,Gradle 生成了 debug 和 release apk。
管理依賴關系
現在是時候對應用程序本身進行更改了。
首先,在項目的根目錄中創建一個名為 dependencies.gradle 的文件。您將使用此文件在一處識別所有項目依賴項版本。將以下內容添加到此文件:
ext { minSdkVersion = 17 targetSdkVersion = 27 compileSdkVersion = 27 buildToolsVersion = “ 26.0.2” kotlinVersion = “ 1.1.51 ”
supportVersion = “ 27.0.1” picassoVersion = “ 2.5.2” }
打開項目級別的 build.gradle 文件(位於根目錄中的一個,而不是 app 目錄中的一個!),然后在文件頂部添加以下行:
apply from: 'dependencies.gradle'
現在,您可以像下面這樣使用其他項目構建文件中在 dependencies.gradle 文件中指定的屬性:
應用程序模塊級別的 build.gradle
android { compileSdkVersion rootProject.compileSdkVersion buildToolsVersion rootProject.buildToolsVersion defaultConfig { applicationId "com.raywenderlich.socializify" minSdkVersion rootProject.minSdkVersion targetSdkVersion rootProject.targetSdkVersion versionCode 1 versionName "1.0" } } dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation "com.android.support:appcompat-v7:$rootProject.supportVersion" implementation "com.android.support:design:$rootProject.supportVersion" implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$rootProject.kotlinVersion" }
Gradle依賴項配置
implementation 您先前使用的關鍵字是依賴項配置,該配置告訴 Gradle 以這種方式添加依賴,其他模塊無法使用它。該選項大大加快了構建時間。
在某些其他情況下,您可能希望項目的其他模塊可以訪問依賴項。在這種情況下,您可以使用 api 關鍵字。
其他選項包括 runtimeOnly 和 compileOnly 配置,它們僅在運行時或編譯時標記依賴項的可用性。
准備發布:使用 Product Flavors and Build Types
您的應用已准備就緒,您正在考慮怎么從項目中獲利的方法:

一種解決方案是擁有多個版本的應用程序:免費和付費版本。幸運的是,gradle 在構建級別支持此功能,使您可以定義不同構建類型的邊界。但是,在開始之前,您需要了解 Gradle 如何允許您使用不同的應用程序版本。
構建類型
默認情況下,有兩種構建類型 debug 和 release。它們之間的唯一區別是 debuggable 參數的值。換句話說,您可以使用調試版本查看日志並調試應用程序,而發布版本則用於將您的應用程序發布到 Google Play 商店。您可以通過在 android 模塊級 build.gradle 文件的塊中添加以下代碼來為構建類型配置屬性:
buildTypes {
release {
}
debug {
}
}
在 debug 和 release 塊中,您可以指定應用程序的特定於類型的設置。
Build Signing
構建的最重要的配置之一是其簽名。沒有簽名,您將無法發布您的應用程序,因為有必要驗證您是否是特定應用程序的所有者。盡管您無需簽署調試版本(Android Studio會自動進行簽名),但發行版本應由開發人員簽名。
當你的密鑰庫已准備就緒,下面添加的代碼位於 android 塊下,與上述 buildTypes 塊處於 module 層級的的 build.gradle 文件:
signingConfigs { release { storeFile file("path to your keystore file") storePassword "your store password" keyAlias "your key alias" keyPassword "your key password" } }
在 signingConfigs 塊中,為構建類型指定簽名信息。注意密鑰庫文件路徑。應該相對於模塊目錄進行指定。換句話說,如果您在模塊目錄中創建了密鑰庫文件並將其命名為“ keystore.jks”,則應指定的值將等於文件名。
更新 buildTypes 塊以自動簽署發布版本:
release {
signingConfig signingConfigs.release
}
注意:與密鑰庫文件相關的兩個重要注意事項:
-
將應用發布到Google Play商店后,后續提交必須使用相同的密鑰庫文件和密碼,以確保安全。
-
確保不要將密鑰庫密碼提交給版本控制系統,例如GitHub。您可以通過以下方式進行操作:將密碼保存在與中不同的文件中build.gradle(例如keystorePassword.gradle,在Signing目錄中),然后build.gradle通過以下方式從應用程序模塊級別引用該文件:
apply from: "../Signing/keystorePassword.gradle
然后確保保持 keystorePassword.gradle 版本控制系統忽略它。其他技術包括將密碼保存在 OS 級環境變量中,尤其是在遠程持續集成系統(例如 CircleCI )上。
Build Flavors
為了創建您的應用程序的多個版本,您需要使用 productflavors。Flavors 是一種區分應用程序屬性的方法,無論它是免費/付費的,分階段的/生產的等等。
您將使用不同的應用程序名稱來區分您的應用程序風格。首先,將以下名稱添加為 strings.xml 文件中的字符串:
<string name="app_name_free">Socializify Free</string> <string name="app_name_paid">Socializify Paid</string>
並刪除現有的:
<string name="app_name">test</string>
現在,原始 app_name 字符串不再可用,請編輯 AndroidManifest.xml 文件,並將在 application 中的 android:label="@string/app_name" 替換為 android:label="${appName}" 。
同時在 modle 層級 build.gradle 文件的 android 塊中添加以下代碼:
// 1
flavorDimensions "appMode"
// 2
productFlavors {
// 3
free {
// 4
dimension "appMode"
// 5
applicationIdSuffix ".free"
// 6
manifestPlaceholders = [appName: "@string/app_name_free"]
}
paid {
dimension "appMode"
applicationIdSuffix ".paid"
manifestPlaceholders = [appName: "@string/app_name_paid"]
}
}
-
您需要指定 flavorDimensions 以正確匹配構建類型。在當前示例中,只需要一個維度 - appMode。
-
在 productFlavors 指定具體的 flavors 和 具體的設置。在當前示例中,分別是 free 和 paid。
-
指定第一個 productFlavors 的名稱為:free。
-
必須指定 dimension 參數值。這里 free flavor 屬於 appMode dimension。
-
由於您要為免費和付費功能創建單獨的應用程序,因此需要它們具有不同的應用程序標識符。該 applicationIdSuffix 參數定義了會被附加到一個 applicationId 上,從而讓你的應用程序擁有唯一標識符。
-
manifestPlaceholders 允許你在構建的時候修改 AndroidManifest.xml 中的屬性。在當前示例中,會根據不同的版本來修改應用名稱。
再次 sync project with Gradle。項目同步后,運行 tasks 命令,並查看哪些內容發生了改變:
./gradlew tasks
您將獲得與第一次運行此命令時類似的任務列表:
...
Build tasks
-----------
...
assembleDebug - Assembles all Debug builds.
assembleFree - Assembles all Free builds.
assemblePaid - Assembles all Paid builds.
assembleRelease - Assembles all Release builds.
...
可以發現,任務添加了一些新的選項。現在,每種構建類型和構建 flavors 都有自己單獨的命令。
從上一個 ./gradlew assemble 任務中刪除生成的輸出文件夾,以便您可以在添加 buildTypes 和 productFlavors 之后看到明顯的區別。運行命令:
rm -rf app/build/outputs/apk
然后
./gradlew assembleDebug
命令完成后,檢查輸出目錄:
cd app/build/outputs/apk
ls -R
您將獲得如下內容:
free paid
./free:
debug
./free/debug:
app-free-debug.apk output.json
./paid:
debug
./paid/debug:
app-paid-debug.apk output.json
您應該生成兩個應用 – freeDebug 和 paidDebug。
什么是Build Variant
從上面的輸出中,您實際生成的是不同的構建變體,它們是構建類型 (buildType) 和構建風格 (flavors)組合。也就是說,您有四個可能的構建變體– paidDebug,paidRelease,freeDebug 和 freeRelease。
現在您有兩種不同的構建風格,但是,不同的名稱不足以讓您從中獲利。相反,您將根據構建風格 (flavors)配置應用程序的行為!
現在我們在 MainActivity 中定義一個常量:
private static String PAID_FLAVOR = "paid";
在 onCreate 方法中添加如下變量:
if (BuildConfig.FLAVOR == PAID_FLAVOR) {
Toast.makeText(this, "3453", Toast.LENGTH_SHORT).show();
}
如果是付費版本,就會有個 toast 提示。當然,上面只是一個示例,大家后面
創建任務
有時,您需要構建系統執行更復雜的操作或以某種方式自定義構建過程。例如,您可能希望Gradle輸出名稱中包含構建日期的APK文件。一種可能的解決方案是創建自定義 Gradle 任務。
將以下代碼添加到模塊級別的 build.gradle 文件中,與 android block 處於同一級別:
// 1
task addCurrentDate() {
// 2
android.applicationVariants.all { variant ->
// 3
variant.outputs.all { output ->
// 4
def date = new Date().format("dd-MM-yyyy")
// 5
def fileName = variant.name + "_" + date + ".apk"
// 6
output.outputFileName = fileName
}
}
}
下面說下相關邏輯:
-
您定義一個 addCurrentDate() 任務。
-
您遍歷所有輸出構建變量。
-
您遍歷所有 APK 文件。
-
您創建一個實例 Date 並設置其格式。
-
您創建一個新的文件名,將當前日期附加到初始名稱之后。
-
您將新文件名設置為當前的 APK 文件。
現在,您需要在構建過程的特定時刻執行此任務。在 task addCurrentDate() 塊下面添加以下代碼:
gradle.taskGraph.whenReady {
addCurrentDate
}
whenReady 當前圖形中充滿任務並准備開始執行時,塊中指定的任務將被調用一次。在這里,您指定 addCurrentDate 任務的名稱。
現在,返回命令行,並確保您位於根目錄中。運行以下命令以組裝構建:
./gradlew assemblePaidRelease
任務完成后,轉到輸出目錄,檢查是否正確命名了內部版本:
cd app/build/outputs/apk/paid/release/
ls
您應該得到類似的輸出:
output.json paidRelease_12-29-2019.apk
如果您的任務正確執行,則所有構建都將使用此約定命名。
到此,關於 gradle 的介紹就到這里。當然這也只是入門,后續還有 gradle 插件等需要繼續學習。
參考文章
原文:Gradle Tutorial for Android: Getting Started
