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)建過(guò)程易于配置,擴(kuò)展和優(yōu)化
- 良好的IDE整合
1.2為什么使用Gradle?
Gradle既是一個(gè)先進(jìn)的構(gòu)建系統(tǒng),也是一個(gè)允許通過(guò)插件創(chuàng)建自定義構(gòu)建邏輯的構(gòu)建工具集。以下是一些我們?yōu)槭裁催x擇Gradle的原因:
- 用于描述和操作構(gòu)建邏輯的,基于Groovy的特定領(lǐng)域語(yǔ)言(DSL)
- 基于Groovy的構(gòu)建文件,允許混合通過(guò)使用DSL的聲明式元素以及使用代碼去操作DSL元素來(lái)提供自定義邏輯。
- 通過(guò)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)域語(yǔ)言(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è)試代碼。它們各自位于:
在這些目錄里,每一個(gè)資源組件都有各自的子目錄。對(duì)于Java和Android插件,java源代碼和java資源的路徑位置為:
對(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)目相同的語(yǔ)法,但是由于其使用自己的資源集,項(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)然此處的語(yǔ)句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ù),并通過(guò)check任務(wù)進(jìn)行依賴,無(wú)論什么時(shí)候執(zhí)行調(diào)用該任務(wù),都可以直接使用check任務(wù)。
在命令行中,你可以通過(guò)下面的命令得到高級(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ù)即可。
總的來(lái)說(shuō),你可能應(yīng)當(dāng)僅僅調(diào)用assemble任務(wù)或者check任務(wù)并忽略其他的任務(wù)。你可以點(diǎn)擊這里查看Java插件所有的任務(wù)集合及其描述信息:Java插件的任務(wù)集合
2.3.3Android的任務(wù)
Android插件使用相同的概念來(lái)保持和其他插件之間的兼容性,并且,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ù)來(lái)優(yōu)化構(gòu)建:
- assemble
- assembleDebug
- assembleRelease
assembleDebug和assembleRelease兩者都依賴于其他的多步任務(wù)執(zhí)行來(lái)構(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
-
connectedCheck
-
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)域定制語(yǔ)言(DSL)在構(gòu)建系統(tǒng)中對(duì)大多數(shù)內(nèi)容進(jìn)行自定義。
2.4.1Manifest條目
通過(guò)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)域語(yǔ)言參考。
把這些清單屬性放入構(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)建過(guò)程中的提示)所自動(dòng)創(chuàng)建的key/證書所簽名。release版本在構(gòu)建過(guò)程中并不被簽名,這將會(huì)在后面發(fā)生。
這項(xiàng)配置通過(guò)一個(gè)叫做BuildType 的對(duì)象完成。默認(rèn)情況下,有兩個(gè)實(shí)例被創(chuàng)建,分別是debug版和release版。Android插件運(yùn)行自定義這兩個(gè)實(shí)例,就像其他構(gòu)建類型一樣。這是由buildTypes 特定領(lǐng)域語(yǔ)言容器所完成的:
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ú)一無(wú)二(這是插件所限制的)。
就像其他任何的資源集一樣,構(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 來(lái)運(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)置配置信息是可行的。這是通過(guò)signingConfigs 特定領(lǐng)域語(yǔ)言容器完成的:
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)建。從另一方面來(lái)說(shuō),這是和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)域語(yǔ)言元素是標(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)目也能夠通過(guò)多項(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
setting.gradle的內(nèi)容非常簡(jiǎn)單。它定義了哪個(gè)文件夾是一個(gè)Gradle項(xiàng)目:
include ':app', ':libraries:lib1', ':libraries:lib2'
:app 項(xiàng)目很可能依賴于其他的項(xiàng)目作為庫(kù),這是通過(guò)以下聲明實(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輸出。但是,如果你想要通過(guò)Android API或使用Android風(fēng)格的資源來(lái)共享代碼,這些庫(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ì)上來(lái)說(shuō),兩個(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)目相同,并可以通過(guò)相同的方式自定義。
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)目。但是你可以使用自定義資源集來(lái)改變庫(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è)試框架來(lái)測(cè)試應(yīng)用,包括Android單元測(cè)試,instrumentation tests以及uiautomator tests。清單中的<instrumentation> 節(jié)點(diǎn)是被生成的,但是你可以創(chuàng)建一個(gè)src/androidTest/AndroidManifest.xml 文件來(lái)添加測(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ò)誤來(lái)自于間接依賴(在你自己的build.gradle中沒有聲明的庫(kù)),僅僅在需要的地方(compile 或者androidTestCompile )添加最新的依賴即可。你也可以使用Gradle解決沖突機(jī)制。你可以通過(guò)運(yùn)行以下代碼檢查依賴樹:./gradlew :app:dependencies 和./gradlew :app:androidDependencies 。
4.4運(yùn)行測(cè)試
如前所述,check 任務(wù)需要一個(gè)連接的設(shè)備,并通過(guò)祖先任務(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)告。你可以通過(guò)添加lintOption部分來(lái)配置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./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í),如果是,那么通過(guò)庫(kù)項(xiàng)目去實(shí)現(xiàn)可能更適合一些。
產(chǎn)品渠道通過(guò)一個(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ā)布包共享這些簽名配置。通過(guò)設(shè)置android.buildTypes.release.signingConfig 或者對(duì)每一個(gè)包通過(guò)設(shè)置自己的android.productFlavors.*.signingConfig 來(lái)分別使用簽名配置。
5.4資源集和依賴
和構(gòu)建類型相似,產(chǎn)品渠道也是通過(guò)自己的資源集來(lái)貢獻(xiàn)代碼。上述的例子創(chuàng)建了四個(gè)資源集:
android.sourceSets.flavor1 位置為src/flavor1
android.sourceSets.flavor2 位置為src/flavor2/
android.sourceSets.androidTestFlavor1 位置為 src/androidTestFlavor1/
android.sourceSets.androidTestFlavor2 位置為 src/androidTestFlavor2/
這些資源集通過(guò)構(gòu)建類型和android.sourceSets.main 被用于構(gòu)建APK。下面的規(guī)則用于處理所有被用于構(gòu)建單個(gè)APK的情況:
所有的代碼(src/*/java )共同用于多文件夾來(lái)生成單個(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過(guò)濾條件。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ò)渠道規(guī)格(flavor dimension)來(lái)實(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ī)格的順序是通過(guò)android.flavorDimensions 定義的,這一點(diǎn)非常重要。
每一個(gè)版本通過(guò)不同的產(chǎn)品渠道進(jìn)行配置:
android.defaultConfig
- abi規(guī)格
- 版本規(guī)格
規(guī)格的順序驅(qū)動(dòng)了是哪個(gè)渠道去覆蓋哪個(gè)渠道,這對(duì)于渠道的哪個(gè)資源值去替代另一個(gè)渠道的資源值而言非常重要。
渠道規(guī)格通過(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è)試可以通過(guò)祖先任務(wù)deviceCheck 完成,或者通過(guò)主androidTest 任務(wù)。
每一個(gè)渠道都有自己的測(cè)試任務(wù):androidTest版本名 ,例如:
androidTestFlavor1Debug
androidTestFlavor2Debug
相似地,測(cè)試APK的構(gòu)建和卸載安裝按照每個(gè)版本進(jìn)行:
- assembleFlavor1Test
- installFlavor1Debug
- installFlavor1Test
- uninstallFlavor1Debug
最后,HTML報(bào)告生成支持通過(guò)渠道的匯總。
測(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è)特定版本的常量值。你可以指定這些常量值來(lái)改變不同版本,例如:
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過(guò)濾版本
當(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)建類型通過(guò)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ì)象,或者通過(guò)更方便的過(guò)濾器。
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
- AidlCompile
- RenderscriptCompile
- 文件 sourceOutputDir
- 文件 resOutputDir
- MergeResources
- MergeAssets
- ProcessAndroidResources
- 文件 manifestFile
- 文件 resDir
- 文件 assetsDir
- 文件 sourceOutputDir
- 文件 textSymbolOutputDir
- 文件 packageOutputFile
- 文件 proguardOutputFile
- GenerateBuildConfig
- Dex
- 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ù)的輸入并不是無(wú)關(guān)緊要的,通常來(lái)自于資源集和構(gòu)建類型以及產(chǎn)品渠道的混合。為了保持構(gòu)建文件易于閱讀和理解,開發(fā)者通過(guò)領(lǐng)域特定語(yǔ)言對(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語(yǔ)言等級(jí)
你可以使用compileOptions 代碼塊選擇編譯器的語(yǔ)言等級(jí),默認(rèn)情況下是基于compileSdkVersion 的值。
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_6
targetCompatibility JavaVersion.VERSION_1_6
}
}
|