Android Gradle 指南

簡(jiǎn)介

Gradle 是用了一種基于 Groovy 的領(lǐng)域特定語(yǔ)言(DSL,Domain Specific Language)來(lái)聲明項(xiàng)目設(shè)置,摒棄了 XML(如 ANT 和 Maven)的各種繁瑣配置。

對(duì)于 Groovy 和 Gradle 的深入理解,這里推薦一篇非常好的博客:深入理解 Android 之 Gradle

Gradle 選擇了 Groovy 這門動(dòng)態(tài)語(yǔ)言。Groovy 基于 Java 并拓展了 Java雅采。 Java 程序員可以無(wú)縫切換到使用 Groovy 開發(fā)程序。Groovy 說(shuō)白了就是把寫 Java 程序變得像寫腳本一樣簡(jiǎn)單慨亲。寫完就可以執(zhí)行婚瓜, Groovy 內(nèi)部會(huì)將其編譯成 Javaclass 然后啟動(dòng)虛擬機(jī)來(lái)執(zhí)行。

總的來(lái)說(shuō)刑棵,Gradle 基于 Groovy 實(shí)現(xiàn)了一套編程框架巴刻,所以我們可以在 Gradle 配置中通過(guò)編程的方式靈活的去配置我們的構(gòu)建過(guò)程。Gradle 本質(zhì)上是執(zhí)行一系列項(xiàng)目構(gòu)建過(guò)程铐望,也就是所謂的自動(dòng)化冈涧。為了更好地利用 Gradle茂附,除了要知道 Gradle 如何使用之外正蛙,我們更要熟悉正在開發(fā)的項(xiàng)目的構(gòu)建過(guò)程。

Android 項(xiàng)目的 .gradle 文件

在 Android Studio 新建一個(gè)項(xiàng)目营曼,生成如下目錄 ↓

├── app #Android App目錄
│   ├── app.iml
│   ├── build #構(gòu)建輸出目錄
│   ├── build.gradle #構(gòu)建腳本
│   ├── libs #so相關(guān)庫(kù)
│   ├── proguard-rules.pro #proguard混淆配置
│   └── src #源代碼乒验,資源等
├── build
│   └── intermediates
├── build.gradle #工程構(gòu)建文件
├── gradle
│   └── wrapper
├── gradle.properties #gradle的配置
├── gradlew #gradle wrapper linux shell腳本
├── gradlew.bat
├── LibSqlite.iml
├── local.properties #配置Androod SDK位置文件
└── settings.gradle #工程配置

觀察目錄,會(huì)生成以下三個(gè) .gradle 文件 ↓



接下來(lái)逐一講解蒂阱。

1. settings.gradle

用于配置 project锻全,標(biāo)明該項(xiàng)目有哪些 module 需要構(gòu)建,如下录煤,則代表包含一個(gè) :app module

include ':app'
2. 工程目錄下的 build.gradle

和 settings.gradle 同處于根目錄下的 build.gradle 是一個(gè)頂級(jí)的 build 配置文件鳄厌,在這里可以為所有 project 以及 module 配置一些常用的配置。

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        // 代碼托管倉(cāng)庫(kù)
        jcenter()
    }
    dependencies {
        // Gradle 插件及使用版本
        classpath 'com.android.tools.build:gradle:3.2.1'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        // 代碼托管倉(cāng)庫(kù)
        jcenter()
    }
}

// 運(yùn)行g(shù)radle clean時(shí)妈踊,執(zhí)行此處定義的task了嚎。  
// 該任務(wù)繼承自Delete,刪除根目錄中的build目錄。  
// 相當(dāng)于執(zhí)行Delete.delete(rootProject.buildDir)  
task clean(type: Delete) {
    delete rootProject.buildDir
}

