Gradle For Android(2)--基礎的定製構建
理解Gradle檔案
當建立一個新的Project的時候,會預設生成3個Gradle檔案。在專案的根目錄(在Project的Top-Level)下會生成settings.gradle
和build.gradle
。而在Android app模組中會建立一個build.gradle
檔案。目錄結構如下:
MyApp
├── build.gradle
├── settings.gradle
└── app
└── build.gradle
Settings檔案
對於一個新的Project,settings.gradle
檔案只會有一行
include ':app'
這個setting.gradle
在初始化階段被執行,並且定義了哪些Module應該在構建中被包含。在該例中,只有:app
模組被包含。只有一個模組的Project可以不需要該檔案,而多個模組的Project的必須要該檔案,否則Gradle不知道哪些模組需要被包含(include)。
在這種場景下,Gradle建立了為每個Settings檔案都建立了一個Serttings
物件,並且可以從該物件中呼叫所需要的Methods。我們不需要知道Settings類的細節,但是最好關注一下。
頂層的build.gradle
頂層的build.gradle
檔案中,我們可以配置一些options,這些options可以應用於所有在這個Project中的Module。它預設包含以下兩個程式碼塊:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
}
}
allprojects {
repositories {
jcenter() }
}
}
buildscript
程式碼塊中是真正構建的配置的地方。respositories
程式碼塊配置了JCenter作為倉庫。在這種情況下,倉庫代表了這個Project所依賴的資源或者說我們所需要的一些可下載的Libraries都是儲存在這個倉庫中。JCenter是一個知名的Maven倉庫。
dependencies
程式碼塊用來配置構建過程的依賴。也就是說,我們不應該在Top-Level的build.gradle
中包含Application或者Libraries的依賴。它唯一的依賴關係應該為是預設定義的Android Plugin。它會去遍歷每一個Android Module,因為它是會執行Android-Related Tasks的外掛。
allprojects
程式碼塊用來定義需要被應用到每一個Module中的屬性。我們甚至可以在這個程式碼塊中建立Task,而這些Task可以在各個Module中被應用。
Module中的build.gradle
Module層的build.gradle
檔案包含了一些options,這些options只能應用在Android app module中。它也能夠覆蓋Project層的build.gradle
檔案中的屬性。該模組的file如下:
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "com.gradleforandroid.gettingstarted"
minSdkVersion 14
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile
('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.0'
}
其中三個主要的程式碼塊:
- plugin:第一行應用了Android的application plugin,配置在頂層的
build.gradle
中。這個外掛主要由Android工具團隊寫並且維護的,提供了所有需要構建application以及libraries的build,test,package任務 - android:這個程式碼塊主要包括了Android特殊的配置。只有兩個屬性需要配置
compileSdkVersion
以及buildToolsVersion
。負責編譯的sdk api版本以及build tools的版本。其中build tools包括了很多命令列的工具,比如說aapt,zipalign,dx,renderscript等等,使用這些工具我們可以生產出各種各樣的中介軟體。我們可以通過SDK Manager下載build tools。
defaultConfig
程式碼塊配置了App核心的屬性。在這個程式碼塊中的屬性會重寫AndroidManifest.xml中相對應的屬性。
applicationId
屬性會重寫Manifest.xml中的packageName。在Gradle之前的構建系統中,PackageName有兩個作用,唯一表示一個App以及用於為R.java賦予包名。而通過Gradle使用build variants使得構建不同版本的App變得更加簡單了。比如,很容易構建一個付費/免費的版本。而這兩個版本需要兩個單獨的PackageName,這樣才能夠被一起裝到一個手機上。但是原始碼以及R檔案包名都還保持著相同的PackageName,以至於在構建多個版本的時候,需要把所有的原始檔都進行修改。
因此,這也就是為什麼Android Tool團隊減弱了packageName的這兩個用途。定義在Manifest中的PackageName仍然會用於SourceCode以及R檔案。而Google Play則會使用application id作為唯一識別符號來區分App。
包括minSdkVersion,targetSdkVersion,versionCode,versionName等等在內的所有值都會覆蓋掉Manifest.xml中的值,如果在build.gradle
中定義了這些值,Manifest.xml中就可以不定義了,但是以防萬一最好還是在Manifest.xml中定義好,避免遺漏出錯。
buildType
程式碼塊定義了構建不同型別的App的地方。後續會再詳細說明。
dependencies
程式碼塊是標準Gradle配置的一部分,這也就是它為什麼會在android
程式碼塊之外的原因。並且它定義了app或者library中所有的依賴關係。預設一個新的Android App會對libs
目錄下的所有jar包有依賴。取決於新Project的啟動項配置。
瞭解Tasks
為了瞭解整個Project中哪些Task是可用的,我們可以通過gradlew tasks
來列出所有可用的Tasks。如下圖所示:
在一個新建立的Android Project中,它包括了:
- Android tasks
- build tasks
- build setup tasks
- help tasks
- install Tasks
- verification Tasks
- ...
如果不止想看到Tasks,而是各個Task之間的依賴關係,可以使用gradlew tasks --all
。當你希望列印出執行一個特殊的Task的所有步驟時,可以加上引數-m
或者--dry-run
。
Android Tasks
Android Plugin繼承自基礎的Task,並且實現了自己一些功能。這些Tasks在Android中會有如下表現:
- assemble:為每個Build Type構建APK
- clean:移除所有Build中介軟體以及Apk檔案等等
- check:執行Lint的檢查,並且如果Lint出現問題的時候,會打斷Build過程
- build:執行assemble以及check任務
Assemble
任務預設由assembleDebug
以及assembleRelease
構成,如果有更多的Build Type的話,則會有更多的任務。也就是說,執行Aseemble將會為每個Build Type觸發一個構建。
除了繼承了這些Tasks之外,Android Plugin也新增了一些新的Task。以下為最重要的新的Tasks:
- connectedCheck:在已經連線的裝置或者模擬器上執行tests任務
- deviceCheck:為其他外掛在遠端裝置上除錯提供的佔位任務
- installDebug/installRelease:在已經連線的裝置或者模擬器上安裝一個特定的版本
- 所有的
install
任務都會有相對應的uninstall
任務
build
任務依賴於check
任務,而不是connectedCheck
或者deviceCheck
。這保證了常規的檢查不需要連線裝置 。執行完check
任務後,會生成一個Lint Report檔案,其中儲存著warnings以及errors,可以在app/build/outputs/lint-results.html
中找到。
當Assemble一個Release版本時,Lint將檢查可能會導致App Crash的問題。如果找到的話,就會中斷Build,並且在Command-Line中列印出錯誤。並且也會在app/build/outputs
中生成lint-results-release-fatal.html
檔案。如果有多個錯誤,則通過HTML的Report報告然後滑動到報錯的位置就可以看到了。
在Android Studio中,右側的Gradle
視窗雙擊對應的Task即可開始執行。也就不用在命令列工具中輸入命令了。
BuildConfig以及Resources
從SDK Tool版本17之後,Build Tool會生成一個名為BuildConfig
的類,其中包含了根據build type生成的DEBUG
常量。這對控制日誌列印是非常有利的。而且,這也為Debug或者Release的常量區分帶來了很多的方案,比如我們需要根據Build Type來開啟/關閉一些Features,或者設定Server的URLs等等,例如:
android {
buildTypes {
debug {
buildConfigField "String", "API_URL","\"http://test.example.com/api\""
buildConfigField "boolean", "LOG_HTTP_CALLS", "true"
}
release {
buildConfigField "String", "API_URL","\"http://example.com/api\""
buildConfigField "boolean", "LOG_HTTP_CALLS", "false"
}
}
}
通過雙引號中新增的String值會被生成一個真實的String。通過新增了buildConfigField
這一行,我們可以使用BuildConfig.API_URL
和BuildConfig.LOG_HTTP
來引用不同的值。
而最近,Android Tool團隊也會通過以下方式來配置資源:
android {
buildTypes {
debug {
resValue "string", "app_name", "Example DEBUG"
}
release {
resValue "string", "app_name", "Example"
}
}
}
Project級別的Settings
如果擁有多個Android Modules的話,它可以非常簡便的修改每個Module中的build.gradle
中的值,而不用手動的去修改了。我們已經看到了allprojects
程式碼塊在頂層的build.gradle
中定義了reositories
,並且你可以使用相同的方式來應用Android指定的Settings:
allprojects {
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
}
}
這段程式碼塊只會應用於所有的Android App Project,因為需要應用Android Plugin去使用Android特殊的Settings。一種更好的方案是在頂層的build.gradle
中定義這些值,然後在各個Module中應用。也就意味著,我們可以在build.gradle
檔案中繫結ext
程式碼塊,其中定義一些自定義的屬性:
ext {
compileSdkVersion = 22
buildToolsVersion = "22.0.1"
}
通過這種方式來在Module級別的build.gradle
中使用rootProject
來獲取使用的值。
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
}
Project properties
定義Project的Properties有幾種方式,最常用的三種:
- 使用
ext
程式碼塊 - 使用
gradle.properties
檔案 - 通過
-P
的命令列引數
以下為這三種方式的示例程式碼:
ext {
local = 'Hello from build.gradle'
}
task printProperties << {
println local // Local extra property
println propertiesFile // Property from file
if (project.hasProperty('cmd')) {
println cmd // Command line property
}
}
在gradle.properties
檔案中定義如下:
propertiesFile = Hello from gradle.properties
如果通過命令列引數執行printProperties
任務的話,輸出如下:
$ gradlew printProperties -P cmd='Hello from the command line'
:printProperties
Hello from build.gradle
Hello from gradle.properties
Hello from the command line
預設的任務
如果使用gradle
沒有指定具體的任務的話,則會執行help
任務。如果需要指定預設的任務的話,則需要在頂層的build.gradle
中加入預設任務:
defaultTasks 'clean', 'assembleDebug'
這樣的話,執行gradlew
就會預設執行這兩個任務。而通過gradlew tasks | grep "Default tasks"
也可以檢視預設的任務。
相關文章
- Gradle系列之構建指令碼基礎Gradle指令碼
- Gradle系列之Android Gradle基礎配置GradleAndroid
- Gradle for Android ( 構建變體 )GradleAndroid
- 用Gradle 構建你的android程式GradleAndroid
- Gradle For Android (一) 基礎定義與依賴管理篇GradleAndroid
- 不得不學之「 Gradle」 ③ 構建指令碼基礎Gradle指令碼
- Android中的Gradle之配置及構建優化AndroidGradle優化
- Android Gradle基於引數化配置實現差異化構建AndroidGradle
- gradle中的增量構建Gradle
- Android 應用構建速度提升Gradle配置優化AndroidGradle優化
- Android Gradle Groovy自動化構建進階篇AndroidGradle
- 使用新 Android Gradle 外掛加速您的應用構建AndroidGradle
- Idea下構建基於Gradle的Spring Boot專案IdeaGradleSpring Boot
- 作為Android開發你必須明白的Gradle基礎AndroidGradle
- Gradle自動實現Android元件化模組構建GradleAndroid元件化
- https構建(基礎)HTTP
- 構建第一個基於 Gradle 的 Spring Boot 專案GradleSpring Boot
- springboot gradle demo (使用 Gradle 構建的 Spring Boot專案)Spring BootGradle
- 構建與定製:唯品會PaaS基於Kubernetes的實踐
- Gradle中的差異化構建Gradle
- Gradle 與 AGP 構建 API: 配置您的構建檔案GradleAPI
- Gradle之多專案構建Gradle
- gradle構建spring原始碼GradleSpring原始碼
- Gradle構建SpringBoot專案GradleSpring Boot
- 【Java】【Gradle】Gradle構建SpringBoot專案,Gradle模組化管理JavaGradleSpring Boot
- Android Studio NDK :一、基礎入門(基於gradle-experimental外掛)AndroidGradle
- 通過Gradle自動實現Android元件化模組構建GradleAndroid元件化
- Android 基礎知識課程助您輕鬆構建應用Android
- 讓Gradle放飛你的apk構建GradleAPK
- webgl值得重視的基礎構建Web
- 使用gradle構建springboot專案GradleSpring Boot
- Gradle系列(一) Groovy 基礎Gradle
- OrangeBusinessServices助力汽車製造商寶沃構建數字化基礎架構架構
- Gradle更小、更快構建APP的奇淫技巧GradleAPP
- 使用cordova構建基於vue的Android專案VueAndroid
- Gradle快速構建Spring Boot專案GradleSpring Boot
- 在gradle中構建java專案GradleJava
- Gradle 之語言基礎 GroovyGradle