簡介
Android Studio預設使用Gradle作為建構工具,不像Ant那樣基于XML,取而代之的是采用基于Groovy的DSL(Domain Specific Language)。
Gradle建構工具是任務驅動型的建構工具,并且可以通過各種Plugin擴充功能以适應各種建構任務。
采用約定優于配置的原則,最簡單方式是使用一個預設的目錄結構。當然目錄結構是可以自己修改的。
Gradle Build Files
建立一個Android Studio項目時,會預設生成以下Gradle相關檔案。
Project級别的build.gradle檔案
buildscript {
//編譯Gradle腳本過程中需要的依賴關系.//
repositories {
jcenter()
}
//選擇JCenter repository.//
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
//腳本依賴Android plugin for Gradle 1.2.3//
}
}
allprojects {
//你應用的依賴關系.//
repositories {
jcenter()
}
}
//應用依賴jCenter repository.//
Module級别的build.gradle檔案
apply plugin: 'com.android.application'
//引入Android App插件.//
android {
//下面的部配置設定置Android App相關的資訊.//
compileSdkVersion
//編譯的SDK版本.//
buildToolsVersion "21.1.1"
//Build Tools版本,最好選擇版本号大于或等于compileSdkVersion的.//
defaultConfig {
applicationId "com.example.jessica.myapplication"
//application’s ID. 舊版本是 ‘packageName’.//
minSdkVersion
//需要的最小API版本.//
targetSdkVersion
//應用運作的API版本.//
versionCode
versionName "1.0"
}
buildTypes {
release {
//‘BuildTypes’ 控制你App如何編譯打包. 如果你想建立你自己的 build variants, 添加到這裡.//
minifyEnabled true
//是否進行混淆.//
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
//混淆配置.//
}
}
}
dependencies {
//當然Module需要的依賴關系.//
compile fileTree(dir: 'libs', include: ['*.jar'])
//依賴編譯app/libs.//
compile 'com.android.support:appcompat-v7:21.0.3'
//依賴編譯遠端庫.//
}
Other Gradle Files
gradle-wrapper.properties (Gradle Version)
wrapper相關配置檔案:當其他人編譯你的項目時,即使他們沒有安裝gradle,使用./gradlew相關指令時,這個檔案會檢查正确版本的gradle是否被安裝,如有必要會幫你下載下傳正确的版本。下面會詳細講wrapper。
distributionBase=GRADLE_USER_HOME
//決定解壓後的Gradle包是存儲到工程目錄下, 還是存儲到Gradle user home directory.
//(對于Unix machines, Gradle user home directory預設在 ~/.gradle/wrapper.)
//如果是PROJECT則zip會解壓到該工程目錄下
distributionPath=wrapper/dists
//解壓後的Gradle包存放的具體路徑.//
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
//下載下傳的Gradle zip包所放置的目錄//
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
//Gradle的下載下傳位址.//
settings.gradle
該檔案組合你所有想建構的module。
gradle.properties (Project Properties)
這個檔案包含整個project的配置資訊。預設是空檔案,你可以添加各種屬性值到這個檔案,build.gradle中可以引用之。
local.properties (SDK Location)
這個檔案告訴Android Gradle plugin你的Android SDK安裝在哪:
sdk.dir=/Users/jessica/Library/Android/sdk
由于這是你本地的SDK路徑,是以這個檔案不應該加入版本控制中。
The Gradle Wrapper
Android Studio建立項目時都建議使用Gradle Wrapper來建構,這不是必須的,直接指定你本地的安裝的Gradle也行。
用wrapper的好處是當别人參與到該項目時,無須事先本地安裝Gradle或者Android Studio,當運作./gradlew相關的指令時,wrapper會檢查本地相應目錄下是否已經有對應版本的Gradle,如果沒有會幫你下載下傳正确的版本。還有對于一些持續內建的測試伺服器,不一定是安裝了Gradle的,這時候使用wrapper就能避免重新配置伺服器。
如果你想将Gradle項目轉換成基于Gradle Wrapper的,隻需要簡單的跑一下gradle wrapper即可,也可以加上–gradle-version 2.4選項來指定一個gradle的版本,–gradle-distribution-url選項指定了從哪兒下載下傳gradle,如果沒有任何選項,則會從Gradle repository下載下傳你運作wrappertask的gradle版本。你也可以将wrapper這個task寫入你的build.gradle檔案:
task wrapper(type: Wrapper) {
gradleVersion = '2.4'
}
wrappertask會在你的項目根目錄下生成如下檔案:
sample/
gradlew
gradlew.bat
gradle/wrapper/
gradle-wrapper.jar
gradle-wrapper.properties
這些檔案是都應該加入到版本控制中的。
如果你想更改Gradle版本,可以直接修改gradle-wrapper.properties檔案:
distributionUrl=https\://services.gradle.org/distributions/gradle--all.zip
或者再跑一下wrappertask重新生成這些檔案,因為wrapper腳本可能會有更新。
使用wrapper的話會忽略你本機已經安裝的gradle。
檔案可在http://services.gradle.org/distributions/找到最新版本。
關于Build variants
Build variants是product flavors和build types的組合。
buildTypes {
debug {
debuggable true
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
demo {
applicationId "me.zircon.test.demo"
versionName "1.0-demo"
}
full {
applicationId "me.zircon.test.full"
versionName "1.0-full"
}
}
上面的片段會組合成4種variants:demoDebug,demoRelease,fullDebug,fullRelease。
Android Studio正常左下角有一個Build Variants的面闆,裡面可以選擇你最終想編譯的版本,當選擇run一個子產品時,就是編譯的這裡選擇的版本。也可以通過指令行./gradlew assemble來編譯,編譯出的apk可以在app/build/outputs/apk裡找到,格式是app--.apk。 也有利用productFlavors來打管道包的例子。可見這篇文章。
Source Sets
我們可以在src下建立多個source set:
每一個set代表一個flavor或者build type,main set所有variants都會用到。在編譯某個variants時會選擇相應set中的src和res。比如assembleDemoDebug,會組合main,demo和debug set。對于res和manifest檔案,内容會合并,如果有重名字段的,其合并優先級從低到高是:libraries/dependencies -> main src -> productFlavor -> buildType。對于src,組合成variants的set中不能存在重名檔案,即demo和Debug中不能同時存在一個A.java,但是Debug和Release中可以同時有。 當然我們也可以通過腳本中的sourceSets{ }配置目錄結構。 特别對于非約定目錄結構的工程(比如Eclipse工程),通過sourceSets{ }加以配置以便Gradle識别:
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
demo {
...
}
instrumentTest.setRoot('tests')
}
關于dependencies
dependencies一般有三種形式:
- Module Dependencies
compile project(":lib")
- Local Dependencies
compile fileTree(dir: 'libs', include: ['*.jar'])
- Remote Dependencies
對于Remote Dependencies,書寫的格式一般是group:name:version,這個網址可以幫你在Maven Central搜尋lib并生成dependencies。
jcenter 和 Maven Central
Gradle會自動從repositories{…}幫你下載下傳編譯Remote Dependencies。
舊版本的Android Studio預設生成的repositories{ }是Maven Central,而新版本已經變成jcenter。這兩者都是互相獨立的lib倉庫,由不同的廠商托管,相較之下,jcenter有以下優勢:
- jcenter對開發者是友好的,上傳自己的lib到jcenter很友善
- jcenter利用CDN加速,是以下載下傳lib更快
- jcenter類庫更全,可以認為是Maven Central的超類
并不是所有類庫都host在jcenter或者Maven Central上,有些是host在自己的Maven倉庫中,比如我們項目中所使用的twitter的crashlytics庫,它host在twitter自己的倉庫中:
repositories {
maven { url 'https://maven.fabric.io/public' }
}
關于如何将自己的類庫上傳到jcenter可以參考 這篇文章。
Gradle的一些概念
我們回過頭來看看Gradle的一些概念。
Gradle腳本基于Groovy。每一個Gradle腳本執行時都會配置一種類型的對象。比如執行build.gradle會建立并配置一個Project類型的對象,而settings.gradle則配置Settings對象。相應的這個類型中的屬性和方法可以直接用在腳本中,如:file(…)傳回路徑的File對象;println name則列印該project的name。
腳本裡可以使用任何Groovy/Java的文法。比如解析AndroidManifest檔案取得VersionName:
def manifestVersionName() {
def manifestFile = file(project.projectDir.absolutePath + '/src/main/AndroidManifest.xml')
def ns = new groovy.xml.Namespace("http://schemas.android.com/apk/res/android", "android")
def xml = new XmlParser().parse(manifestFile)
return xml.attributes()[ns.versionName].toString()
}
Project
Gradle裡面的Project的概念可以了解成Android Studio中的Module的概念,Project是指我們的建構産物(比如Jar包)或實施産物(将應用程式部署到生産環境)。一個項目可以包含一個或多個任務。
Task
Project由一個或多個Task組成,每一個Task代表了一連串原子性的操作。在Android Studio右邊的Gradle面闆或者輸入指令./gradlew tasks都能檢視目前項目所有的Task。 我們也可以用多種方式來建立一個task:
task myTask
task myTask { configure closure }
task myType << { task action }
task myTask(type: SomeType)
task myTask(type: SomeType) { configure closure }
Plugin
在Gradle中,所有有用的特性都是由Plugin來提供的。添加Plugin到Gradle中其實就是添加了一些新的task,域對象(如SourceSet),約定(如Java source預設放在src/main/java下),同時也會擴充一些已經存在的類型。 Plugin分兩種:腳本插件apply from: ‘other.gradle’和二進制插件apply plugin: ‘java’。
Refs
https://docs.gradle.org/current/userguide/userguide.html
http://tools.android.com/tech-docs/new-build-system
http://developer.android.com/sdk/installing/studio-build.html
本文轉自http://www.zircon.me/06-25-2015/about-gradle.html,部分改動。