可以看到代碼中有兩處 repositories歪泳,且閉包中都生明了 jcenter() 這個(gè)配置萝勤,其實(shí)它是一個(gè)代碼托管倉(cāng)庫(kù),很多開源的 Android 項(xiàng)目都會(huì)選擇將代碼托管到到 jcenter() 上呐伞,聲明了這個(gè)配置敌卓,我們就可以輕松地引用 jcenter() 上任何的開源項(xiàng)目了。接下來(lái)伶氢,dependencies 閉包中使用 classpath 聲明了一個(gè) Gradle 插件趟径,這是因?yàn)?Gradle 并不是專門為構(gòu)建 Android 項(xiàng)目而開發(fā)的,Java鞍历、C++ 等很多項(xiàng)目都可以使用 Gradle 來(lái)構(gòu)建舵抹,因此我們?nèi)绻胍褂盟鼇?lái)構(gòu)建 Android 項(xiàng)目必須聲明,其中最后的數(shù)字部分是 Gradle 插件的版本號(hào)劣砍,到這里我們工程目錄下的 build.gradle 就分析完了惧蛹,通常情況下,這個(gè)文件中的內(nèi)容不需要修改刑枝,但是當(dāng)我們模塊化開發(fā)的時(shí)候香嗓,也可以在這里配置全局項(xiàng)目的構(gòu)建相關(guān)的配置。

3. app 目錄下的 build.gradle
// 表明是應(yīng)用程序的插件
apply plugin: 'com.android.application'

// Android 閉包
android {
    compileSdkVersion 28 // 指定項(xiàng)目的編譯版本
    defaultConfig {
        applicationId "com.example.chenguiyan.justtest" // 指定項(xiàng)目的包名
        minSdkVersion 15 // 指定項(xiàng)目最低兼容的安卓版本
        targetSdkVersion 28 // 指定項(xiàng)目目標(biāo)兼容的安卓版本
        versionCode 1 // 指定項(xiàng)目的版本號(hào)
        versionName "1.0" // 指定項(xiàng)目的版本名
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            // 指定是否對(duì)項(xiàng)目的代碼進(jìn)行混淆(true:混淆 false:不混淆)
            minifyEnabled false
            // proguardFiles 用于指定混淆時(shí)使用的規(guī)則文件
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

首先第一行應(yīng)用了一個(gè)插件装畅,這里一般有兩種值可選 ↓

  • com.android.application: 表示是一個(gè)應(yīng)用程序模塊(可以直接運(yùn)行)
  • com.android.library: 表示是一個(gè)庫(kù)模塊(只能作為代碼庫(kù)依附于別的應(yīng)用程序模塊來(lái)運(yùn)行)

接下來(lái)是一個(gè) android 閉包靠娱,在這個(gè)閉包中可以配置項(xiàng)目構(gòu)建的各種屬性,其中 compileSdkVersion 用于指定項(xiàng)目的編譯版本掠兄。

在 android 閉包中有嵌套了一個(gè) defaultConfig 閉包像云,defaultConfig 閉包中可以對(duì)項(xiàng)目的更多細(xì)節(jié)進(jìn)行配置,其中蚂夕,applicationId 用于指定項(xiàng)目的包名迅诬,其實(shí)我們?cè)陧?xiàng)目創(chuàng)建的時(shí)候已經(jīng)進(jìn)行過(guò)指定,如果想后來(lái)進(jìn)行修改婿牍,就可以在這里進(jìn)行修改侈贷,minSdkVersion 用于指定項(xiàng)目的最低兼容 Android 系統(tǒng)版本,這里指定的是 15 表示最低兼容到 Android 4.0 系統(tǒng)等脂,targetSdkVersion 指定的值表示你在該目標(biāo)版本上已經(jīng)做過(guò)充分的測(cè)試俏蛮,系統(tǒng)將會(huì)為你的應(yīng)用程序啟用最新的功能和特性,例如 android 6.0 系統(tǒng)中引入了運(yùn)行時(shí)權(quán)限這個(gè)功能上遥,如果你將 targetSdkVersion 指定成 23 或更高搏屑,那么系統(tǒng)就會(huì)為你的程序啟用運(yùn)行時(shí)權(quán)限功能,而如果你將 targetSdkVersion 指定成 22粉楚,那么就說(shuō)明你的程序最高只能在 Android 5.1 系統(tǒng)上做過(guò)充分的測(cè)試辣恋,Android 6.0 系統(tǒng)中引入的新功能自然就不會(huì)啟用了。剩下的兩個(gè)屬性 versionCode 用于指定項(xiàng)目的版本號(hào),versionName 用于指定項(xiàng)目的版本名抑党,這兩個(gè)屬性在生成安裝包的時(shí)候特別重要包警。

