Gradle 配置詳解
前面我們一起學習了 Groovy 語言的語法基礎,再由淺入深從 Gradle 的環境變量配置,到創建一個簡單的 Gradle 項目。今天這節課我們為大家介紹一下 Android 項目中 Gradle 的配置。
1. AndroidStudio 項目結構
我們介紹 AndroidStudio 中 Android 項目的 Gradle 配置之前,我們先來看下 AndroidStudio 中 Android 項目的結構,我們新建一個項目結構大致如下圖所示:
我們通過上面的圖片可以看到,Android 項目中跟 Gradle 相關的主要有 7 個部分:
- 根目錄下的 build.gradle: 頂級構建文件,配置 Gradle 版本和 Maven 依賴;
- app 目錄下的 build.gralde文件: app 打包和簽名配置,及模塊的依賴;
- gradle 文件夾: 配置 gradel-wrapper;
- setting.gradle 文件: 添加編譯的所有模塊;
- gradle.projects 文件: 項目范圍的梯度設置,編譯內存,Gradle 并發性等設置。;
- gradlew 和 gradlew.bat 文件: Gradle 啟動腳本文件;
- .gradle 文件夾: 編譯時的緩存文件夾。
這幾個部分各自負責的功能都不盡相同。下面我們來看下它們具體的功能。
2. 根目錄下的 build.gradle 文件
這個文件是我們創建 Android 項目的時候自動生成的,它是頂級構建文件,我們可以在其中添加所有子項目/模塊共有的配置選項。我們來看下這個文件:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
//頂級構建文件,您可以在其中添加所有 子項目/modules 共有的配置選項
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
//注意:不要將您的應用程序依賴項放在這里; 它們屬于單獨的模塊 build.gradle 文件
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
以上就是我們每創建一個 Android 項目,項目根目錄下的 build.gradle 文件的代碼,也就是頂級構建文件的代碼。下面來分開講解一下每個閉包:
2.1 buildscript{} 閉包
首先我們先看下上面的buildscript
閉包,這個閉包里是配置 Gradle 腳本執行所需要的的依賴,分別是對應 Maven 倉庫和構建工具 Gradle 的版本。
2.1.1 repositories{} 閉包
這個閉包里面主要是配置遠程的 Maven 倉庫地址。我們看到里面聲明了jcenter()
和google()
,這兩個都是 maven 倉庫,上面托管了很多開源項目,依賴了這個我們就可以引用上面的開源項目了。比如 Android 中的 V7,V4 包等。
2.1.2 dependencies{} 閉包
這個閉包我們直接看,就應該能猜到是配置項目構建工具 Gradle 的版本的,classpath 就是聲明一個插件 Gradle來構建項目。dependencies
雖然是依賴的意思,但是我們這里需要注意:不能將應用程序的依賴放在這里,應用程序的依賴在單獨的build.gradle
里面。
2.2 allprojects{} 閉包
這個閉包里面的是我們項目運行所需要的的依賴,往往和上面的repositories
是相對應的。
buildscript {
repositories { //注釋1
maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
//注意:不要將您的應用程序依賴項放在這里; 它們屬于單獨的模塊build.gradle文件
}
}
allprojects {
repositories { //注釋2
maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
這里我們需要注意代碼中的注釋1和注釋2處的 repositories
閉包,往往我們添加一個 maven 庫的依賴時,需要兩個閉包中都添加一遍。
Tips: 我們添加 Maven 庫時可以需要兩個都添加,比如國外 Maven 訪問太慢,我們可以加入國內阿里云的 Maven 庫。
2.3 clean任務
我們前面講到 Gradle 是基于任務的,這里的clean
它是一個 Gradle 任務,它繼承自Delete
,我們點擊clean Project
或是執行gradle clean
命令的時候就是在執行這個任務,它的任務內容是刪除build
文件夾下的內容。
3. app目錄下的 build.gradle 文件
這個我們直接看文件內容吧:
//注釋1
apply plugin: 'com.android.application'
//注釋2
android {
compileSdkVersion 28
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.bthvi.myuiapplication"
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
//注釋3
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
上面的文件就是 app 模塊下的 build.gradle 文件,我們看到主要是分三個部分,注釋1,注釋2,注釋3分別對應如下三個語句和閉包:
apply plugin
語句android
閉包dependencies
閉包
3.1 apply plugin
這句是文件中的 第一行,表示的意思是在這個模塊應用一個插件,插件的值有以下 2 種:
- com.android.application:如果是這個值,則代表這個模塊是一個Android應用程序,可以獨立運行,生成
apk
文件。 - com.android.library:如果是這個值,代表這個模塊是一個Android model,不能夠獨立運行,必須依附于application才能運行,項目構建后生成的是一個
aar
文件。
Tips:
apply plugin: ‘com.android.application’ 表示這是一個應用程序模塊
apply plugin: ‘com.android.library’ 標識這是一個模塊module
區別: 前者可以直接運行,后者是需要依附在應用程序上運行的
3.2 android閉包
這個閉包主要是配置我們打包的一些信息,包括包名,版本號,版本名稱,混淆配置,簽名信息等。
下面我們詳細介紹下:
- compileSdkVersion: 設置編譯時的 Android 版本。
- buildToolsVersion: 設置編譯時構建工具的版本。
3.2.1 defaultConfig{}閉包:
這個閉包里主要是設置包的一些基本信息,如包名,版本號等。
- applicationId: 設置打包后的 APK 的包名。
- minSdkVersion: 設置 apk 最低的支持 Android 版本,如果手機的 Android 系統版本低于這個值,app 一般無法安裝。
- targetSdkVersion: 設置項目的目標版本,表示應用程序在該版本上已經做過充分的測試,系統會為該應用啟動一些對應該目標系統的最新功能特性。
Tips: Android系統的行為變更,只有 targetSdkVersion 的值設置為大于或等于該手機系統的 API 版本時,才會生效。例如,設置 targetSdkVersion 為 28,對應為 Android 系統版本為 9.0,在 Android 10.0(對應 targetSdkVersion 為 29)系統的手機上,Android 10.0 擁有的新特性[如外存中私有目錄權限變更等功能]就不會被啟用。
- versionCode: 設置 APK 包的版本號,一般情況每次打包都要 +1,否則會無法覆蓋安裝。
- versionName: 表示版本名稱,展示在 APP 的關于里面或是應用市場上。
- testInstrumentationRunner: 設置單元測試,
android.support.test.runner.AndroidJUnitRunner
表明是要使用AndroidJUnitRunner
進行單元測試。
- versionCode: 設置 APK 包的版本號,一般情況每次打包都要 +1,否則會無法覆蓋安裝。
- versionName: 表示版本名稱,展示在 APP 的關于里面或是應用市場上。
- testInstrumentationRunner: 設置單元測試,
android.support.test.runner.AndroidJUnitRunner
表明是要使用AndroidJUnitRunner
進行單元測試。
3.2.2 buildTypes{}閉包:
這個閉包主要是配置我們打包的,一般包含兩個閉包release
和debug
分別對應的是打Release
包還是Debug
包。所謂Debug
包就是我們直接運行的包,這個包的配置新建項目時是省略沒有寫的。
buildTypes {
release {// 生產包配置
minifyEnabled true//是否混淆
shrinkResources true//是否啟用未使用資源的收縮
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//指定混淆的規則文件
signingConfig signingConfigs.release//設置簽名信息
zipAlignEnabled true//是否對APK包執行ZIP對齊優化,減小zip體積
renderscriptOptimLevel 5 //指定RenderScript的編譯優化等級,一般設置為3
}
debug {// 開發配置
minifyEnabled false//是否混淆
shrinkResources false//是否啟用未使用資源的收縮
signingConfig signingConfigs.release//設置簽名信息
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//指定混淆的規則文件
zipAlignEnabled true//是否對APK包執行ZIP對齊優化,減小zip體積
renderscriptOptimLevel 5
}
}
從上面的代碼中我們可以看到release
和debug
的配置基本差不多。關于每個字段的具體的意義上面注釋中有寫,下面就不多做說明了。我們下面主要看下signingConfig
這個字段,這個是設置 APP 的簽名信息的。
//簽名
signingConfigs {
//你自己的keystore信息
releaseConfig {
storeFile file(rootProject.ext.store_file)
storePassword rootProject.ext.store_password
keyAlias rootProject.ext.key_alias
keyPassword rootProject.ext.key_password
v1SigningEnabled true
v2SigningEnabled true
}
}
Tips: 簽名信息設置
signingConfig
閉包是在最外層的,也就是和buildTypes
閉包是在同一層級的。千萬不要把它放在buildTypes
閉包里面。
3.2.3 dependencies 閉包
這個閉包是項目運行所需要的依賴。如我們需要引用的本地 libs 目錄下的第三方的 jar 包或是 aar 包,還可以是 maven 庫里面的第三方的開源庫 [如 support-v4 support-v7 包等]。
Tips: 這里我們要和最外層的
build.gradle
文件的dependencies
閉包區分開來。這里的 dependencies 閉包是配置項目運行時引入的第三方庫。而最晚層的文件中的 dependencies 閉包是配置構建項目時的 Gradle 的版本。
4. gradle文件夾
gradle 文件夾主要是配置 gradle-wrapper 的,我們看到它的目錄下有個wrapper
目錄,下面有gradle-wrapper.jar
和gradle-wrapper.properties
兩個文件。
下面我們看下gradle-wrapper.properties
文件的內容,我們會發現它是配置 Gradle 版本的。看著毫不起眼,但是它卻非常重要,關于它的詳細介紹我們下一節會做詳細的講解。
#Sat Nov 09 17:54:23 CST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
5. setting.gradle 文件
這個文件其實非常簡單,就是配置項目的模塊的,有幾個模塊就在 setting.gradle 文件里面添加它們的名字就行了。默認創建只有app
在里面:
include ':app'
//如果,我們的項目中有person,common,home等模塊時,可以這樣引入
include ':app',':person',':common',':home'
6. gradle.projects 文件
這個文檔一般我們在日常開發中不需要去動它,這個文檔主要是項目范圍的梯度設置,通過 AndroidStudio 配置的漸變設置將覆蓋此文件中指定的任何設置。
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1024m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
通過上面的代碼我們看到主要有一句沒有注釋,第 9 行,這句的作用就是設置運行時的最大內存。
Tips: 這里分享一個經驗,如果你的電腦編譯項目耗時比較久,我們可以修改這個文件的配置,適當增加編譯時的內存,使 Gradle 獨立運行。筆者親測有效:第11、12行。
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# 提高AndroidStudio的并發性,使Gradle獨立運行。
org.gradle.parallel=true
org.gradle.daemon=true
7. gradlew 和 gradlew.bat 文件
這兩個文件其實就是 Gradle 啟動的腳本文件,我們可以使用gradlew
命令來打包相當于gradle
命令。關于gradle
的命令我們后面有一節專門介紹。這節我們看下這兩個文件的區別,以及怎么使用gradlew
命令。
下面我們看看這兩個文件的前面幾行:
gradlew 文件
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
gradlew.bat 文件
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
通過上面的注釋我們可以看到,原來這兩個文件的作用是你一樣的,都是 Gradle 啟動的腳本文件,不過gradlew
文件是 Linux 系統或是 Unix 系統的腳本文件,而gradlew.bat
是 Windows 系統的腳本文件。
使用 gradlew 命令,以 clean 命令為例,我們只需要在 AndroidStudio下輸入如下命令:
//Windows系統
gradlew clean
//Linux系統或是Mac系統
./gradlew clean
Tips: 我們可能在 MAC 或是 Linux 系統中遇到
bash: ./gradlew: Permission denied
這個錯誤,這是因為沒有權限。我們只需要執行chmod +x gradlew
這個命令后,再執行./gradlew clean
命令就 OK 了。
8. .gradle 文件夾
這個文件其實我們不用太在意它,這個文件夾是項目構建的一個緩存的目錄。只要我們打開一個 Android 項目,它就會生成這個文件夾。是一個臨時的文件夾。
9. 小結
本節我們主要為大家介紹了 AndroidStudio 中 Android 項目的結構,及相關 Gradle 知識的詳解。我們回顧一下前面所說的 7 個文件的作用:
- 根目錄下的 build.gradle: 頂級構建文件,配置 Gradle 版本和 Maven 依賴;
- app 目錄下的 build.gralde文件: app 打包和簽名配置,及模塊的依賴;
- gradle 文件夾: 配置 gradel-wrapper;
- setting.gradle 文件: 添加編譯的所有模塊;
- gradle.projects 文件: 項目范圍的梯度設置,編譯內存,Gradle 并發性等設置;
- gradlew 和 gradlew.bat 文件: Gradle 啟動腳本文件;
- .gradle 文件夾: 編譯時的緩存文件夾。