1.介紹
如果你正在查閱build.gradle文件的所有可選項(xiàng),請(qǐng)點(diǎn)擊這里進(jìn)行查閱:DSL參考
1.1新構(gòu)建系統(tǒng)的特性
gradle構(gòu)建系統(tǒng)具有如下的特點(diǎn):
- 易于代碼和資源復(fù)用
- 易于創(chuàng)建應(yīng)用的版本,例如發(fā)布多apk以及應(yīng)用的不同渠道版本
- 構(gòu)建過程易于配置羞延,擴(kuò)展和優(yōu)化
- 良好的IDE整合
1.2為什么使用Gradle玻淑?
Gradle既是一個(gè)先進(jìn)的構(gòu)建系統(tǒng)摊欠,也是一個(gè)允許通過插件創(chuàng)建自定義構(gòu)建邏輯的構(gòu)建工具集谨履。以下是一些我們?yōu)槭裁催x擇Gradle的原因:
- 用于描述和操作構(gòu)建邏輯的,基于Groovy的特定領(lǐng)域語言(DSL)
- 基于Groovy的構(gòu)建文件,允許混合通過使用DSL的聲明式元素以及使用代碼去操作DSL元素來提供自定義邏輯探入。
- 通過Maven或者Ivy的內(nèi)置依賴管理
- 非常靈活狡孔。
- 插件能夠?qū)С鲎约旱腄SL以及自己的API,用于使用構(gòu)建文件
- 支持IDE整合的良好工具API
1.3要求
- Gradle 2.2
- SDK版本19.0.0及以上蜂嗽,一些特性可能會(huì)需要更新的版本
2.基礎(chǔ)項(xiàng)目搭建
一個(gè)Gradle項(xiàng)目在一個(gè)文件中描述了該項(xiàng)目的構(gòu)建情況苗膝,該文件被稱為build.gradle,位于項(xiàng)目的根目錄植旧。(點(diǎn)擊這里查看構(gòu)建系統(tǒng)概述)
2.1簡(jiǎn)單的構(gòu)建文件
大多數(shù)簡(jiǎn)單的Android項(xiàng)目擁有如下的build.gradle文件:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.1'
}
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.1.0"
}
在Android的構(gòu)建文件中荚醒,有以下三個(gè)主要區(qū)域:
buildscript{…}
用于配置用于構(gòu)建的代碼。在上面的例子中隆嗅,聲明使用jCenter庫(kù)界阁,并且有一個(gè)依賴于Maven類路徑的Maven Artifact。該Artifact是包含包含Android構(gòu)建插件的1.3.1版本Gradle胖喳。
上例中的Artifact僅僅影響到構(gòu)建代碼的運(yùn)行泡躯,并不作用于代碼項(xiàng)目。至于項(xiàng)目本身需要聲明自己的庫(kù)和依賴關(guān)系,該部分將會(huì)在下文介紹较剃。
之后咕别,該構(gòu)建文件應(yīng)用了com.android.application插件。該插件用于構(gòu)建Android應(yīng)用写穴。
最后android{…}
中配置了所有用于Android應(yīng)用構(gòu)建的參數(shù)惰拱。這里是Android特定領(lǐng)域語言(DSL)的入口點(diǎn)。默認(rèn)情況下啊送,僅僅編譯目標(biāo)(compilation target)和構(gòu)建工具版本(version of the build-tool)是必備的偿短。也就是上例中的compileSdkVersion屬性和buildtoolsVersion屬性。該編譯目標(biāo)和舊版本的project.properties文件中的target屬性是相同的馋没。新版本中既可以指定一個(gè)整型(即API level)昔逗,也可以使用表示相同值的字符串對(duì)compileSdkVersion進(jìn)行指定。
重點(diǎn):你應(yīng)當(dāng)使用com.android.application插件篷朵,使用java插件會(huì)導(dǎo)致錯(cuò)誤勾怒。
注意1:另外,你也需要一個(gè)local.properties文件声旺,設(shè)置sdk.dir去配置本地的SDK路徑位置笔链。
注意2:另外,你也可以設(shè)置名為ANDROID_HOME
的環(huán)境變量腮猖。 這兩者并沒有什么區(qū)別卡乾,你可以選擇任意一種。例如:sdk.dir=/path/to/Android/Sdk
2.2項(xiàng)目結(jié)構(gòu)
上面例子的基本構(gòu)建文件預(yù)期了一個(gè)默認(rèn)的文件夾結(jié)構(gòu)缚够。Gradle遵循“約定優(yōu)于配置”的概念朱庆,盡可能提供良好的默認(rèn)項(xiàng)值抑诸〗遥基本項(xiàng)目由兩個(gè)被稱為代碼集(source sets)的部分構(gòu)成界赔,一個(gè)是主要的源代碼,另一個(gè)是測(cè)試代碼雏吭。它們各自位于:
src/main
src/androidTest
在這些目錄里锁施,每一個(gè)資源組件都有各自的子目錄。對(duì)于Java和Android插件杖们,java源代碼和java資源的路徑位置為:
java/
resources/
對(duì)于Android插件而言悉抵,有如下特定的文件和目錄:
AndroidManifest.xml
res/
assets
aidl/
rs/
jni/
jniLibs/
這意味著主資源集中的所有*.java
文件位于src/main.java
中,主清單文件(main manifest)位于src/main/AndroidManifest.xml
摘完。
注意:
src/androidTest/AndroidManifest.xml
由于會(huì)自動(dòng)創(chuàng)建姥饰,因此并不是必須手動(dòng)編寫的。
2.2.1配置結(jié)構(gòu)
當(dāng)默認(rèn)的項(xiàng)目結(jié)構(gòu)并不完善時(shí)孝治,可能需要進(jìn)行配置列粪。本部分只介紹Android項(xiàng)目結(jié)構(gòu)的配置审磁,關(guān)于純java項(xiàng)目的項(xiàng)目結(jié)構(gòu)配置,請(qǐng)參閱:gradle documentation岂座。
Android插件使用和純java項(xiàng)目相同的語法态蒂,但是由于其使用自己的資源集,項(xiàng)目的配置由android{...}
代碼塊完成费什。例如钾恢,舊的項(xiàng)目結(jié)構(gòu)(Eclipse)中對(duì)主代碼和測(cè)試代碼進(jìn)行映射:
android {
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
androidTest.setRoot('tests')
}
}
注1: 因?yàn)榕f的結(jié)構(gòu)中在同一個(gè)文件夾中放入所有的資源文件,我們需要對(duì)這些資源集重新進(jìn)行映射,將java代碼鸳址,資源文件等等放入src文件夾瘩蚪。
注2:setRoot()
移動(dòng)整個(gè)資源集和其子文件夾到一個(gè)新的文件夾中,上例將src/androidTest/*
移動(dòng)到tests/*
中氯质,當(dāng)然此處的語句androidTest.setRoot('tests')
只是Android的特性,并不適用于Java的資源集祠斧。
2.3構(gòu)建的任務(wù)
2.3.1通用任務(wù)
在構(gòu)建文件中應(yīng)用插件會(huì)自動(dòng)創(chuàng)建一系列構(gòu)建任務(wù)的集合闻察。Java插件和Android插件都是如此。關(guān)于任務(wù)的約定如下:
- assemble 該任務(wù)用于組合項(xiàng)目的輸出
- check 該任務(wù)用于運(yùn)行所有的的檢測(cè)
- build 該任務(wù)執(zhí)行assemble和check任務(wù)
- clean該任務(wù)清除項(xiàng)目的輸出
任務(wù)assemble琢锋,check以及build并不真正做任何事辕漂。這些插件中的“祖先”任務(wù)用于添加在任務(wù)中真正執(zhí)行的任務(wù)。
這樣吴超,不論當(dāng)前的任務(wù)類型是什么以及何種插件被應(yīng)用钉嘹,都將會(huì)允許你使用執(zhí)行相同的任務(wù)。例如鲸阻,findbugs插件將會(huì)創(chuàng)建一個(gè)一個(gè)新的任務(wù)跋涣,并通過check任務(wù)進(jìn)行依賴,無論什么時(shí)候執(zhí)行調(diào)用該任務(wù)鸟悴,都可以直接使用check任務(wù)陈辱。
在命令行中,你可以通過下面的命令得到高級(jí)別任務(wù):
gradle tasks
查看所有依賴任務(wù)列表可以使用下面的命令:
gradle tasks —all
注意:gradle自動(dòng)顯示任務(wù)已經(jīng)聲明任務(wù)的輸入和輸出情況细诸。
當(dāng)你在沒有變更項(xiàng)目?jī)?nèi)容的情況下再次運(yùn)行構(gòu)建任務(wù)時(shí)沛贪,Gradle將會(huì)報(bào)告所有的任務(wù)已經(jīng)UP-TO-DATE,意味著沒有需要運(yùn)行的任務(wù)震贵。這樣會(huì)使得任務(wù)彼此正確的依賴利赋,而不需要沒必要的構(gòu)建操作。
2.3.2Java項(xiàng)目任務(wù)
以下是由Java插件所創(chuàng)建的猩系,依賴于祖先任務(wù)的最重要的兩個(gè)任務(wù):
-
assemble
jar:創(chuàng)建輸出的任務(wù) -
check
test:運(yùn)行測(cè)試的任務(wù)
jar任務(wù)本身直接或間接依賴于其他任務(wù):例如classes任務(wù)將會(huì)編譯Java代碼媚送。測(cè)試代碼被任務(wù)testClasses所編譯,但是就像classes任務(wù)一樣寇甸,幾乎很少有人會(huì)去調(diào)用季希,因?yàn)閳?zhí)行test任務(wù)即可褪那。
總的來說,你可能應(yīng)當(dāng)僅僅調(diào)用assemble任務(wù)或者check任務(wù)并忽略其他的任務(wù)式塌。你可以點(diǎn)擊這里查看Java插件所有的任務(wù)集合及其描述信息:Java插件的任務(wù)集合
2.3.3Android的任務(wù)
Android插件使用相同的概念來保持和其他插件之間的兼容性博敬,并且,Android插件還添加了額外的祖先任務(wù):
- assemble
- check
- connectedCheck 運(yùn)行check任務(wù)需要一個(gè)連接的設(shè)備或者模擬器峰尝,在所有的連接設(shè)備中偏窝,該任務(wù)將并行執(zhí)行。
- deviceCheck 使用API去連接遠(yuǎn)程設(shè)備武学,用于CI服務(wù)器(持續(xù)集成服務(wù)器)祭往。
- build
- clean
新的祖先任務(wù)是必備的,這是為了能夠在不需要連接設(shè)備的情況下進(jìn)行規(guī)則檢查火窒。請(qǐng)注意硼补,build任務(wù)并不依賴deviceCheck任務(wù)或者connectedCheck任務(wù)。
一個(gè)Android的項(xiàng)目有至少兩個(gè)輸出文件:一個(gè)debug apk文件以及一個(gè)release apk文件熏矿。它們中的每一個(gè)都有其自己的祖先任務(wù)來優(yōu)化構(gòu)建:
- assemble
- assembleDebug
- assembleRelease
assembleDebug和assembleRelease兩者都依賴于其他的多步任務(wù)執(zhí)行來構(gòu)建app文件已骇。assemble任務(wù)依賴于assembleDebug和assembleRelease,可調(diào)用assemble任務(wù)構(gòu)建上述兩種apk票编。
提示: gradle支持駱駝命名法縮寫的形式在命令行中為任務(wù)命名褪储。例如:
gradle aR
和下面的命令相同:
gradle assembleRelease
除非有其他任務(wù)和’aR’重復(fù)。
check任務(wù)有自己的依賴項(xiàng):
-
check
lint
-
connectedCheck
connectedAndroidTest
-
deviceCheck
- 這取決于當(dāng)任務(wù)創(chuàng)建時(shí)慧域,其他插件什么時(shí)候?qū)崿F(xiàn)測(cè)試拓展點(diǎn)鲤竹。
最后,插件創(chuàng)建了安裝了卸載所有構(gòu)建類型的任務(wù)(包括debug昔榴,release和test)辛藻,只要能夠被安裝(需要簽名)。例如:
installDebug
installRelease
-
uninstallAll
uninstallDebug
uninstallRelease
uninstallDebugAndroidTest
2.4構(gòu)建自定義基礎(chǔ)
Android插件提供了一個(gè)寬泛的領(lǐng)域定制語言(DSL)在構(gòu)建系統(tǒng)中對(duì)大多數(shù)內(nèi)容進(jìn)行自定義互订。
2.4.1Manifest條目
通過DSL揩尸,能夠配置最重要的manifest條目,例如:
minSdkVersion
targetSdkVersion
versionCode
versionName
-
applicationId
關(guān)于包名屁奏,詳情請(qǐng)點(diǎn)擊:應(yīng)用ID VS 包名 -
testApplicationId
(用于測(cè)試apk) testInstrumentationRunner
例如:
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
versionCode 12
versionName "2.0"
minSdkVersion 16
targetSdkVersion 23
}
}
關(guān)于完整的構(gòu)建屬性清單以及其默認(rèn)值岩榆,請(qǐng)查看Android插件特定領(lǐng)域語言參考。
把這些清單屬性放入構(gòu)建文件中的好處是坟瓢,這些值可以動(dòng)態(tài)獲取勇边。例如,別人可以從文件中閱讀版本名稱或者使用自定義邏輯:
def computeVersionName() {
//...
}
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
versionCode 12
versionName computeVersionName()
minSdkVersion 16
targetSdkVersion 23
}
}
注意:不要使用當(dāng)前域中可能和getters沖突的文件名折联。例如
defaultConfig{...}
調(diào)用getVersionName()
會(huì)自動(dòng)使用defaultConfig.getVersion()
而不是自定義的方法粒褒。
2.4.2構(gòu)建類型
默認(rèn)情況下,Android插件自動(dòng)建立了debug版和release版應(yīng)用诚镰。二者最大的不同是在安全設(shè)備(非開發(fā)設(shè)備)上的調(diào)試能力奕坟,以及APK文件被簽名的詳情信息祥款。debug版本是由已知用戶名/密碼(防止在構(gòu)建過程中的提示)所自動(dòng)創(chuàng)建的key/證書所簽名。release版本在構(gòu)建過程中并不被簽名月杉,這將會(huì)在后面發(fā)生刃跛。
這項(xiàng)配置通過一個(gè)叫做BuildType
的對(duì)象完成。默認(rèn)情況下,有兩個(gè)實(shí)例被創(chuàng)建苛萎,分別是debug版和release版桨昙。Android插件運(yùn)行自定義這兩個(gè)實(shí)例,就像其他構(gòu)建類型一樣腌歉。這是由buildTypes
特定領(lǐng)域語言容器所完成的:
android {
buildTypes {
debug {
applicationIdSuffix ".debug"
}
jnidebug {
initWith(buildTypes.debug)
applicationIdSuffix ".jnidebug"
jniDebuggable true
}
}
}
上述片斷實(shí)現(xiàn)了如下內(nèi)容:
- 配置默認(rèn)的debug構(gòu)建類型
- 設(shè)置包為”應(yīng)用ID.debug”蛙酪,使得應(yīng)用的debug版和release版都能在同一個(gè)設(shè)備上安裝。
- 創(chuàng)建了一個(gè)新的叫作
jnidebug
的構(gòu)建類型翘盖,并對(duì)其使用debug
構(gòu)建類型進(jìn)行復(fù)制桂塞。 - 繼續(xù)配置
jnidebug
,開啟JNI組件調(diào)試功能馍驯,并添加一個(gè)不同的包名后綴阁危。
創(chuàng)建一個(gè)新的構(gòu)建類型就和使用buildTypes
容器下的一個(gè)新元素一樣簡(jiǎn)單,要么調(diào)用initWith()
要么將其完全配置結(jié)束泥彤。關(guān)于構(gòu)建類型的完整屬性清單欲芹,請(qǐng)查閱:Android構(gòu)建類型參考
另外卿啡,關(guān)于修改構(gòu)建屬性吟吝,構(gòu)建類型可以用于添加指定的代碼和資源文件。對(duì)每一種構(gòu)建類型颈娜,新的相匹配資源集被創(chuàng)建剑逃,其默認(rèn)位置為”src/構(gòu)建類型名稱”,例如src/debug/java
目錄能夠用于添加僅僅在debug APK文件中所編譯的代碼或資源文件官辽。這意味著構(gòu)建類型的命名不能和main
以及androidTest
重復(fù)(蛹磺,并且必須獨(dú)一無二(這是插件所限制的)。
就像其他任何的資源集一樣同仆,構(gòu)建類型資源的位置能夠重新指定:
android {
sourceSets.jnidebug.setRoot('foo/jnidebug')
}
此外萤捆,對(duì)于每一種構(gòu)建類型,一個(gè)新的assemble構(gòu)建類型名稱
任務(wù)被創(chuàng)建俗批,例如assembleDebug
俗或。assembleDebug
任務(wù)和assembleRelease
任務(wù)在上文中已經(jīng)被提及,這也就是他們?yōu)槭裁磿?huì)存在的原因岁忘。當(dāng)debug
構(gòu)建類型和release
構(gòu)建類型預(yù)創(chuàng)建時(shí)辛慰,這些任務(wù)(assembleDebug
和assembleRelease
)也會(huì)被自動(dòng)創(chuàng)建。根據(jù)這個(gè)規(guī)則干像,上述的build.gradle片段也將會(huì)生成一個(gè)叫做assembleJnidebug
的任務(wù)帅腌,該任務(wù)的依賴關(guān)系也和assembleDebug
以及assembleRelease
一樣驰弄。
提示:請(qǐng)記得你能夠輸入
aJ
來運(yùn)行assembleJnidebug
任務(wù)。
可能的使用情況:
- 一些權(quán)限只在debug模式下開啟速客,在release模式下禁用
- 調(diào)試的自定義實(shí)現(xiàn)
- debug模式下的使用資源不同(例如當(dāng)一個(gè)資源值與資源證書相掛鉤時(shí))
不同構(gòu)建類型的代碼/資源被用于以下情況: - Manifest清單被合并到app清單文件中
- 作為其他資源文件夾的代碼
- 資源文件被主資源文件覆蓋并替換現(xiàn)有的值
2.4.3簽名配置
對(duì)一個(gè)應(yīng)用的簽名需要以下內(nèi)容(關(guān)于APK文件簽名的詳細(xì)信息戚篙,請(qǐng)查閱簽名你的應(yīng)用):
- keystore
- keystore密碼
- keystore別名
- key密碼
- 商店類型
位置,key名稱以及密碼和商店類型共同構(gòu)成簽名配置挽封。默認(rèn)情況下已球,debug
配置使用debug keystore,其帶有已知的密碼和默認(rèn)的key和key的密碼辅愿。debug的keystore位于$HOME/.android/debug.keystore
智亮,如果不存在會(huì)被創(chuàng)建。debug
構(gòu)建類型被自動(dòng)設(shè)成使用debug
簽名配置点待。
創(chuàng)建其他配置信息或自定義默認(rèn)的內(nèi)置配置信息是可行的阔蛉。這是通過signingConfigs
特定領(lǐng)域語言容器完成的:
android {
signingConfigs {
debug {
storeFile file("debug.keystore")
}
myConfig {
storeFile file("other.keystore")
storePassword "android" keyAlias "androiddebugkey"
keyPassword "android"
}
}
buildTypes {
foo {
signingConfig signingConfigs.myConfig
}
}
}
上述片段改變了debug版本keystore文件的位置為項(xiàng)目的根目錄。這將會(huì)自動(dòng)影響到任何構(gòu)建類型癞埠,任何構(gòu)建類型都能夠使用它状原。在上例中即為debug
構(gòu)建類型。這也將會(huì)創(chuàng)建一個(gè)新的簽名配置苗踪,新的構(gòu)建類型(foot
)便可以使用這個(gè)新的簽名配置颠区。
注意1:只有debug keystore文件自動(dòng)創(chuàng)建并位于默認(rèn)位置。改變debug keystore文件位置并不會(huì)按需創(chuàng)建通铲。只有使用不同命名創(chuàng)建簽名配置并使用默認(rèn)的debug keystore位置的情況下才會(huì)自動(dòng)創(chuàng)建毕莱。從另一方面來說,這是和keystore文件的位置掛鉤的颅夺,而不是和配置信息的命名相對(duì)應(yīng)的朋截。
注意2:keystore文件的位置通常情況下和項(xiàng)目的根目錄相關(guān),但是也能夠是絕對(duì)目錄吧黄,雖然這并不被推薦(除非是debug的部服,因?yàn)樗鼤?huì)自動(dòng)被創(chuàng)建)。
注意3:如果你把這些文件納入到版本控制系統(tǒng)中拗慨,你可能并不想要把密碼放在其中廓八。這里介紹了從控制臺(tái)或環(huán)境變量中讀取值的方法。
3.依賴赵抢,Android庫(kù)以及多項(xiàng)目建立
3.1依賴二進(jìn)制包
3.1.1本地包
要去配置一個(gè)依賴庫(kù)或者額外的jar庫(kù)剧蹂,你需要在compile
配置中添加一個(gè)依賴關(guān)系。下面的片段在libs文件夾中添加了所有jar文件的依賴關(guān)系:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
android {
//...
}
注意:
dependencies
特定領(lǐng)域語言元素是標(biāo)準(zhǔn)Gradle API中的一部分昌讲。在這里面的每一項(xiàng)都被加入到編譯類路徑中国夜,并都在最終的APK文件中被打包進(jìn)去。以下是可能的配置信息:
-
compile
主應(yīng)用 -
androidTestCompile
測(cè)試應(yīng)用 -
debugCompile
debug構(gòu)建類型 -
releaseCompile
release構(gòu)建類型
由于在構(gòu)建APK時(shí)并不可能沒有關(guān)聯(lián)的構(gòu)建類型短绸,因此APK總是被配置至少兩個(gè)編譯配置信息:compile
以及構(gòu)建類型Compile
车吹。創(chuàng)建一個(gè)新的構(gòu)建類型將會(huì)自動(dòng)創(chuàng)建一個(gè)基于該構(gòu)建類型名稱的編譯配置筹裕。如果debug版本需要添加一個(gè)自定義的庫(kù)(如報(bào)告程序崩潰情況)時(shí),或者不同構(gòu)建類型依賴于相同庫(kù)的不同版本時(shí)這將是非常有用的(點(diǎn)擊這里詳見不同版本的沖突是如何處理的)窄驹。
3.1.2遠(yuǎn)程依賴
Gradle支持從Maven和Ivy庫(kù)中拉取依賴(artifact)朝卒。首先,該倉(cāng)庫(kù)必須被添加到列表中乐埠,其次依賴必須被聲明抗斤。
repositories {
jcenter()
}
dependencies {
compile 'com.google.guava:guava:18.0'
}
android {
//...
}
注意1:
jcenter()
是指定倉(cāng)庫(kù)的URL縮寫。Gradle同時(shí)支持遠(yuǎn)程和本地的倉(cāng)庫(kù)丈咐。
注意2:Gradle遵循依賴的傳遞性瑞眼。這意味著,如果如果一個(gè)依賴棵逊,依賴于其本身伤疙,這也會(huì)被拉取。
關(guān)于建立依賴的更多信息辆影,請(qǐng)閱讀Gradle使用指南和DSL文檔
3.2多項(xiàng)目的搭建
Gradle項(xiàng)目也能夠通過多項(xiàng)目搭建依賴于其他Gradle項(xiàng)目徒像。一個(gè)多項(xiàng)目的搭建通常為將所有項(xiàng)目作為已給項(xiàng)目根目錄的子目錄。例如蛙讥,給出如下的結(jié)構(gòu):
MyProject/
- app/
- libraries/
- lib1/
- lib2/
我們能夠識(shí)別出三個(gè)項(xiàng)目锯蛀。Gradle會(huì)用下述的命名進(jìn)行參考:
:app
:libraries:lib1
:libraries:lib2
每一個(gè)項(xiàng)目擁有其自己的build.gradle文件,聲明了其如何得到其構(gòu)建次慢。額外的旁涤,將會(huì)有一個(gè)被命名為setting.gradle的文件位于根目錄,用于聲明所有項(xiàng)目经备。一下給出了結(jié)構(gòu):
MyProject/
| settings.gradle
- app/
| build.gradle - libraries/
- lib1/
| build.gradle - lib2/
| build.gradle
- lib1/
setting.gradle的內(nèi)容非常簡(jiǎn)單拭抬。它定義了哪個(gè)文件夾是一個(gè)Gradle項(xiàng)目:
include ':app', ':libraries:lib1', ':libraries:lib2'
:app
項(xiàng)目很可能依賴于其他的項(xiàng)目作為庫(kù)部默,這是通過以下聲明實(shí)現(xiàn)的:
dependencies {
compile project(':libraries:lib1')
}
關(guān)于多項(xiàng)目搭建的更多信息侵蒙,請(qǐng)點(diǎn)擊這里。
3.3庫(kù)項(xiàng)目
在上述的多項(xiàng)目搭建中:libraries:lib1
和:libraries:lib2
作為Java項(xiàng)目傅蹂,:app
Android項(xiàng)目將會(huì)使用這兩個(gè)項(xiàng)目的jar輸出纷闺。但是,如果你想要通過Android API或使用Android風(fēng)格的資源來共享代碼份蝴,這些庫(kù)就不能是常規(guī)的Java項(xiàng)目犁功,它們必須是Android庫(kù)項(xiàng)目。
3.3.1創(chuàng)建一個(gè)庫(kù)項(xiàng)目
一個(gè)庫(kù)項(xiàng)目和一個(gè)常規(guī)的Android項(xiàng)目非常相似婚夫。因?yàn)闃?gòu)建庫(kù)和構(gòu)建應(yīng)用是不同的浸卦,因此使用的插件也不同。本質(zhì)上來說案糙,兩個(gè)插件大多數(shù)代碼都是相似的限嫌,并且都由相同的com.android.tools.build.gradle
jar文件提供靴庆。
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.1'
}
}
apply plugin: 'com.android.library'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
}
這將會(huì)創(chuàng)建一個(gè)使用API 23進(jìn)行編譯的庫(kù)項(xiàng)目。資源集怒医,構(gòu)建類型以及依賴關(guān)系的使用都和應(yīng)用項(xiàng)目相同炉抒,并可以通過相同的方式自定義。
3.3.2項(xiàng)目和項(xiàng)目庫(kù)的區(qū)別
庫(kù)項(xiàng)目的主要輸出是一個(gè).arr包(表示Android archive)稚叹,是編譯代碼(就像jar文件或者原生的.so文件一樣)和資源文件(清單焰薄,res文件以及assets文件)的組合。一個(gè)庫(kù)項(xiàng)目也可以生成一個(gè)測(cè)試apk文件用于測(cè)試庫(kù)的獨(dú)立性扒袖。對(duì)此使用的祖先任務(wù)也是相同的(assembleDebug
和assembleReleas
)。因此用命令去構(gòu)建這樣一個(gè)項(xiàng)目并沒有什么區(qū)別蠢络。對(duì)于其他方面,庫(kù)項(xiàng)目表現(xiàn)得和應(yīng)用項(xiàng)目一樣。庫(kù)項(xiàng)目也擁有構(gòu)建類型和產(chǎn)品渠道(product flavors返敬,見下文),并且能夠潛在地生成多個(gè)版本的aar文件苗沧。請(qǐng)注意震束,構(gòu)建類型的大多數(shù)配置并不能夠用于庫(kù)項(xiàng)目宏榕。但是你可以使用自定義資源集來改變庫(kù)的內(nèi)容枢劝,這取決于當(dāng)前庫(kù)是否被用于一個(gè)項(xiàng)目,或者用于被測(cè)試您旁。
3.3.4引用一個(gè)庫(kù)
引用一個(gè)庫(kù)和二進(jìn)制包被引用是一樣的:
dependencies {
compile project(':libraries:lib1')
compile project(':libraries:lib2')
}
注意:如果你有多個(gè)庫(kù)烙常,那么引用的順序就變得很重要。這和舊的構(gòu)建系統(tǒng)中在project.properties文件中的依賴順序一樣重要。
3.3.5庫(kù)發(fā)布
默認(rèn)情況下蚕脏,一個(gè)庫(kù)僅僅發(fā)布其release版本侦副。該版本被用于所有項(xiàng)目對(duì)庫(kù)的引用,不論這些項(xiàng)目本身使用怎樣的的構(gòu)建類型驼鞭,而這是一個(gè)我們將要取消的臨時(shí)限制秦驯。你可以控制要發(fā)布何種版本:
android {
defaultPublishConfig "debug"
}
注意,發(fā)布的配置名參考于版本的命名挣棕。Release和Debug版僅僅適合沒有渠道的情況下译隘。如果你想要使用渠道改變默認(rèn)的發(fā)布版本,你可以這樣寫:
android {
defaultPublishConfig "flavor1Debug"
}
發(fā)布一個(gè)庫(kù)的所有版本是可能的洛心。我們計(jì)劃允許使用一個(gè)標(biāo)準(zhǔn)的項(xiàng)目到項(xiàng)目的依賴固耘,但是目前這是不可能的,這是因?yàn)镚radle中的一些限制(我們正在努力解決這些)词身。
發(fā)布所有版本在默認(rèn)情況下是不可以的厅目。下面的片段展示了如何開啟這項(xiàng)功能:
android {
publishNonDefault true
}
很重要的一點(diǎn)是,你需要意識(shí)到發(fā)布多版本的arr文件而不是包含多個(gè)版本的arr文件法严。每一個(gè)arr包包含單個(gè)版本损敷。發(fā)布一個(gè)版本意味著使得這個(gè)arr文件和Gradle項(xiàng)目輸出的依賴一樣可用。這能夠被用于當(dāng)發(fā)布到maven庫(kù)時(shí)深啤,或者當(dāng)另一個(gè)項(xiàng)目依賴于該庫(kù)時(shí)嗤锉。
Gradle有一個(gè)默認(rèn)依賴的概念。這是當(dāng)我們這樣寫時(shí):
dependencies {
compile project(':libraries:lib2')
}
創(chuàng)建一個(gè)依賴于另一個(gè)發(fā)布類庫(kù)的類庫(kù)時(shí)墓塌,你需要指定使用哪一個(gè):
dependencies {
flavor1Compile project(path: ':lib1', configuration: 'flavor1Release')
flavor2Compile project(path: ':lib1', configuration: 'flavor2Release')
}
重點(diǎn)1:請(qǐng)注意到已發(fā)布的配置是全版本的瘟忱,包括所有的構(gòu)建類型,并且需要被引用苫幢。
重點(diǎn)2:當(dāng)開啟非默認(rèn)發(fā)布時(shí)访诱,maven發(fā)布插件將會(huì)發(fā)布這些額外的版本作為額外的包(帶有classifier)。這意味著發(fā)布到maven庫(kù)并不能真正地兼容韩肝。你應(yīng)該發(fā)布一個(gè)單版本触菜,或者開啟所有的配置用于發(fā)布內(nèi)部項(xiàng)目依賴。
4.測(cè)試
應(yīng)用項(xiàng)目中整合了測(cè)試應(yīng)用的構(gòu)建哀峻。因此不需要再有一個(gè)獨(dú)立的測(cè)試項(xiàng)目涡相。
4.1單元測(cè)試
在1.1中所提到的單元測(cè)試支持,請(qǐng)點(diǎn)擊這里剩蟀。本章節(jié)的剩下部分介紹了“工具測(cè)試(instrumentation tests)”催蝗,能夠運(yùn)行在真機(jī)或者模擬機(jī)上,其要求是要構(gòu)建一個(gè)測(cè)試APK文件育特。
4.2基礎(chǔ)配置
如之前所提到的丙号,main
資源集后面就是androidTest
資源集,默認(rèn)情況下位于src/androidTest
,使用這個(gè)資源集使得測(cè)試APK被構(gòu)建并能夠安裝到設(shè)備中犬缨,從而可以使用Android測(cè)試框架來測(cè)試應(yīng)用喳魏,包括Android單元測(cè)試,instrumentation tests以及uiautomator tests怀薛。清單中的<instrumentation>
節(jié)點(diǎn)是被生成的刺彩,但是你可以創(chuàng)建一個(gè)src/androidTest/AndroidManifest.xml
文件來添加測(cè)試清單(manifest)的其他組件。
還有一些值能夠在instrumentation測(cè)試應(yīng)用中配置枝恋。(詳情請(qǐng)查閱DSL參考)
- testApplicationId
- testInstrumentationRunner
- testHandleProfiling
- testFunctionalTest
如前所述迂苛,上述信息被配置在defaultConfig
對(duì)象:
android {
defaultConfig {
testApplicationId "com.test.foo" testInstrumentationRunner "android.test.InstrumentationTestRunner"
testHandleProfiling true
testFunctionalTest true
}
}
測(cè)試應(yīng)用清單文件的instrumentation節(jié)點(diǎn)中targetPackage
屬性的值自動(dòng)化填充為測(cè)試應(yīng)用的包名。即使在defaultConfig
中或者在構(gòu)建類型對(duì)象中自定義,該值并不會(huì)發(fā)生改變鼓择。這也就是清單文件被自動(dòng)生成的部分原因三幻。
另外,androidTest
資源集能夠配置自己的依賴關(guān)系呐能。默認(rèn)情況下念搬,應(yīng)用和其自身的依賴被添加到測(cè)試app的類路徑中,但是可以使用下面的片段進(jìn)行擴(kuò)展:
dependencies {
androidTestCompile 'com.google.guava:guava:11.0.2'
}
測(cè)試app是由assembleAndroidTest
任務(wù)構(gòu)建的摆出。這并不是對(duì)主assemble
任務(wù)的依賴朗徊,而是當(dāng)測(cè)試準(zhǔn)備運(yùn)行時(shí)自動(dòng)調(diào)用的。
當(dāng)前只有一個(gè)構(gòu)建類型能夠被測(cè)試偎漫。默認(rèn)情況下是debug
構(gòu)建類型爷恳。但是可以進(jìn)行如下配置:
android {
//...
testBuildType "staging"
}
4.3解決主apk和測(cè)試apk之間的沖突
當(dāng)instrumentation測(cè)試運(yùn)行時(shí),主APK和測(cè)試APK共享相同的類路徑象踊。如果主APK和測(cè)試APK使用相同的庫(kù)(如Guava)的不同版本時(shí)温亲,Gradle構(gòu)建會(huì)失敗。如果gradle并不捕獲這一點(diǎn)杯矩,你的應(yīng)用會(huì)在測(cè)試版和正常版表現(xiàn)地不同(包括任何會(huì)崩潰的情況)栈虚。
為了讓應(yīng)用構(gòu)建成功,請(qǐng)確保兩個(gè)APK都使用相同版本的庫(kù)史隆。如果錯(cuò)誤來自于間接依賴(在你自己的build.gradle中沒有聲明的庫(kù))魂务,僅僅在需要的地方(compile
或者androidTestCompile
)添加最新的依賴即可。你也可以使用Gradle解決沖突機(jī)制泌射。你可以通過運(yùn)行以下代碼檢查依賴樹:./gradlew :app:dependencies
和./gradlew :app:androidDependencies
粘姜。
4.4運(yùn)行測(cè)試
如前所述,check
任務(wù)需要一個(gè)連接的設(shè)備熔酷,并通過祖先任務(wù)connnectedCheck
啟動(dòng)孤紧。這個(gè)任務(wù)會(huì)依賴connectedDebugAndroidTest
。這個(gè)任務(wù)做了以下幾件事:
- 確保app和測(cè)試app被構(gòu)建(依賴于
assembleDebug
和assembleDebugAndroidTest
)纯陨。 - 安裝兩款應(yīng)用
- 運(yùn)行測(cè)試
- 卸載兩款應(yīng)用
如果有多個(gè)設(shè)備連接坛芽,所有的測(cè)試都會(huì)平行運(yùn)行在所有連接的設(shè)備上留储。如果其中一個(gè)測(cè)試失敗翼抠,在任何設(shè)備中咙轩,構(gòu)建都將會(huì)失敗。
4.5測(cè)試Android庫(kù)
測(cè)試Android庫(kù)項(xiàng)目和測(cè)試Android應(yīng)用項(xiàng)目是完全相同的阴颖。唯一的區(qū)別在于活喊,整個(gè)庫(kù)以及依賴作為測(cè)試app的一個(gè)庫(kù)被自動(dòng)添加。結(jié)果是量愧,測(cè)試APK不僅僅包括了自身的代碼钾菊,也包含了庫(kù)本身及其依賴。androidTest
任務(wù)變成僅僅安裝(卸載)測(cè)試APK(因?yàn)闆]有其他APK可供安裝)偎肃。
4.6測(cè)試報(bào)告
當(dāng)運(yùn)行單元測(cè)試時(shí)煞烫,Gradle輸出一個(gè)HTML格式的報(bào)告可供輕松地查看結(jié)果。Android插件構(gòu)建并拓展HTML報(bào)告用于從所有連接設(shè)備中匯集累颂。所有的測(cè)試結(jié)果以xml文件的形式存儲(chǔ)在build/reports/androidTests/
中(和常規(guī)的jNnit存儲(chǔ)在build/reports/tests
相似)滞详。該路徑可配置如下:
android {
//...
testOptions {
resultsDir = "${project.buildDir}/foo/results"
}
}
android.testOptions.resultsDir
的值請(qǐng)參考:Project.file(String)。
4.6.1多項(xiàng)目報(bào)告
在帶有多應(yīng)用和多庫(kù)的多項(xiàng)目的搭建中紊馏,當(dāng)同時(shí)運(yùn)行所有測(cè)試時(shí)料饥,可能生成一個(gè)所有測(cè)試的測(cè)試報(bào)告是很有用的。
為了做到這一點(diǎn)朱监,可用一個(gè)不同的gradle插件:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.5.6'
}
}
apply plugin: 'android-reporting'
這應(yīng)該被用在根項(xiàng)目中岸啡,也就是setting.gradle旁邊的build.gradle。
之后赫编,從根文件夾開巡蘸,以下的命令將會(huì)運(yùn)行所有的測(cè)試并匯集成報(bào)告:
gradle deviceCheck mergeAndroidReports --continue
注意:
--continue
選項(xiàng)確保了所有子目錄在內(nèi)的所有測(cè)試都能夠被運(yùn)行,即使其中有失敗的情況擂送。
4.7Lint支持
你可以在一個(gè)指定版本運(yùn)行l(wèi)int檢查(如下)赡若,例如:./gradlew lintRelease
或者全版本的lint檢查(./gradlew lint
),在這種情況下會(huì)產(chǎn)生一個(gè)描述指定版本的報(bào)告团甲。你可以通過添加lintOption部分來配置lint(如下)逾冬。你應(yīng)該添加一些典型的部分:詳見。
android {
lintOptions {
// turn off checking the given issue id's
disable 'TypographyFractions','TypographyQuotes'
// turn on the given issue id's
enable 'RtlHardcoded','RtlCompat', 'RtlEnabled'
// check *only* the given issue id's
check 'NewApi', 'InlinedApi'
}
}
5.構(gòu)建版本
新構(gòu)建系統(tǒng)的一個(gè)目標(biāo)就是能夠?qū)ν粋€(gè)應(yīng)用創(chuàng)建不同的版本躺苦。
主要使用情況有兩個(gè):
- 一個(gè)應(yīng)用的不同版本身腻。例如,一個(gè)免費(fèi)/demo版本和一個(gè)專業(yè)版本
- 同一個(gè)應(yīng)用在Google Play商店打包分發(fā)多個(gè)詳見:http://developer.android.com/google/play/publishing/multiple-apks.html
- 前兩者的組合
目標(biāo)是能夠在同一個(gè)項(xiàng)目中生成不同的應(yīng)用匹厘,而不是使用同一個(gè)庫(kù)的不同應(yīng)用項(xiàng)目嘀趟。
5.1產(chǎn)品渠道
產(chǎn)品渠道(product flavor)定義了一個(gè)項(xiàng)目應(yīng)用構(gòu)建的自定義版本。單個(gè)的項(xiàng)目可以有不同的渠道愈诚,從而生成的應(yīng)用不同她按。
這個(gè)新的概念被設(shè)計(jì)用于幫助版本差異非常小的情況下牛隅。如果當(dāng)問到“這是否是同一個(gè)應(yīng)用?”時(shí)酌泰,如果是媒佣,那么通過庫(kù)項(xiàng)目去實(shí)現(xiàn)可能更適合一些。
產(chǎn)品渠道通過一個(gè)叫做productFlavors
的特定領(lǐng)域容器聲明:
android {
//....
productFlavors {
flavor1 {
//...
}
flavor2 {
...
}
}
}
上例中將會(huì)創(chuàng)建兩個(gè)渠道陵刹,分別是flavor1
和flavor2
注意:渠道的名稱不能喝已經(jīng)存在的構(gòu)建類型名稱沖突默伍,也不能使用
androidTest
和test
資源集的名稱。
5.2構(gòu)建類型+產(chǎn)品渠道=構(gòu)建版本
正如我們前面所看到的衰琐,每一個(gè)構(gòu)建類型生成一個(gè)新的APK文件也糊。產(chǎn)品渠道也是相同的:項(xiàng)目的輸出變成所有可能構(gòu)建類型和產(chǎn)品渠道的組合。每一個(gè)(構(gòu)建類型羡宙,產(chǎn)品渠道)組合被稱為構(gòu)建版本狸剃。例如,在默認(rèn)的debug
和release
構(gòu)建類型中狗热,上面的例子可以生成四個(gè)構(gòu)建版本:
- Flavor1 - debug
- Flavor1 - release
- Flavor2 - debug
- Flavor2 - release
沒有渠道的項(xiàng)目依然擁有構(gòu)建版本钞馁,使用的是單個(gè)默認(rèn)的default
渠道/配置.
5.3產(chǎn)品渠道配置
每一個(gè)渠道的完整配置如下:
android {
//...
defaultConfig {
minSdkVersion 8
versionCode 10
}
productFlavors {
flavor1 {
applicationId "com.example.flavor1"
versionCode 20
}
flavor2 {
applicationId "com.example.flavor2"
minSdkVersion 14
}
}
}
注意到android.productFlavors.*
對(duì)象是ProductFlavor
,其類型和android.defaultConfig
對(duì)象類型相同斗搞。這意味著它們共享相同的屬性指攒。
defaultConfig
為所有的渠道提供了基礎(chǔ)的配置,每一個(gè)種渠道能夠覆蓋它的任何值僻焚。在上述的例子中允悦,配置信息以如下結(jié)尾:
- flavor1
- applicationId: com.example.flavor1
- minSdkVersion: 8
- versionCode: 20
- flavor2
- applicationId: com.example.flavor2
- minSdkVersion: 14
- versionCode: 10
通常情況下,構(gòu)建類型配置會(huì)覆蓋其他配置虑啤。例如隙弛,構(gòu)建類型的applicationIdSuffix
追加在產(chǎn)品渠道的applicationId
后面。有一些在構(gòu)建類型和產(chǎn)品渠道都能夠設(shè)置的情況狞山。在這種情況下全闷,例如signingConfig
就是這種屬性。這使得所有發(fā)布包共享這些簽名配置萍启。通過設(shè)置android.buildTypes.release.signingConfig
或者對(duì)每一個(gè)包通過設(shè)置自己的android.productFlavors.*.signingConfig
來分別使用簽名配置总珠。
5.4資源集和依賴
和構(gòu)建類型相似,產(chǎn)品渠道也是通過自己的資源集來貢獻(xiàn)代碼勘纯。上述的例子創(chuàng)建了四個(gè)資源集:
android.sourceSets.flavor1
位置為src/flavor1android.sourceSets.flavor2
位置為src/flavor2/android.sourceSets.androidTestFlavor1
位置為 src/androidTestFlavor1/android.sourceSets.androidTestFlavor2
位置為 src/androidTestFlavor2/
這些資源集通過構(gòu)建類型和android.sourceSets.main
被用于構(gòu)建APK局服。下面的規(guī)則用于處理所有被用于構(gòu)建單個(gè)APK的情況:所有的代碼(
src/*/java
)共同用于多文件夾來生成單個(gè)輸出。清單被共同合并到單個(gè)的清單中驳遵。這允許產(chǎn)品渠道擁有不同的組件秋柄、權(quán)限贱纠,和構(gòu)建類型相似。
所有的資源遵循覆蓋的優(yōu)先級(jí)。構(gòu)建類型覆蓋產(chǎn)品渠道粗俱,產(chǎn)品渠道覆蓋
main
資源集。每個(gè)構(gòu)建版本生成自己的R類。各個(gè)版本直接不存在共享。
最后鳞溉,和構(gòu)建類型一樣,產(chǎn)品渠道可以擁有自己的依賴妒蔚。例如穿挨,如果渠道用于生成基于廣告的app或者付費(fèi)的app月弛,每一個(gè)渠道擁有自己的廣告sdk依賴肴盏。
dependencies {
flavor1Compile "..."
}
在這個(gè)例子中,文件src/flavor1/AndroidManifest.xml
可能需要包含網(wǎng)絡(luò)權(quán)限
每個(gè)版本同樣也創(chuàng)建了額外的資源集:
-
android.sourceSets.flavor1Debug
位于src/flavor1Debug
-
android.sourceSets.flavor1Release
位于src/flavor1Release
-
android.sourceSets.flavor2Debug
位于src/flavor2Debug
-
android.sourceSets.flavor2Release
位于src/flavor2Release
他們比構(gòu)建類型擁有更高的優(yōu)先級(jí)帽衙,并且允許自定義版本等級(jí)菜皂。
5.5構(gòu)建和任務(wù)
我們之前看到的,每一種構(gòu)建類型創(chuàng)建自己的assmble名字
任務(wù)厉萝,但是構(gòu)建版本是構(gòu)建類型和產(chǎn)品渠道的組合恍飘。
當(dāng)使用產(chǎn)品類型時(shí),更多的任務(wù)會(huì)被創(chuàng)建谴垫,如:
assemble構(gòu)建版本名
assemble構(gòu)建類型名
assemble產(chǎn)品渠道名
第1項(xiàng)允許你直接構(gòu)建單個(gè)的版本章母,例如aseembleFlavor1Debug
。
第2項(xiàng)允許你構(gòu)建所有已給構(gòu)建類型的apk文件翩剪。例如assembleDebug
將會(huì)構(gòu)建flavor1Debug
和flavor2Debug
乳怎。
第3項(xiàng)允許你構(gòu)建給定渠道的所有APK文件。例如前弯,assembleFlavor1
將會(huì)構(gòu)建assembleFlavor1Debug
和assembleFlavor1Release
蚪缀。
任務(wù)assemble
會(huì)構(gòu)建有可能的版本。
5.6多渠道版本
在一些情況下恕出,可能會(huì)想要基于多種條件下創(chuàng)建相同應(yīng)用的多個(gè)版本询枚。
考慮一個(gè)游戲作為例子,該游戲有一個(gè)demo版本和一個(gè)付費(fèi)版本并且想要使用多apk支持中的ABI過濾條件浙巫。3個(gè)ABI和2個(gè)版本需要生成6個(gè)APK文件(不考慮構(gòu)建類型)金蜀。
但是,支付版本的代碼對(duì)于相對(duì)應(yīng)的3個(gè)ABI版本是相同的的畴,因此創(chuàng)建6個(gè)渠道并不是一個(gè)好方法渊抄。
取而代之的是,配置兩個(gè)渠道版本苗傅,所有的構(gòu)建版本應(yīng)該自動(dòng)構(gòu)建可能的組合抒线。
這個(gè)功能是通過渠道規(guī)格(flavor dimension)來實(shí)現(xiàn)的。渠道被設(shè)置到指定的規(guī)格:
android {
//...
flavorDimensions "abi", "version"
productFlavors {
freeapp {
dimension "version"
//...
}
paidapp {
dimension "version"
...
}
arm {
dimension "abi"
...
}
mips {
dimension "abi"
...
}
x86 {
dimension "abi"
...
}
}
}
android.flavorDimensions
數(shù)組定義了可能的規(guī)格渣慕。每一個(gè)產(chǎn)品渠道指定一個(gè)規(guī)格嘶炭。
從指定了規(guī)格的產(chǎn)品渠道(free app,paid app)以及構(gòu)建類型(debug抱慌,release),能夠創(chuàng)建如下的構(gòu)建版本:
- x86-freeapp-debug
- x86-freeapp-release
- arm-freeapp-debug
- arm-freeapp-release
- mips-freeapp-debug
- mips-freeapp-release
- x86-paidapp-debug
- x86-paidapp-release
- arm-paidapp-debug
- arm-paidapp-release
- mips-paidapp-debug
- mips-paidapp-release
規(guī)格的順序是通過android.flavorDimensions
定義的眨猎,這一點(diǎn)非常重要抑进。
每一個(gè)版本通過不同的產(chǎn)品渠道進(jìn)行配置:
android.defaultConfig
- abi規(guī)格
- 版本規(guī)格
規(guī)格的順序驅(qū)動(dòng)了是哪個(gè)渠道去覆蓋哪個(gè)渠道,這對(duì)于渠道的哪個(gè)資源值去替代另一個(gè)渠道的資源值而言非常重要睡陪。
渠道規(guī)格通過高優(yōu)先級(jí)進(jìn)行定義寺渗。在這種情況下:
abi
>version
>defaultConfig
多渠道項(xiàng)目也擁有額外的資源集,和構(gòu)建版本資源集相似但是不包括構(gòu)建類型:
-
android.sourceSets.x86Freeapp
位于src/x86Freeapp
-
android.sourceSets.armPaidapp
位于src/armPaidapp
這樣允許渠道組合級(jí)別的自定義兰迫。他們比基本的渠道資源集擁有更高的優(yōu)先級(jí)信殊,但是優(yōu)先級(jí)低于構(gòu)建類型資源集。
5.7測(cè)試
多渠道項(xiàng)目測(cè)試和簡(jiǎn)單的項(xiàng)目測(cè)試非常相似汁果。
androidTest
資源集用于所有渠道的通用測(cè)試涡拘,而每個(gè)渠道可以有自己的測(cè)試。
如上所提及的据德,每個(gè)渠道的資源集按照如下形式被創(chuàng)建:
-
android.sourceSets.androidTestFlavor1
位于src/androidTestFlavor1
-
android.sourceSets.androidTestFlavor2
位于src/androidTestFlavor2/
相似地鳄乏,它們可以有各自的依賴:
dependencies {
androidTestFlavor1Compile "..."
}
運(yùn)行測(cè)試可以通過祖先任務(wù)deviceCheck
完成,或者通過主androidTest
任務(wù)棘利。
每一個(gè)渠道都有自己的測(cè)試任務(wù):androidTest版本名
橱野,例如:
androidTestFlavor1Debug
androidTestFlavor2Debug
相似地,測(cè)試APK的構(gòu)建和卸載安裝按照每個(gè)版本進(jìn)行:
- assembleFlavor1Test
- installFlavor1Debug
- installFlavor1Test
- uninstallFlavor1Debug
最后善玫,HTML報(bào)告生成支持通過渠道的匯總水援。
測(cè)試結(jié)果和報(bào)告的位置如下所示,首先是渠道版蝌焚,其次是匯總版:
- build/androidTest-results/flavors/渠道名
- build/androidTest-results/all/
- build/reports/androidTests/flavors/渠道名
- build/reports/androidTests/all/
或者可以自定義路徑裹唆,但這僅僅改變了文件夾的根目錄,但是仍然會(huì)對(duì)每個(gè)渠道創(chuàng)建子目錄并匯集報(bào)告結(jié)果只洒。
5.8構(gòu)建配置
Android Studio生成一個(gè)叫作BuildConfig
的類许帐,包含了用于構(gòu)建一個(gè)特定版本的常量值。你可以指定這些常量值來改變不同版本毕谴,例如:
private void javaCode() {
if (BuildConfig.FLAVOR.equals("paidapp")) {
doIt();
else {
showOnlyInPaidAppDialog();
}
}
以下是構(gòu)建配置中含有的值:
-
boolean DEBUG
– if the build is debuggable. int VERSION_CODE
String VERSION_NAME
String APPLICATION_ID
-
String BUILD_TYPE
- 構(gòu)建類型的名字成畦,例如”release” -
String FLAVOR
– 渠道名稱,例如”paid app”
如果項(xiàng)目使用渠道規(guī)格涝开,將會(huì)生成額外的規(guī)格循帐。使用上面的例子,會(huì)有如下的構(gòu)建配置示例:
String FLAVOR = "armFreeapp"
String FLAVOR_abi = "arm"
String FLAVOR_version = "free app"
5.9過濾版本
當(dāng)你添加規(guī)格和渠道時(shí)舀武,你應(yīng)該停止使用沒有意義的版本拄养。例如你可能為了更快的測(cè)試,會(huì)定義一個(gè)使用你的Web API的渠道银舱,以及一個(gè)使用硬編碼的假數(shù)據(jù)瘪匿。第二個(gè)渠道僅僅在開發(fā)的時(shí)候有用跛梗,但是在發(fā)布版本的構(gòu)建時(shí)卻沒有用處。你可以刪除這個(gè)版本棋弥,改成使用variantFilter
核偿,例如:
android {
productFlavors {
realData
fakeData
}
variantFilter { variant ->
def names = variant.flavors*.name
if (names.contains("fakeData") && variant.buildType.name == "release") {
variant.ignore = true
}
}
}
在上面的配置中,你的項(xiàng)目只有三個(gè)版本:
realDataDebug
realDataRelease
fakeDataDebug
6.高級(jí)構(gòu)建自定義
6.1運(yùn)行混淆
混淆插件在Android插件中被自動(dòng)使用顽染,如果構(gòu)建類型通過minifyEnabled
屬性開啟了混淆漾岳,那么任務(wù)會(huì)被自動(dòng)創(chuàng)建。
android {
buildTypes {
release {
minifyEnabled true
proguardFile getDefaultProguardFile('proguard-android.txt')
}
}
productFlavors {
flavor1 {
}
flavor2 { proguardFile 'some-other-rules.txt'
}
}
}
版本使用所有在這個(gè)構(gòu)建類型以及產(chǎn)品渠道中聲明的規(guī)則文件粉寞。
有兩個(gè)默認(rèn)規(guī)則文件:
- proguard-android.txt
- proguard-android-potimize.txt
這些文件位于SDK中尼荆。使用getDefaultProguardFile()
會(huì)返回文件的全路徑。這些文件是相同的仁锯,除非開啟了優(yōu)化耀找。
6.2縮減資源
你可以在構(gòu)建時(shí)自動(dòng)移除所有未使用的資源翔悠。關(guān)于更多信息业崖,請(qǐng)查閱資源縮減文檔。
6.3操作任務(wù)
基本的Java項(xiàng)目擁有有限的任務(wù)集共同創(chuàng)建輸出蓄愁。
classes
是編譯java源代碼的任務(wù)之一双炕,縮寫為:project.tasks.classes
。
在Android項(xiàng)目中有一些復(fù)雜撮抓。這是因?yàn)榭赡苡写罅肯嗤娜蝿?wù)妇斤,并且它們的名字基于產(chǎn)品渠道和構(gòu)建類型命名。
為了去解決這一點(diǎn)丹拯,android
對(duì)象有以下兩個(gè)屬性:
-
applicationVariants
(只用于app插件) -
libraryVariants
(只用于庫(kù)插件) -
testVariants
(同時(shí)適用于app和庫(kù)插件)
三者分別返回ApplicationVariant
站超,LibraryVariant
,TestVariant
的領(lǐng)域?qū)ο蠹?/a>乖酬。
注意到死相,訪問以上三種集合的任意一種都會(huì)引發(fā)所有任務(wù)的創(chuàng)建。這意味著在訪問集合后不會(huì)發(fā)生任何重新配置的情況咬像。
領(lǐng)域?qū)ο蠹现苯釉L問所有對(duì)象算撮,或者通過更方便的過濾器。
android.applicationVariants.all { variant ->
....
}
所有版本類都含有以下屬性:
- name 類型為String县昂,表示版本名稱肮柜,要求不重復(fù)。
- description 類型為String倒彰,人類可讀的版本描述审洞。
- dirName 類型為String,版本的子文件夾名稱待讳,要求不重復(fù)芒澜∷跞可能會(huì)有多個(gè)文件夾,例如”debug/flavor”撰糠。
- baseName 類型為String酥馍,輸出版本的基本名稱,要求不重復(fù)阅酪。
- outputFile 類型為File旨袒,版本的輸出。擁有讀/寫屬性术辐。
- processManifest 類型為ProcessManifest砚尽,用于處理清單的任務(wù)。
- aidlCompile 類型為AidlCompile辉词,編譯AIDL文件的任務(wù)必孤。
- renderscriptCompile 類型為RenderscriptCompile,編譯Renderscript的任務(wù)瑞躺。
- mergeResources 類型為MergeResources敷搪,合并資源文件的任務(wù)。
- mergeAssets 類型為MergeAssets幢哨,合并assets的任務(wù)赡勘。
- processResources 類型為ProcessAndroidResources,用于處理和編譯資源的任務(wù)捞镰。
- generateBuildConfig 類型為GenerateBuildConfig,生成BuildConfig類的任務(wù)
- javaCompile 類型為JavaCompile闸与,編譯Java代碼的任務(wù)。
- processJavaResources 類型為Copy岸售,處理Java資源的任務(wù)践樱。
- assemble 類型為DefaultTask,對(duì)版本輸出的祖先任務(wù)凸丸。
ApplicationVariant類添加了如下內(nèi)容: - buildType 類型為BuildType拷邢,版本的構(gòu)建類型。
- productFlavors 類型為L(zhǎng)ist<ProductFlavor>,版本的產(chǎn)品渠道可以不設(shè)置但是永遠(yuǎn)不為空甲雅。
- mergedFlavor 類型為ProductFlavor,android.defaultConfig和variant.productFlavors的合并解孙。
- signingConfig 類型為SigningConfig,該版本的簽名配置。
- isSigningReady 類型為boolean抛人。為真時(shí)該版本擁有簽名的所有必需信息弛姜。
- testVariant 類型為BuildVariant。TestVariant會(huì)測(cè)試該版本妖枚。
- dex 類型為Dex廷臼,編譯代碼的任務(wù)。如果是個(gè)庫(kù)項(xiàng)目可以為空。
- packageApplication 類型為PackageApplication荠商,構(gòu)建最終APK的任務(wù)寂恬。如果是個(gè)庫(kù)項(xiàng)目可以為空。
- zipAlign 類型為ZipAlign莱没。打包apk的任務(wù)初肉,如果是個(gè)庫(kù)項(xiàng)目或者APK不能被簽名時(shí)可以為空。
- install 類型為DefaultTask饰躲,安裝任務(wù)牙咏,可以為空。
- unstall 類型為DefaultTask嘹裂,卸載任務(wù)妄壶。
LibraryVariant類添加了一下內(nèi)容: - buildType 類型為BuildType,版本的構(gòu)建類型寄狼。
- mergedFlavor 類型為ProductFlavor丁寄,默認(rèn)配置值。
- testVariant 類型為BuildVariant泊愧,要測(cè)試的構(gòu)建版本伊磺。
- packageLibrary 類型為Zip,打包庫(kù)AAR壓縮包的任務(wù)拼卵,如果不是庫(kù)項(xiàng)目則為空奢浑。
TestVariant類添加了如下內(nèi)容: - buildType 類型為BuildType,版本的構(gòu)建類型腋腮。
- productFlavors 類型為L(zhǎng)ist<ProductFlavor>,版本的產(chǎn)品渠道可以不設(shè)置但是永遠(yuǎn)不為空。
- mergedFlavor 類型為ProductFlavor,android.defaultConfig和variant.productFlavors的合并壤蚜。
- signingConfig 類型為SigningConfig,該版本的簽名配置即寡。
- isSigningReady 類型為boolean。為真時(shí)該版本擁有簽名的所有必需信息袜刷。
- testVariant 類型為BuildVariant聪富。TestVariant會(huì)測(cè)試該版本。
- dex 類型為Dex著蟹,編譯代碼的任務(wù)墩蔓。如果是個(gè)庫(kù)項(xiàng)目可以為空。
- packageApplication 類型為PackageApplication萧豆,構(gòu)建最終APK的任務(wù)奸披。如果是個(gè)庫(kù)項(xiàng)目可以為空。
- zipAlign 類型為ZipAlign涮雷。打包apk的任務(wù)阵面,如果是個(gè)庫(kù)項(xiàng)目或者APK不能被簽名時(shí)可以為空。
- install 類型為DefaultTask,安裝任務(wù)样刷,可以為空仑扑。
- unstall 類型為DefaultTask,卸載任務(wù)置鼻。
- connectedAndroidTest 類型為DefaultTask镇饮,在連接設(shè)備上運(yùn)行Android測(cè)試的任務(wù)。
- providerAndroidTest 類型為DefaultTask箕母,使用擴(kuò)展API運(yùn)行Android測(cè)試的任務(wù)盒让。
Android特定任務(wù)類型API:
- ProcessManifest
- 文件 manifestOutputFile
- AidlCompile
- 文件 sourceOutputDir
- RenderscriptCompile
- 文件 sourceOutputDir
- 文件 resOutputDir
- MergeResources
- 文件 outputDir
- MergeAssets
- 文件 outputDir
- ProcessAndroidResources
- 文件 manifestFile
- 文件 resDir
- 文件 assetsDir
- 文件 sourceOutputDir
- 文件 textSymbolOutputDir
- 文件 packageOutputFile
- 文件 proguardOutputFile
- GenerateBuildConfig
- 文件 sourceOutputDir
- Dex
- 文件 outputFolder
- PackageApplication
- 文件 resourceFile
- 文件 dexFile
- File javaResourceDir
- 文件 jniDir
- 文件 outputFile
- 在版本對(duì)象直接使用”outputFile”改變最終輸出文件
- ZipAlign
- 文件 inputFile
- 文件 outputFile
- 在版本對(duì)象直接使用”outputFile”改變最終輸出文件
每一個(gè)任務(wù)類型的APK是有限的,這是由于Gradle的工作方式以及Android插件是如何建立的司蔬。
首先邑茄,Gradle的任務(wù)僅僅配置了輸入輸出的位置以及可能的選項(xiàng)。因此俊啼,任務(wù)僅僅定義了輸入輸出肺缕。
其次,大多數(shù)任務(wù)的輸入并不是無關(guān)緊要的授帕,通常來自于資源集和構(gòu)建類型以及產(chǎn)品渠道的混合同木。為了保持構(gòu)建文件易于閱讀和理解,開發(fā)者通過領(lǐng)域特定語言對(duì)這些對(duì)象進(jìn)行微調(diào)就能夠進(jìn)行構(gòu)建跛十,而不是深入改變項(xiàng)目的輸入和選項(xiàng)彤路。
另外也需要注意到的是,除了ZipAlign任務(wù)類型芥映,所有的任務(wù)需要設(shè)置私有的數(shù)據(jù)才能工作洲尊。這意味著不可能手動(dòng)創(chuàng)建這些類型的新任務(wù)。
主觀上API是能夠修改的奈偏。通常情況下當(dāng)前的API是圍繞著給定的輸入輸出(當(dāng)任務(wù)能夠添加額外必須的處理時(shí))坞嘀。反饋是很重要的,特別是一些需求不可見時(shí)惊来。
關(guān)于Gradle的其他任務(wù)(DefaultTask, JavaCompile, Copy, Zip)丽涩,請(qǐng)參考Gradle文檔。
6.3設(shè)置Java語言等級(jí)
你可以使用compileOptions
代碼塊選擇編譯器的語言等級(jí)裁蚁,默認(rèn)情況下是基于compileSdkVersion
的值矢渊。
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_6
targetCompatibility JavaVersion.VERSION_1_6
}
}