分析完 defaultConfig 閉包,我們接著來(lái)分析 buildTypes 閉包底靠,buildTypes 閉包中用于指定生成安裝文件的相關(guān)配置害晦,通常會(huì)有兩個(gè)子閉包,一個(gè)是 debug暑中,一個(gè)是 release壹瘟。debug 閉包用于指定生成測(cè)試版安裝文件的配置,release 閉包用于指定生成正式版安裝文件的配置鳄逾,另外 debug 閉包是可以忽略不寫的稻轨,因此我們看到上面的代碼中就只有一個(gè) release 閉包。接著我們看一下 release 閉包中的內(nèi)容雕凹,minifyEnabled 用于指定是否對(duì)項(xiàng)目的代碼進(jìn)行混淆殴俱,true 表示混淆,false 表示不混淆枚抵,proguardFiles 用于指定混淆時(shí)使用的規(guī)則文件线欲,這里可以指定兩個(gè)文件,第一個(gè) proguard-android.txt 是在 Android SDK 目錄下的汽摹,里面是所有項(xiàng)目通用的混淆規(guī)則李丰,第二個(gè) proguard-rules.pro 是當(dāng)前項(xiàng)目的根目錄下的,里面可以編寫當(dāng)前項(xiàng)目特有的混淆規(guī)則逼泣,需要注意的是趴泌,通過(guò) Android Studio 直接運(yùn)行的項(xiàng)目生成的都是測(cè)試版安裝文件。

下面還有一個(gè) dependencies 閉包拉庶,這個(gè)閉包的功能非常強(qiáng)大嗜憔,它主要是用來(lái)指定當(dāng)前項(xiàng)目所有的依賴關(guān)系,通常 Android Studio 項(xiàng)目一共有 3 種依賴方式:本地依賴砍的,遠(yuǎn)程依賴和庫(kù)依賴痹筛。本地依賴可以對(duì)本地的 Jar 包或目錄添加依賴關(guān)系莺治,遠(yuǎn)程依賴則可以對(duì) jcenter 庫(kù)上的開源項(xiàng)目添加依賴關(guān)系廓鞠,庫(kù)依賴可以對(duì)項(xiàng)目中的庫(kù)模塊添加依賴關(guān)系。implementation fileTree 就是一個(gè)本地依賴聲明谣旁,它表示將 libs 目錄下所有 .jar 后綴的文件都添加項(xiàng)目的構(gòu)建路徑中床佳,而 com.android.support:appcompat-v7:28.0.0 就是一個(gè)標(biāo)準(zhǔn)的遠(yuǎn)程依賴庫(kù)格式,其中 com.android.support 是域名部分榄审,用于和其他公司的庫(kù)做區(qū)分砌们,appcompat-v7 是組名稱,用于和同一個(gè)公司中不同的庫(kù)做區(qū)分,28.0.0 是版本號(hào)浪感,用于和同一個(gè)庫(kù)的不同版本做區(qū)分昔头,加上這句聲明后,Gradle 在構(gòu)建項(xiàng)目時(shí)會(huì)首先檢查一下本地是否已經(jīng)有這個(gè)庫(kù)的緩存影兽,如果沒有的話則會(huì)去自動(dòng)聯(lián)網(wǎng)下載揭斧,然后再添加到項(xiàng)目的構(gòu)建路徑中。而庫(kù)依賴聲明的基本格式是 implementation project 后面加上要依賴的庫(kù)名稱峻堰,另外的 testCompile 是用于聲明測(cè)試用例庫(kù)的讹开。

Gradle 多項(xiàng)目構(gòu)建

定義

