詳解Android中的build.gradle檔案
一、什麼是Gradle
簡單的說,Gradle是一個構建工具,它是用來幫助我們構建app的,構建包括編譯、打包等過程。我們可以為Gradle指定構建規則,然後它就會根據我們的“命令”自動為我們構建app。Android Studio中預設就使用Gradle來完成應用的構建。有些同學可能會有疑問:”我用AS不記得給Gradle指定過什麼構建規則呀,最後不還是能搞出來個apk。“ 實際上,app的構建過程是大同小異的,有一些過程是”通用“的,也就是每個app的構建都要經歷一些公共步驟。因此,在我們在建立工程時,Android Studio自動幫我們生成了一些通用構建規則,很多時候我們甚至完全不用修改這些規則就能完成我們app的構建。
有些時候,我們會有一些個性化的構建需求,比如我們引入了第三方庫,或者我們想要在通用構建過程中做一些其他的事情,這時我們就要自己在系統預設構建規則上做一些修改。這時候我們就要自己向Gradle”下命令“了,這時候我們就需要用Gradle能聽懂的話了,也就是Groovy。Groovy是一種基於JVM的動態語言,關於它的具體介紹,感興趣的同學可以文末參考”延伸閱讀“部分給出的連結。
我們在開頭處提到“Gradle是一種構建工具”。實際上,當我們想要更靈活的構建過程時,Gradle就成為了一個程式設計框架——我們可以通過程式設計讓構建過程按我們的意願進行。也就是說,當我們把Gradle作為構建工具使用時,我們只需要掌握它的配置指令碼的基本寫法就OK了;而當我們需要對構建流程進行高度定製時,就務必要掌握Groovy等相關知識了。限於篇幅,本文只從構建工具使用者的角度來介紹Gradle的一些最佳實踐,在文末“延伸閱讀”部分給出了幾篇高質量的深入介紹Gradle的文章,其中包含了Groovy等知識的介紹。
二、Gradle的基本組分
Project與Task 在Gradle中,每一個待構建的工程是一個Project,構建一個Project需要執行一系列Task,比如編譯、打包這些構建過程的子過程都對應著一個Task。具體來說,一個apk檔案的構建包含以下Task:Java原始碼編譯、資原始檔編譯、Lint檢查、打包以生成最終的apk檔案等等。
外掛 外掛的核心工作有兩個:一是定義Task;而是執行Task。也就是說,我們想讓Gradle能正常工作,完成整個構建流程中的一系列Task的執行,必須匯入合適的外掛,這些外掛中定義了構建Project中的一系列Task,並且負責執行相應的Task。 在新建工程的app模組的build.gradle檔案的第一行,往往都是如下這句: apply plugin: 'com.android.application' 這句話的意思就是應用“com.android.application“這個外掛來構建app模組,app模組就是Gradle中的一個Project。也就是說,這個外掛負責定義並執行Java原始碼編譯、資原始檔編譯、打包等一系列Task。實際上"com.android.application"整個外掛中定義瞭如下4個頂級任務:
assemble: 構建專案的輸出(apk) check: 進行校驗工作 build: 執行assemble任務與check任務 clean: 清除專案的輸出 當我們執行一個任務時,會自動執行它所依賴的任務。比如,執行assemble任務會執行assembleDebug任務和assembleRelease任務,這是因為一個Android專案至少要有debug和release這兩個版本的輸出。
- Gradle配置檔案
我們在Android Studio中新建一個工程,可以得到如下的工程結構圖: 上面我們說過,Android Studio中的一個Module即為Gradle中的一個Project。上圖的app目錄下,存在一個build.gradle檔案,代表了app Module的構建指令碼,它定義了應用於本模組的構建規則。我們可以看到,工程根目錄下也存在一個build.gradle檔案,它代表了整個工程的構建,其中定義了適用於這個工程中所有模組的構建規則。
接下來我們介紹一下上圖中其他幾個Gradle配置檔案:
gradle.properties: 從它的名字可以看出,這個檔案中定義了一系列“屬性”。實際上,這個檔案中定義了一系列供build.gradle使用的常量,比如keystore的儲存路徑、keyalias等等。
gradlew與gradlew.bat: gradlew為Linux下的shell指令碼,gradlew.bat是Windows下的批處理檔案。gradlew是gradle wrapper的縮寫,也就是說它對gradle的命令進行了包裝,比如我們進入到指定Module目錄並執行“gradlew.bat assemble”即可完成對當前Module的構建(Windows系統下)。
local.properties: 從名字就可以看出來,這個檔案中定義了一些本地屬性,比如SDK的路徑。
settings.gradle: 假如我們的專案包含了不只一個Module時,我們想要一次性構建所有Module以完成整個專案的構建,這時我們需要用到這個檔案。比如我們的專案包含了ModuleA和ModuleB這兩個模組,則這個檔案中會包含這樣的語句:include ':ModuleA', ':ModuleB'。
- 構建指令碼
首先我們來看一下工程目錄下的build.gradle,它指定了真個整個專案的構建規則,它的內容如下:
buildscript { repositories { jcenter() //構建指令碼中所依賴的庫都在jcenter倉庫下載 } dependencies { //指定了gradle外掛的版本 classpath 'com.android.tools.build:gradle:1.5.0' } }
allprojects { repositories { //當前專案所有模組所依賴的庫都在jcenter倉庫下載 jcenter() } }
我們再來簡單介紹下app模組的build.gradle的內容:
//載入用於構建Android專案的外掛 apply plugin: 'com.android.application'
android { //構建Android專案使用的配置 compileSdkVersion 23 //指定編譯專案時使用的SDK版本 buildToolsVersion "23.0.1" //指定構建工具的版本
defaultConfig {
applicationId "com.absfree.debugframwork" //包名
minSdkVersion 15 //指定支援的最小SDK版本
targetSdkVersion 23 //針對的目標SDK版本
versionCode 1
versionName "1.0"
}
buildTypes { //針對不同的構建版本進行一些設定
release { //對release版本進行的設定
minifyEnabled false //是否開啟混淆
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' //指定混淆檔案的位置
}
}
}
dependencies { //指定當前模組的依賴 compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.1.1' compile 'com.android.support:design:23.1.1' }
三、常見配置
整個工程的build.gradle通常不需我們改動,這裡我們介紹下一些對模組目錄下build.gradle檔案的常見配置。
- 依賴第三方庫
當我們的專案中用到了了一些第三方庫時,我們就需要進行一些配置,以保證能正確匯入相關依賴。設定方法很簡單,比如我們在app模組中中用到了Fresco,只需要在build.gradle檔案中的dependencies塊新增如下語句:
dependencies { ... compile 'com.facebook.fresco:fresco:0.11.0' }
這樣一來,Gradle會自動從jcenter倉庫下載我們所需的第三方庫並匯入到專案中。
- 匯入本地jar包
在使用第三方庫時,除了像上面那樣從jcenter倉庫下載,我們還可以匯入本地的jar包。配置方法也很簡單,只需要先把jar檔案新增到app\libs目錄下,然後在相應jar檔案上單擊右鍵,選擇“Ad As Library”。然後在build.gradle的dependencies塊下新增如下語句:
compile files('libs/xxx.jar') 實際上我們可以看到,系統為我們建立的build.gradle中就已經包含了如下語句:
compile fileTree(dir: 'libs', include: ['*.jar'])
這句話的意思是,將libs目錄下的所有jar包都匯入。所以實際上我們只需要把jar包新增到libs目錄下並“Ad As Library"即可。
- 依賴其它模組
假設我們的專案包含了多個模組,並且app模組依賴other模組,那麼我們只需app\build.gradle的denpendencies塊下新增如下語句:
compile project(':other')
- 構建輸出為aar檔案
通常我們構建的輸出目標都是apk檔案,但如果我們的當前專案時Android Library,我們的目標輸出就是aar檔案。要想達到這個目的也很容易,只需要把build.gradle的第一句改為如下:
apply plugin:'com.android.library' 這話表示我們使用的外掛不再是構建Android應用的外掛,而是構建Android Library的外掛,這個外掛定義並執行用於構建Android Library的一系列Task。
- 自動移除不再使用的資源
只需進行如下配置:
android { ... } buildTypes { release { ... shrinkResources true ... } } }
- 忽略Lint錯誤
在我們構建Android專案的過程中,有時候會由於Lint錯誤而終止。當這些錯誤來自第三方庫中時,我們往往想要忽略這些錯誤從而繼續構建程序。這時候,我們可以只需進行如下配置:
android { ... lintOptions { abortOnError false } }
- 整合簽名配置
在構建release版本的Android專案時,每次都手動匯入簽名檔案,鍵入密碼、keyalias等資訊十分麻煩。通過將簽名配置整合到構建指令碼中,我們就不必每次構建發行版本時都手動設定了。具體配置如下:
signingConfigs { myConfig { //將"xx"替換為自己的簽名檔案資訊 storeFile file("xx.jks") storePassword "xx" keyAlias "xx" keyPassword "xx" } } android { buildTypes { release { signingConfig signingConfigs.myConfig //在release塊中加入這行 ... } } ... }
真實開發中,我們不應該把密碼等資訊直接寫到build.gradle中,更好的做法是放在gradle.properties中設定:
RELEASE_STOREFILE=xxx.jks RELEASE_STORE_PASSWORD = xxx RELEASE_KEY_ALIAS=xxx RELEASE_KEY_PASSWORD=xxx
然後在build.gradle中直接引用即可:
signingConfigs { myConfig { storeFilefile(RELEASE_STOREFILE) storePassword RELEASE_STORE_PASSWORD keyAlias RELEASE_KEY_ALIAS keyPassword RELEASE_KEY_PASSWORD } }
關於Gradle的其他配置方法大家可以參考“延伸閱讀”部分的“Gradle最佳實踐”。
四、延伸閱讀
這篇文章主要從使用者的角度介紹了Gradle在使用過程中的最佳實踐,同樣非常精彩。