Android Gradle 使用教程

gradle

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ù)(assembleDebugassembleRelease)也會(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

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)目傅蹂,:appAndroid項(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.gradlejar文件提供靴庆。

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ù)也是相同的(assembleDebugassembleReleas)。因此用命令去構(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)建(依賴于assembleDebugassembleDebugAndroidTest)纯陨。
  • 安裝兩款應(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è):

  1. 一個(gè)應(yīng)用的不同版本身腻。例如,一個(gè)免費(fèi)/demo版本和一個(gè)專業(yè)版本
  2. 同一個(gè)應(yīng)用在Google Play商店打包分發(fā)多個(gè)詳見:http://developer.android.com/google/play/publishing/multiple-apks.html
  3. 前兩者的組合

目標(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è)渠道陵刹,分別是flavor1flavor2

注意:渠道的名稱不能喝已經(jīng)存在的構(gòu)建類型名稱沖突默伍,也不能使用androidTesttest資源集的名稱。

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)的debugrelease構(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/flavor1

  • android.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)建谴垫,如:

  1. assemble構(gòu)建版本名
  2. assemble構(gòu)建類型名
  3. assemble產(chǎn)品渠道名

第1項(xiàng)允許你直接構(gòu)建單個(gè)的版本章母,例如aseembleFlavor1Debug

第2項(xiàng)允許你構(gòu)建所有已給構(gòu)建類型的apk文件翩剪。例如assembleDebug將會(huì)構(gòu)建flavor1Debugflavor2Debug乳怎。

第3項(xiàng)允許你構(gòu)建給定渠道的所有APK文件。例如前弯,assembleFlavor1將會(huì)構(gòu)建assembleFlavor1DebugassembleFlavor1Release蚪缀。

任務(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站超,LibraryVariantTestVariant領(lǐng)域?qū)ο蠹?/a>乖酬。

注意到死相,訪問以上三種集合的任意一種都會(huì)引發(fā)所有任務(wù)的創(chuàng)建。這意味著在訪問集合后不會(huì)發(fā)生任何重新配置的情況咬像。
領(lǐng)域?qū)ο蠹现苯釉L問所有對(duì)象算撮,或者通過更方便的過濾器。

android.applicationVariants.all { variant ->
   ....
}