前面的內(nèi)容講解只是基于創(chuàng)建項(xiàng)目后自動(dòng)生成的文件,整個(gè)工程里的 module 也只有 app 這個(gè)文件夾捐名。而現(xiàn)實(shí)情況里旦万,中大型的安卓軟件開發(fā) 為了提高可維護(hù)性和防止緊密耦合,可以基于特定的功能和邏輯將代碼寫在不同的模塊中镶蹋。模塊通常具有層次結(jié)構(gòu)而且可以定義為相互依賴成艘。Gradle對(duì)構(gòu)建多模塊項(xiàng)目提供了強(qiáng)大的支持,Gradle中的每一模塊都是一個(gè)項(xiàng)目贺归,我們稱之為多項(xiàng)目構(gòu)建狰腌。
注意:在Android Studio中,一個(gè)模塊和一個(gè)項(xiàng)目是有區(qū)別的牧氮。一個(gè)項(xiàng)目包含多個(gè)模塊module琼腔。而Android Studio中的每一個(gè)module對(duì)應(yīng)的是Gradle多項(xiàng)目構(gòu)建中的一個(gè)項(xiàng)目。

步驟

假若我們現(xiàn)在要構(gòu)建一個(gè)多項(xiàng)目工程踱葛,文件夾目錄如下 ↓

rootProject
      |———— settings.gradle
      |———— build.gradle
      |———— sub_project1
      |            |———— build.gradle
      |———— sub_project2
      |            |———— build.gradle
  1. 在多項(xiàng)目構(gòu)建中丹莲,根目錄下的 settings.gradle 文件聲明了所需的配置來(lái)實(shí)例化項(xiàng)目的層次結(jié)構(gòu)。該腳本的執(zhí)行是在構(gòu)建生命周期的初始化階段尸诽。Gradle 組裝構(gòu)建之前會(huì)創(chuàng)建一個(gè) Settings 類型的實(shí)例甥材。Settings 接口是 settings 文件的直接表示。若想使每個(gè)子項(xiàng)目都稱為構(gòu)建的一部分性含,則可以調(diào)用 Settings 接口中帶有項(xiàng)目路徑參數(shù)的 include 方法洲赵。
include ':sub_project1', ':sub_project2'

初始化階段,gradle 會(huì)尋找到這個(gè) settings.gradle 文件商蕴。如果該文件不存在叠萍,那么 gradle 就會(huì)假定你只有一個(gè)單獨(dú)的構(gòu)建模塊。如果你有多個(gè)模塊绪商,且 settings.gradle 文件定義了這些模塊的位置苛谷。如果這些子目錄包含了其自己的 build.gradle 文件,gradle 將會(huì)運(yùn)行它們格郁,并且將他們合并到構(gòu)建任務(wù)中腹殿。

  1. 之后在根目錄下的 build.gradle 里定義子模塊行為以及描述項(xiàng)目的一些公共插件独悴、屬性、依賴等锣尉。
方法名 描述
allprojects 配置當(dāng)前模塊以及所有子模塊行為
subprojects 配置所有子模塊行為
project 配置指定子模塊行為

舉個(gè)栗子 ↓

// 所有模塊都采用統(tǒng)一的版本號(hào)以及groupName
allprojects {
    group = 'org.pkaq.gradle.multi'
    version = "0.1.0"
}
// 為所有子模塊都應(yīng)用java插件
subprojects {
   apply plugin: 'java'
}
// 為 sub_project1 模塊定義特定行為,采用war插件并且依賴base模塊
project(':sub_project1') {
    apply plugin: 'war'
    dependencies {
        compile  project(':base')
    }
}
  1. 分離配置:當(dāng)項(xiàng)目足夠復(fù)雜的時(shí)候刻炒,采用集中化配置顯然不是一個(gè)好計(jì)謀。此時(shí)自沧,將不同項(xiàng)目的定制行為分離到各自的腳本里無(wú)疑會(huì)顯著的減輕根目錄 build.gradle 的負(fù)擔(dān)落蝙。這不僅可以是項(xiàng)目結(jié)構(gòu)看起來(lái)更加清晰,腳本更加易讀暂幼,分離化的配置還可以讓我們更好地關(guān)注子模塊的特定行為筏勒。要分離模塊配置只需要很簡(jiǎn)單的兩步:
  • 在子模塊建立 build.gradle 文件。
  • 將原來(lái)的 project(':xxx'){} 內(nèi)的腳本移動(dòng)到上面建立的文件中去旺嬉。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末管行,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子邪媳,更是在濱河造成了極大的恐慌捐顷,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,013評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件雨效,死亡現(xiàn)場(chǎng)離奇詭異迅涮,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)徽龟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門叮姑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人据悔,你說(shuō)我怎么就攤上這事传透。” “怎么了极颓?”我有些...
    開封第一講書人閱讀 152,370評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵朱盐,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我菠隆,道長(zhǎng)兵琳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,168評(píng)論 1 278
  • 正文 為了忘掉前任骇径,我火速辦了婚禮躯肌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘既峡。我一直安慰自己羡榴,他們只是感情好碧查,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評(píng)論 5 371
  • 文/花漫 我一把揭開白布运敢。 她就那樣靜靜地躺著校仑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪传惠。 梳的紋絲不亂的頭發(fā)上迄沫,一...
    開封第一講書人閱讀 48,954評(píng)論 1 283
  • 那天,我揣著相機(jī)與錄音卦方,去河邊找鬼羊瘩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛盼砍,可吹牛的內(nèi)容都是我干的尘吗。 我是一名探鬼主播,決...
    沈念sama閱讀 38,271評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼浇坐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼睬捶!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起近刘,我...
    開封第一講書人閱讀 36,916評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤擒贸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后觉渴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體介劫,經(jīng)...
    沈念sama閱讀 43,382評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評(píng)論 2 323
  • 正文 我和宋清朗相戀三年案淋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了座韵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,989評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡踢京,死狀恐怖回右,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情漱挚,我是刑警寧澤翔烁,帶...
    沈念sama閱讀 33,624評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站旨涝,受9級(jí)特大地震影響蹬屹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜白华,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評(píng)論 3 307
  • 文/蒙蒙 一慨默、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧弧腥,春花似錦厦取、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)铡买。三九已至,卻和暖如春霎箍,著一層夾襖步出監(jiān)牢的瞬間奇钞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工漂坏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留景埃,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,401評(píng)論 2 352
  • 正文 我出身青樓顶别,卻偏偏與公主長(zhǎng)得像谷徙,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子驯绎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評(píng)論 2 345

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

  • 在 Android Studio 構(gòu)建的項(xiàng)目中蒂胞,基于 Gradle 進(jìn)行項(xiàng)目的構(gòu)建,同時(shí)使用 Android DS...
    Ant_way閱讀 7,327評(píng)論 0 16
  • 目前為止条篷,我們已經(jīng)學(xué)習(xí)了如何修改Gradle構(gòu)建屬性骗随,以及如何運(yùn)行任務(wù)。本章赴叹,我們會(huì)深入了解這些屬性鸿染,并且創(chuàng)建我們...
    sollian閱讀 2,596評(píng)論 0 8
  • 這一章主要針對(duì)項(xiàng)目中可以用到的一些實(shí)用功能來(lái)介紹Android Gradle,比如如何隱藏我們的證書文件乞巧,降低風(fēng)險(xiǎn)...
    acc8226閱讀 7,564評(píng)論 3 25
  • 說(shuō)明 本文主要介紹和Gradle關(guān)系密切涨椒、相對(duì)不容易理解的配置,偏重概念介紹绽媒。部分內(nèi)容是Android特有的(例如...
    jzj1993閱讀 15,573評(píng)論 1 62
  • Gradle 是一款構(gòu)建系統(tǒng)工具蚕冬,它的 DSL 基于 Groovy 實(shí)現(xiàn)。Gradle 構(gòu)建的大部分功能都是通過(guò)插...
    任教主來(lái)也閱讀 3,041評(píng)論 3 6