所有版本類都含有以下屬性:

  1. name 類型為String县昂,表示版本名稱肮柜,要求不重復(fù)。
  2. description 類型為String倒彰,人類可讀的版本描述审洞。
  3. dirName 類型為String,版本的子文件夾名稱待讳,要求不重復(fù)芒澜∷跞可能會(huì)有多個(gè)文件夾,例如”debug/flavor”撰糠。
  4. baseName 類型為String酥馍,輸出版本的基本名稱,要求不重復(fù)阅酪。
  5. outputFile 類型為File旨袒,版本的輸出。擁有讀/寫屬性术辐。
  6. processManifest 類型為ProcessManifest砚尽,用于處理清單的任務(wù)。
  7. aidlCompile 類型為AidlCompile辉词,編譯AIDL文件的任務(wù)必孤。
  8. renderscriptCompile 類型為RenderscriptCompile,編譯Renderscript的任務(wù)瑞躺。
  9. mergeResources 類型為MergeResources敷搪,合并資源文件的任務(wù)。
  10. mergeAssets 類型為MergeAssets幢哨,合并assets的任務(wù)赡勘。
  11. processResources 類型為ProcessAndroidResources,用于處理和編譯資源的任務(wù)捞镰。
  12. generateBuildConfig 類型為GenerateBuildConfig,生成BuildConfig類的任務(wù)
  13. javaCompile 類型為JavaCompile闸与,編譯Java代碼的任務(wù)。
  14. processJavaResources 類型為Copy岸售,處理Java資源的任務(wù)践樱。
  15. assemble 類型為DefaultTask,對(duì)版本輸出的祖先任務(wù)凸丸。
    ApplicationVariant類添加了如下內(nèi)容:
  16. buildType 類型為BuildType拷邢,版本的構(gòu)建類型。
  17. productFlavors 類型為L(zhǎng)ist<ProductFlavor>,版本的產(chǎn)品渠道可以不設(shè)置但是永遠(yuǎn)不為空甲雅。
  18. mergedFlavor 類型為ProductFlavor,android.defaultConfig和variant.productFlavors的合并解孙。
  19. signingConfig 類型為SigningConfig,該版本的簽名配置。
  20. isSigningReady 類型為boolean抛人。為真時(shí)該版本擁有簽名的所有必需信息弛姜。
  21. testVariant 類型為BuildVariant。TestVariant會(huì)測(cè)試該版本妖枚。
  22. dex 類型為Dex廷臼,編譯代碼的任務(wù)。如果是個(gè)庫(kù)項(xiàng)目可以為空。
  23. packageApplication 類型為PackageApplication荠商,構(gòu)建最終APK的任務(wù)寂恬。如果是個(gè)庫(kù)項(xiàng)目可以為空。
  24. zipAlign 類型為ZipAlign莱没。打包apk的任務(wù)初肉,如果是個(gè)庫(kù)項(xiàng)目或者APK不能被簽名時(shí)可以為空。
  25. install 類型為DefaultTask饰躲,安裝任務(wù)牙咏,可以為空。
  26. unstall 類型為DefaultTask嘹裂,卸載任務(wù)妄壶。
    LibraryVariant類添加了一下內(nèi)容:
  27. buildType 類型為BuildType,版本的構(gòu)建類型寄狼。
  28. mergedFlavor 類型為ProductFlavor丁寄,默認(rèn)配置值。
  29. testVariant 類型為BuildVariant泊愧,要測(cè)試的構(gòu)建版本伊磺。
  30. packageLibrary 類型為Zip,打包庫(kù)AAR壓縮包的任務(wù)拼卵,如果不是庫(kù)項(xiàng)目則為空奢浑。
    TestVariant類添加了如下內(nèi)容:
  31. buildType 類型為BuildType,版本的構(gòu)建類型腋腮。
  32. productFlavors 類型為L(zhǎng)ist<ProductFlavor>,版本的產(chǎn)品渠道可以不設(shè)置但是永遠(yuǎn)不為空。
  33. mergedFlavor 類型為ProductFlavor,android.defaultConfig和variant.productFlavors的合并壤蚜。
  34. signingConfig 類型為SigningConfig,該版本的簽名配置即寡。
  35. isSigningReady 類型為boolean。為真時(shí)該版本擁有簽名的所有必需信息袜刷。
  36. testVariant 類型為BuildVariant聪富。TestVariant會(huì)測(cè)試該版本。
  37. dex 類型為Dex著蟹,編譯代碼的任務(wù)墩蔓。如果是個(gè)庫(kù)項(xiàng)目可以為空。
  38. packageApplication 類型為PackageApplication萧豆,構(gòu)建最終APK的任務(wù)奸披。如果是個(gè)庫(kù)項(xiàng)目可以為空。
  39. zipAlign 類型為ZipAlign涮雷。打包apk的任務(wù)阵面,如果是個(gè)庫(kù)項(xiàng)目或者APK不能被簽名時(shí)可以為空。
  40. install 類型為DefaultTask,安裝任務(wù)样刷,可以為空仑扑。
  41. unstall 類型為DefaultTask,卸載任務(wù)置鼻。
  42. connectedAndroidTest 類型為DefaultTask镇饮,在連接設(shè)備上運(yùn)行Android測(cè)試的任務(wù)。
  43. 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
    }
}
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市枉证,隨后出現(xiàn)的幾起案子矮男,更是在濱河造成了極大的恐慌,老刑警劉巖刽严,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件昂灵,死亡現(xiàn)場(chǎng)離奇詭異避凝,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)眨补,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門管削,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人撑螺,你說我怎么就攤上這事含思。” “怎么了甘晤?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵含潘,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我线婚,道長(zhǎng)遏弱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任塞弊,我火速辦了婚禮漱逸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘游沿。我一直安慰自己饰抒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布诀黍。 她就那樣靜靜地躺著袋坑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪眯勾。 梳的紋絲不亂的頭發(fā)上枣宫,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音咒精,去河邊找鬼镶柱。 笑死,一個(gè)胖子當(dāng)著我的面吹牛模叙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鞋屈,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼范咨,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了厂庇?” 一聲冷哼從身側(cè)響起渠啊,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎权旷,沒想到半個(gè)月后替蛉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年躲查,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了它浅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡镣煮,死狀恐怖姐霍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情典唇,我是刑警寧澤镊折,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站介衔,受9級(jí)特大地震影響恨胚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜炎咖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一赃泡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧塘装,春花似錦急迂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至阴幌,卻和暖如春勺阐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背矛双。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國(guó)打工渊抽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人议忽。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓懒闷,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親栈幸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子愤估,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,071評(píng)論 25 707
  • 轉(zhuǎn)載注明出處:http://www.reibang.com/p/5255b100930e 0. 前言 完全由個(gè)人翻...
    王三的貓阿德閱讀 2,514評(píng)論 0 4
  • 這一章主要針對(duì)項(xiàng)目中可以用到的一些實(shí)用功能來介紹Android Gradle,比如如何隱藏我們的證書文件速址,降低風(fēng)險(xiǎn)...
    acc8226閱讀 7,606評(píng)論 3 25
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,803評(píng)論 6 342
  • 一大早起床玩焰,準(zhǔn)備早餐,洗衣芍锚,掃地拖地昔园,七點(diǎn)喊孩子起床蔓榄,監(jiān)督刷牙洗臉,吃早餐默刚。 8:50準(zhǔn)時(shí)趕到跆...
    李思睿vicky閱讀 258評(píng)論 0 0