在使用Android Studio過(guò)程中沒(méi)少被Gradle坑過(guò)藐石,雖然網(wǎng)上有很多簡(jiǎn)單粗暴的解決方案,但極少會(huì)說(shuō)清楚緣由梅割,所以一直想看一本叫《Android Gradle權(quán)威指南》扇调。
不過(guò)由于書(shū)中實(shí)踐內(nèi)容很多,更像一本工具書(shū)沪伙,而且Gradle現(xiàn)已發(fā)行了好幾版,因此本篇僅僅是陳列出一些大的要點(diǎn)县好,尤其是那些熟悉又陌生的名詞围橡,如果想要具體了解細(xì)節(jié)和操作流程,一定要跟著書(shū)探索喲~
- Gradle入門(mén)
- Groovy基礎(chǔ)
- Gradle構(gòu)建腳本基礎(chǔ)
- Gradle插件
- Java Gradle插件
- Android Gradle插件
1.本書(shū)環(huán)境
- JDK:OpenJDK 1.8.0
- Gradle:Gradle 2.14.1 All 版
- IDE:Android Studio 2.2.3
- Android Plugin:Android Gradle 2.2.3
- Android:API 23
2.Eclipse和Android Studio
a.開(kāi)發(fā)配置區(qū)別:
- Eclipse+ADT+Ant
- Android Studio+Gradle:Gradle比Ant更靈活缕贡,有效提高開(kāi)發(fā)效率
b.Eclipse遷移到AndroidStudio兩種方式:
- 使用AndroidStudio直接導(dǎo)入Eclipse工程
- 特點(diǎn):使用AS默認(rèn)推薦目錄結(jié)構(gòu)
- 使用Eclipse導(dǎo)出Android Gradle配置文件翁授,并轉(zhuǎn)換成Gradle工程,再使用Android Studio把它作為Gradle工程導(dǎo)入
- 特點(diǎn):保留原項(xiàng)目結(jié)構(gòu)
3.Gradle的ZIP解壓后目錄
- docs:API晾咪、 DSL收擦、指南等文檔
- init.d:gradle初始化腳本目錄
- lib:相關(guān)庫(kù)
- media:一些icon資源
- samples:示例
- src:源文件
- getting-started.html:入門(mén)鏈接
- LICENSE
NOTICE
4.引例:Gradle版Hello World
//build.gradle:
task hello{//定義一個(gè)任務(wù)Task名為hello
doLast{//添加一個(gè)動(dòng)作Action,表示在Task執(zhí)行完畢后回調(diào)doLast閉包中的代碼
println'Hello World'//輸出字符串谍倦,單雙號(hào)均可
}
}
//終端:
gradle hello//執(zhí)行build.gradle中名為Hello的任務(wù)
//輸出:
Hello World
5.Gradle Wrapper
a.含義:對(duì)Gradle一層包裝炬守,便于使用統(tǒng)一Gradle構(gòu)建
b.目錄結(jié)構(gòu):
|--gradle
| |--wrapper
| |--gradle-wrapper.jar
| |--gradle-wrapper.properties
|--gradlew
|--gradlew.bat
-
gradle-wrapper.jar
:具體業(yè)務(wù)邏輯實(shí)現(xiàn)的jar包 -
gradle-wrapper.properties
:配置文件,包含篇配置信息如下圖:
-
gradlew
:Linux下可執(zhí)行腳本 -
gradlew.bat
:Windows下可執(zhí)行腳本
c.常用命令:
- 生成:
gradle wrapper
剂跟,由Wrapper Task生成 - 配置參數(shù):
-
gradle wrapper --gradle-version XXX
用于指定使用的Gradle版本 -
gradle wrapper --distribution-url XXX
用于指定下載Gradle發(fā)行版的url地址
-
- 自定義:
task wrapper(type:Wrapper){ //配置信息 }
6.Gradle日志
a.日志級(jí)別:
b.日志輸出代碼:
- 使用print方法,屬于quiet級(jí)別日志:
println 'XX'X
- 使用內(nèi)置logger:
c.日志輸出控制:
例如酣藻,輸出QUIET級(jí)別及其之上的日志信息:gradle -q tasks
7.Gradle命令行
- 查看所有可執(zhí)行tasks:
./gradlew tasks
- 強(qiáng)制刷新依賴(lài):
./gradlew --refresh-dependencies assemble
- 多任務(wù)調(diào)用:
./gradlew clean jar
- 查看幫助:
./gradlew -?
或./gradlew -h
或./gradlew -help
一句話表明Groovy的地位:Groovy于Gradle曹洽,好比Java于Android
1.特性:Groovy是個(gè)靈活的動(dòng)態(tài)腳本語(yǔ)言,語(yǔ)法和Java很相似辽剧,又兼容Java送淆,且在此基礎(chǔ)上增加了很多動(dòng)態(tài)類(lèi)型和靈活的特性,如支持閉包和DSL
2.語(yǔ)法
- 分號(hào)不必需
- 字符串:?jiǎn)我?hào)和雙引號(hào)均可定義一個(gè)字符串常量怕轿,區(qū)別在于單引號(hào)不能對(duì)字符串表達(dá)式做運(yùn)算偷崩,而雙引號(hào)可以
task printStringVar << {
def name = "張三”
println '單引號(hào)的變量計(jì)算:${name}'
println "雙引號(hào)的變量計(jì)算:${name}"
}
運(yùn)行./gradlew printStringVar輸出結(jié)果:
單引號(hào)的變量計(jì)算:${name}
雙引號(hào)的變量計(jì)算:張三
- 集合:以List和Map為例辟拷,介紹如何定義集合和訪問(wèn)集合元素
//List
task printList<<{
def numList = [1,2,3,4,5,6];//定義一個(gè)List
println numList[1]//輸出第二個(gè)元素
println numList[-1]//輸出最后一個(gè)元素
println numList[1..3]//輸出第二個(gè)到第四個(gè)元素
numList.each{
println it//輸出每個(gè)元素
}
}
//Map
task printlnMap<<{
def map1 =['width':1024,'height':768]//定義一個(gè)Map
println mapl['width']//輸出width的值
println mapl.height//輸出height的值
map1.each{
println "Key:${it.key},Value:${it.value}"http://輸出所有鍵值對(duì)
}
}
- 方法:方法調(diào)用傳參的括號(hào)可省略;return不必需阐斜,無(wú)return時(shí)會(huì)將最后一行代碼作為其返回值衫冻;允許將代碼塊(閉包)作為參數(shù)傳遞
//以集合的each方法為例,接受的參數(shù)就是一個(gè)閉包
numList.each({println it})
//省略傳參的括號(hào)谒出,并調(diào)整格式隅俘,有以下常見(jiàn)形式
numList.each{
println it
}
- 不是一定要定義成員變量才能作為類(lèi)屬性被訪問(wèn),用get/set方法也能當(dāng)作類(lèi)屬性
task helloJavaBean<<{
Person p = new Person()
p.name = "張三"
println "名字是: ${p.name}"http://輸出類(lèi)屬性name笤喳,為張三
println "年齡是: ${p.age}"http://輸出類(lèi)屬性age为居,為12
}
class Person{
private String name
public int getAge(){//省略return
12
}
}
- 閉包:當(dāng)閉包有一個(gè)參數(shù)時(shí),默認(rèn)為it杀狡,多個(gè)參數(shù)時(shí)需要一一羅列
//單個(gè)參數(shù)
task helloClosure<<{
customEach{
println it
}
}
def customEach(closure){
for(int i in 1..10){
closure(i)
}
}
//多個(gè)參數(shù)
task helloClosure<<{
eachMap{k,v->
println "${k} is ${v}"
}
}
def eachMap(closure){
def map1 = ["name":"張三","age":18]
map1.each{
closure(it.key,it.value)
}
}
1.Settings文件
- 作用:初始化蒙畴、設(shè)置工程樹(shù)
-
文件名:
settings.gradle
,放在Project下 - 常用方法:include方法指定能被Gradle識(shí)別的Module
//添加:app和:common這兩個(gè)module參與構(gòu)建
include ':app'
project(':app').projectDir = new File('存放目錄')
include':common'
project(':common').projectDir = new File('存放目錄')
2.Build文件
- Project的
build.gradle
:整個(gè)Project的共有屬性呜象,包括配置版本膳凝、插件、依賴(lài)庫(kù)等信息 - Module的
build.gradle
:各個(gè)module私有的配置文件
a.含義:指原子性操作
b.關(guān)系:一個(gè)Gradle可包含多個(gè)Project董朝,一個(gè) Project可包含多個(gè)Task鸠项,即每個(gè)Project是由多個(gè)Task組成的;Task是Project的屬性子姜,屬性名就是任務(wù)名
c.創(chuàng)建
- 以任務(wù)名創(chuàng)建:接受一個(gè)name參數(shù)
def task myTask = task(myTask)
myTask.doLast{
println "第一種創(chuàng)建Task方法祟绊,原型為T(mén)ask task(String name) throws InvalidUserDataException"
}
-
以任務(wù)名+Map創(chuàng)建:Map參數(shù)用于對(duì)創(chuàng)建的task進(jìn)行配置,可用配置如下圖
def task myTask = task(myTask,group:BasePlugin.BUILD_GROUP)
myTask.doLast{
println "第二種創(chuàng)建Task方法哥捕,原型為T(mén)ask task(String name,Map<String,?> args) throws InvalidUserDataException"
}
- 以任務(wù)名+閉包創(chuàng)建:常見(jiàn)形式
task myTask{
doLast{
println "第三種創(chuàng)建Task方法牧抽,原型為T(mén)ask task(String name,Closure configureClosure)"
}
}
以上創(chuàng)建方式實(shí)際上最終都會(huì)調(diào)用
TaskContainter#create()
方法,使用./gradlew myTask
命令執(zhí)行任務(wù)
d.訪問(wèn)
- 通過(guò)任務(wù)名訪問(wèn):
名稱(chēng).方法
- 通過(guò)TaskContainter訪問(wèn):
tasks['名稱(chēng)'].方法
- 通過(guò)路徑訪問(wèn):參數(shù)可以為路徑或名稱(chēng)
- get方式:
tasks.getByPath('路徑/名稱(chēng)')
遥赚,若不存在會(huì)拋出UnknownTaskException異常 - find方式:
tasks.findByPath('路徑/名稱(chēng)')
扬舒,若不存在返回null
- get方式:
- 通過(guò)名稱(chēng)訪問(wèn):參數(shù)只能為名稱(chēng)
- get方式:
tasks.getByName('名稱(chēng)')
,若不存在會(huì)拋出UnknownTaskException異常 - find方式:
tasks.findByName('名稱(chēng)')
凫佛,若不存在返回null
- get方式:
可見(jiàn)任務(wù)名稱(chēng)是唯一的讲坎,這是因?yàn)門(mén)askContainer的父類(lèi) NamedDomainObjectCopllection是個(gè)具有唯一不變名字的域?qū)ο蟮募?/p>
e.依賴(lài):在創(chuàng)建任務(wù)時(shí)通過(guò)dependsOn指定其依賴(lài)的任務(wù),可以控制任務(wù)的執(zhí)行順序
task task1<<{
println 'hello'
}
task task2<<{
println 'world'
}
//依賴(lài)單個(gè)任務(wù)
task task3(dependsOn:task1){
doLast{
println 'one'
}
}
//依賴(lài)多個(gè)任務(wù)
task task4{
dependsOn task1,task2
doLast{
println 'two'
}
}
當(dāng)執(zhí)行task4時(shí)愧薛,會(huì)發(fā)現(xiàn)task1晨炕、task2會(huì)先執(zhí)行,再執(zhí)行task4
注:操作符<< 用在Task定義上相當(dāng)于doLast
f.排序:除了通過(guò)強(qiáng)依賴(lài)來(lái)控制任務(wù)的執(zhí)行順序毫炉,還可以通過(guò) shouldRunAfter
和 mustRunAfter
實(shí)現(xiàn)
taskB.shouldRunAfter(taskA) //表示taskB應(yīng)該在taskA執(zhí)行之后執(zhí)行瓮栗,有可能不會(huì)按預(yù)設(shè)執(zhí)行
taskB.mustRunAfter(taskA) //表示taskB必須在taskA執(zhí)行之后執(zhí)行
g.分組& 描述:分組是對(duì)任務(wù)的分類(lèi),便于歸類(lèi)整理;描述是說(shuō)明任務(wù)的作用费奸;建議兩個(gè)一起配置弥激,便于快速了解任務(wù)的分類(lèi)和用途
def task myTask = task(myTask)
myTask .group = BasePlugin.BUILD_GROUP
myTask .description = '這是一個(gè)構(gòu)建的引導(dǎo)任務(wù)'
h.啟用 & 禁用:enable屬性可以啟動(dòng)和禁用任務(wù),執(zhí)行被禁用的任務(wù)輸出提示該任務(wù)被跳過(guò)
def task myTask = task(myTask)
myTask.enable = false //禁用任務(wù)
i.執(zhí)行分析:執(zhí)行Task的時(shí)候?qū)嶋H上是執(zhí)行其擁有的actions List愿阐,它是Task對(duì)象實(shí)例的成員變量微服;在創(chuàng)建任務(wù)時(shí)Gradle會(huì)解析其中被TaskAction注解的方法作為其Task執(zhí)行的action,并添加到 actions List换况,其中doFirst和doList會(huì)被添加到action List第一位和最后一位
4.自定義屬性
Project职辨、Task和SourceSet都允許用戶添加額外的自定義屬性、并對(duì)自定義屬性進(jìn)行讀取和設(shè)置
- 方式:通過(guò)ext屬性戈二,添加多個(gè)通過(guò)ext代碼塊
- 優(yōu)點(diǎn):相比局部變量有廣泛的作用域舒裤,可以跨Project、跨Task訪問(wèn)觉吭,只要能訪問(wèn)這些屬性所屬的對(duì)象即可
//給Project添加自定義屬性
ext.age = 18
ext{
phone = 13888888888
address = 'Beijing'
}
//給Task添加自定義屬性
task customProperty {
ext.inner = 'innnnnner'
doLast{
println project.hasProperty('customProperty') //true
println project.hasProperty('age') //true
println project.hasProperty('inner')//返回fasle
println "${age}"
println "${phone}"
println "${inner}"
}
}
四.Gradle插件
1.作用
- 可以添加任務(wù)到項(xiàng)目腾供,比如測(cè)試、編譯鲜滩、打包等
- 可以添加依賴(lài)配置到項(xiàng)目伴鳖,幫助配置項(xiàng)目構(gòu)建過(guò)程中需要的依賴(lài),比如第三方庫(kù)等
- 可以向項(xiàng)目中現(xiàn)有的對(duì)象類(lèi)型添加新的擴(kuò)展屬性和方法等徙硅,幫助配置和優(yōu)化構(gòu)建
- 可以對(duì)項(xiàng)目進(jìn)行一些約定榜聂,比如約定源代碼存放位置等
Gradle本身內(nèi)置許多常用的插件,如若需要還可以擴(kuò)展現(xiàn)有插件或者自定義插件嗓蘑,如Android Gradle插件就是基于內(nèi)置的Java插件實(shí)現(xiàn)的
2.擴(kuò)展現(xiàn)有插件
a.插件種類(lèi)
- 二進(jìn)制插件:實(shí)現(xiàn)
org.gradle.api.Plugin
接口的插件须肆,可以有plugin id - 腳本插件:嚴(yán)格上只是一個(gè)腳本,可以來(lái)自本地或網(wǎng)路
b.應(yīng)用插件:通過(guò)Project#apply()
方法桩皿,有三種用法
- Map參數(shù):
void apply (Map<String, ?> options)
- 二進(jìn)制插件:
- id:
apply plugin:'java'
- 類(lèi)型:
apply plugin:org.gradle.api.plugins.JavaPlugin
- 簡(jiǎn)寫(xiě):
apply plugin:JavaPlugin
- id:
- 腳本插件:
apply from:'version.gradle'
- 第三方發(fā)布插件:
apply plugin:'com.android.application'
- 二進(jìn)制插件:
注意:應(yīng)用第三方發(fā)布的作為jar的二進(jìn)制插件時(shí)豌汇,必須先在
buildscript{}
配置其classpath才能使用,否則會(huì)提示找不到該插件
//buildscript:為項(xiàng)目進(jìn)行前提準(zhǔn)備和初始化相關(guān)配置依賴(lài)
buildscript {
repositories {
jcenter ()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.0"
}
}
apply plugin:'com.android.application
- 閉包:
void apply (Closure closure)
apply {
plugin:'java'
}
- Action:
void apply (Action<? super ObjectConfigurationActicn> action)
3.自定義插件:實(shí)現(xiàn)Plugin接口泄隔、重寫(xiě)apply()方法
1.項(xiàng)目結(jié)構(gòu)
使用Java插件要先應(yīng)用進(jìn)來(lái):
apply plugin:'java'
此時(shí)會(huì)添加許多默認(rèn)設(shè)置和約定拒贱,比如有以下默認(rèn)項(xiàng)目結(jié)構(gòu):
|-example
| |-build.gradle
| |-src
| |-main
| |-java 源代碼存放目錄
| |-resources 打包文件存放目錄
| |-test
| |-java 單元測(cè)試用例存放目錄
| |-resources 單元測(cè)試中使用的文件
2.源集(SourceSet)
- 作用:用于描述和管理源代碼(java)及其資源(resources),如訪問(wèn)源代碼目錄佛嬉、設(shè)置源集屬性逻澳、更改Java原代碼目錄等
-
方式:通過(guò)
sourceSets
屬性(是一個(gè)SourceSetsContainer)和sourceSets{}
閉包 -
常用屬性:
比如,在上述Java插件默認(rèn)項(xiàng)目結(jié)構(gòu)中的main和test就是內(nèi)置的兩個(gè)源集暖呕,現(xiàn)在更改main源集的Java源文件的存放目錄到src/java下:
apply plugin:'java'
sourceSets{
main{
java{
srcDir 'src/java'
}
}
}
-
定義新源集:通過(guò)
sourceSets{}
閉包添加
apply plugin:'java'
sourceSets{
vip{
}
}
此時(shí)會(huì)新建兩個(gè)目錄:src/vip/java和src/vip/resources
補(bǔ)充:除了SourceSet斜做,Java插件里常用的其他屬性:
3.配置第三方依賴(lài)
a.依賴(lài)方式
- 外部依賴(lài):依賴(lài)外部倉(cāng)庫(kù),如Maven缰揪、Ivy等
- 項(xiàng)目依賴(lài):依賴(lài)項(xiàng)目,依賴(lài)后可以使用該項(xiàng)目的Java類(lèi)
- 文件依賴(lài):如依賴(lài)Jar包,出于安全考慮不發(fā)布到Maven而是放在項(xiàng)目的libs文件夾下
b.具體方法
- 對(duì)于外部依賴(lài)钝腺,需要先在
repositories{}
閉包里聲明依賴(lài)庫(kù)的位置 - 在
dependencies{}
閉包添加依賴(lài)- 外部依賴(lài):說(shuō)明依賴(lài)庫(kù)的
group:name:version
- 項(xiàng)目依賴(lài):
project('項(xiàng)目名稱(chēng)')
- 文件依賴(lài):
files('文件名稱(chēng)')
抛姑,多個(gè)文件逗號(hào)分開(kāi),或者fileTree(dir:'文件名稱(chēng)',include:'*.擴(kuò)展名稱(chēng)')
依賴(lài)指定文件夾下指定擴(kuò)展名文件
- 外部依賴(lài):說(shuō)明依賴(lài)庫(kù)的
-
幾種依賴(lài)類(lèi)型
舉例:
apply plugin:'java'
repositories {
//外部依賴(lài) 依賴(lài)Maven中心庫(kù)
maveCentral()
}
dependencies {
//外部依賴(lài) 完整寫(xiě)法
compile group:'com.squareup.okhttp3',name:'okhttp', version:'3.0.1'
//外部依賴(lài) 簡(jiǎn)單寫(xiě)法
compile 'com.squareup.okhttp3:okhttp:3.0.1'
//外部依賴(lài) 指定main源集依賴(lài)
mainCompile 'com.squareup.okhttp3:okhttp:3.0.1'
//項(xiàng)目依賴(lài)
compile project(':example')
//文件依賴(lài) 依賴(lài)libs下兩個(gè)Jar包
compile files('libs/example01.jar', 'libs/example02.jar')
//文件依賴(lài) 指定依賴(lài)libs下所有Jar包
compile fileTree(dir: 'libs',include: '*.jar')
}
4.內(nèi)置任務(wù)
常用幾種任務(wù):
-
build
任務(wù):構(gòu)建項(xiàng)目 -
clean
任務(wù):刪除build目錄及構(gòu)建生成的文件 -
assemble
任務(wù):不執(zhí)行單元測(cè)試艳狐,只編譯和打包 -
check
任務(wù):只執(zhí)行單元測(cè)試 -
javadoc
任務(wù):生成Java格式的doc api文檔
還有些通用任務(wù)定硝、對(duì)源集適用的任務(wù):
5.多項(xiàng)目構(gòu)建
- 含義:多個(gè)Gradle項(xiàng)目一起構(gòu)建
-
方式:通過(guò)
settings.gradle
配置管理多項(xiàng)目;在每個(gè)項(xiàng)目都有一個(gè)build.gradle
毫目,采用項(xiàng)目依賴(lài)就能實(shí)現(xiàn)多項(xiàng)目協(xié)作
//settings.gradle
include ':app'
project(':app').projectDir = new File('存放目錄')
include ':base'
project(':base').projectDir = new File('存放目錄')
//app/build.gradle
apply plugin:'java'
dependencies {
compile project(':base')
}
6.發(fā)布構(gòu)件
- 構(gòu)件:Gradle構(gòu)建的產(chǎn)物蔬啡,如Jar包、Zip包等
- 意義:發(fā)布構(gòu)建給其他工程使用镀虐,可以發(fā)布到本地目錄箱蟆、Maven、Ivy等
-
方式:明確構(gòu)件類(lèi)型刮便,并通過(guò)
artifacts{}
閉包配置需要發(fā)布的構(gòu)建空猜,在uploadArchives{}
上傳發(fā)布構(gòu)件
//以發(fā)布jar構(gòu)件為例
apply plugin:'java '
task publishJar(type:Jar)
artifacts{
archives publishJar
}
uploadArchives{
repositories{
//發(fā)布到本地目錄
flatDir{
name 'libs'
dirs "$projectDir/libs"
}
//發(fā)布到本地Maven庫(kù)
mavenLocal()
}
}
1.概述
Android Gradle插件繼承于Java插件,具有Java插件的所有特性恨旱,也有自己的特性辈毯,看下官方介紹:
- 可以很容易地重用代碼和資源
- 可以很容易地創(chuàng)建應(yīng)用的衍生版本
- 可以很容易地配置、擴(kuò)展以及自定義構(gòu)建過(guò)程
- 和IDE無(wú)縫整合
2.插件分類(lèi)
-
App應(yīng)用工程:生成可運(yùn)行apk應(yīng)用搜贤;id:
com.android.application
-
Library庫(kù)工程:生成aar包給其他的App工程公用谆沃;id:
com.android.library
-
Test測(cè)試工程:對(duì)App應(yīng)用工程或Library庫(kù)工程進(jìn)行單元測(cè)試;id:
com.android.test
3.項(xiàng)目結(jié)構(gòu)
|-example
| |-build.gradle
| |-example.iml
| |-libs
| |-proguard-rules.pro 混淆配置文件
| |-src
| |-androidTest
| |-java Android單元測(cè)試代碼
| |-main
| |-java App主代碼
| |-res 資源文件
| |-AndroidManifest.xml 配置文件
| |-test
| |-java 普通單元測(cè)試代碼
4.內(nèi)置任務(wù)
- Java插件內(nèi)置任務(wù):如build仪芒、assemble唁影、check等
- Android特有的常用任務(wù):
-
connectedCheck
任務(wù):在所有連接的設(shè)備或者模擬器上運(yùn)行check檢查 -
deviceCheck
任務(wù):通過(guò)API連接遠(yuǎn)程設(shè)備運(yùn)行checks -
lint
任務(wù):在所有ProductFlavor上運(yùn)行l(wèi)int檢查 -
install
、uninstall
任務(wù):在已連接的設(shè)備上安裝或者卸載App -
signingReport
任務(wù):打印App簽名 -
androidDependencies
任務(wù):打印Android 依賴(lài)
-
//應(yīng)用插件桌硫,Android Gradle屬于Android發(fā)布的第三方插件
buildscript{
repositories{
jcenter()
}
dependencies{
classpath 'com.android.tcols.build:gradle:1.5.0'
}
}
apply plugin:'com.android.application'
//自定義配置入口夭咬,后續(xù)詳解
android{
compileSdkVersion 23 //編譯Android工程的SDK版本
buildToolsVersion "23.0.1" //構(gòu)建Android工程所用的構(gòu)建工具版本
defaultConfig{
applicationId "org.minmin.app.example"
minSdkVersion 14
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes{
release{
minifyEnabled false
proguardFiles getDefaultPraguardFile('proguard-andrcid.txt'), 'proguard-rules.pro'
}
}
}
//配置第三方依賴(lài)
dependencies{
compile fileTree(dir:'libs', include:['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcorpat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
}
a.defaultConfig
- 作用:用于定義所有的默認(rèn)配置,是一個(gè)ProductFlavor铆隘,若ProductFlavor沒(méi)有被特殊定義卓舵,默認(rèn)使用defaultConfig塊指定的配置
- 常用配置:
屬性名 | 含義 |
---|---|
applicationId | 指定App包名 |
minSdkVersion | 指定App最低支持的Android SDK |
targetSdkVersion | 指定基于的Android SDK |
versionCode | 配置Android App的內(nèi)部版本號(hào) |
versionName | 配置Android App的版本名稱(chēng) |
testApplicationId | 配置測(cè)試App的包名,默認(rèn)為applicationId + “.test” |
testInstrumentationRunner | 配置單元測(cè)試使用的Runner膀钠,默認(rèn)為android.test.InstrumentationTestRunner |
proguardFile | 配置App ProGuard混淆所使用的ProGuard配置文件 |
proguardFiles | 同時(shí)配置多個(gè)ProGuard配置文件 |
signingConfig | 配置默認(rèn)的簽名信息掏湾,也是一個(gè)ProductFlavor,可直接配置 |
b.buildTypes
- 作用:是構(gòu)建類(lèi)型肿嘲,在Android Gradle中內(nèi)置了debug和release兩個(gè)構(gòu)建類(lèi)型融击,差別在于能否在設(shè)備上調(diào)試和簽名不同
- 每一個(gè)BuildType都會(huì)生成一個(gè)SourceSet以及相應(yīng)的
assemble<BuildTypeName>
任務(wù) - 常用配置:
屬性名 | 含義 |
---|---|
applicationIdSuffix | 配置基于默認(rèn)applicationId的后綴 |
debuggable | 是否生成一個(gè)可供調(diào)試的Apk |
jniDebuggable | 是否生成一個(gè)可供調(diào)試JNI代碼的Apk |
minifyEnabled | 是否啟用Proguard混淆 |
multiDexEnabled | 是否啟用自動(dòng)拆分多個(gè)Dex的功能 |
zipAlignEnabled | 是否開(kāi)啟開(kāi)啟zipalign優(yōu)化,提高apk運(yùn)行效率 |
shrinkResources | 是否自動(dòng)清理未使用的資源雳窟,默認(rèn)為false |
proguardFile | 配置Proguard混淆使用的配置文件 |
proguardFiles | 同時(shí)配置多個(gè)ProGuard配置文件 |
signingConfig | 配置默認(rèn)的簽名信息尊浪,也是一個(gè)ProductFlavor匣屡,可直接配置 |
c.signingConfigs
- 作用:配置簽名設(shè)置,標(biāo)記App唯一性拇涤、保護(hù)App
- 可以對(duì)不同構(gòu)建類(lèi)型采用不同簽名方式:debug模式用于開(kāi)發(fā)調(diào)試捣作,可以直接使用Android SDK提供的默認(rèn)debug簽名證書(shū);release模式用于發(fā)布鹅士,需要手動(dòng)配置
- 常用配置:
屬性名 | 含義 |
---|---|
storeFile | 簽名證書(shū)文件 |
storePassword | 簽名證書(shū)文件的密碼 |
storeType | 簽名證書(shū)的類(lèi)型 |
keyAlias | 簽名證書(shū)中密鑰別名 |
keyPassword | 簽名證書(shū)中該密鑰的密碼 |
android {
signingConfigs {
release{
storeFile file('myFile.keystore')
storePassword 'psw'
keyAlias 'myKey'
keyPassword 'psw'
}
}
}
d.productFlavors
- 作用:添加不同的渠道券躁、并對(duì)其做不同的處理
- 常用配置:
屬性名 | 含義 |
---|---|
applicationId | 設(shè)置該渠道的包名 |
consumerProguardFiles | 對(duì)aar包進(jìn)行混淆 |
manifestPlaceholders | |
multiDexEnabled | 啟用多個(gè)dex的配置,可突破65535方法問(wèn)題 |
proguardFiles | 混淆使用的文件配置 |
signingConfig | 簽名配置 |
testApplicationId | 適配測(cè)試包的包名 |
testFunctionalTest | 是否是功能測(cè)試 |
testHandleProfiling | 是否啟用分析功能 |
testInstrumentationRunner | 配置運(yùn)行測(cè)試使用的Instrumentation Runner的類(lèi)名 |
testInstrumentationRunnerArguments | 配置Instrumentation Runner使用的參數(shù) |
useJack | 標(biāo)記是否啟用Jack和Jill這個(gè)全新的掉盅、高性能的編譯器 |
dimension | 維度也拜,通過(guò)flavorDimensions方法聲明,聲明前后代表優(yōu)先級(jí) |
//定義baidu和google兩個(gè)渠道趾痘,并聲明兩個(gè)維度慢哈,優(yōu)先級(jí)為abi>version>defaultConfig
android{
flavorDimensions "abi", "version"
productFlavors{
google{
dimension "abi"
}
baidu{
dimension "version"
}
}
e.buildConfigFiled
- 作用:在buildTypes、ProductFlavor自定義字段等配置
-
方法:
buildConfigField(String type,String name,String value)
- type:字段類(lèi)型
- name:字段常量名
- value:字段常量值
android{
buildTypes{
debug{
buildConfigField "boolean", "LOG_DEBUG", "true"
buildConfigField "String", "URL", ' "http://www.ecjtu.jx.cn/" '
}
}
}
和Java Grdle多項(xiàng)目構(gòu)建一樣的扼脐,通過(guò)settings.gradle
配置管理多項(xiàng)目岸军;在每個(gè)項(xiàng)目都有一個(gè)build.gradle
,采用項(xiàng)目依賴(lài)就能實(shí)現(xiàn)多項(xiàng)目協(xié)作瓦侮。
項(xiàng)目直接依賴(lài)一般適用于關(guān)聯(lián)較緊密艰赞、不可復(fù)用的項(xiàng)目,如果想讓項(xiàng)目被其他項(xiàng)目所復(fù)用肚吏,比如公共組件庫(kù)方妖、工具庫(kù)等,可以單獨(dú)發(fā)布出去罚攀。
a.基本原理
- 構(gòu)建變體(Build Variant)=構(gòu)建類(lèi)型(Build Type)+構(gòu)建渠道(Product Flavor)
Build Type有release党觅、debug兩種構(gòu)建類(lèi)型
Product Flavor有baidu、google兩種構(gòu)建渠道
Build Variant有baiduRelease斋泄、baiduDebug杯瞻、googleRelease、googleDebug四種構(gòu)件產(chǎn)出
構(gòu)建渠道(Product Flavor)還可以通過(guò)dimension進(jìn)一步細(xì)化分組
assemble開(kāi)頭的負(fù)責(zé)生成構(gòu)件產(chǎn)物(Apk)
assembleBaidu:運(yùn)行后會(huì)生成baidu渠道的release和debug包
assembleRelease:運(yùn)行后會(huì)生成所有渠道的release包
assembleBaiduRelease:運(yùn)行后只會(huì)生成baidu的release包
b.構(gòu)建方式:通過(guò)占位符manifestPlaceholders
實(shí)現(xiàn):
//AndroidManifest
<meta-data
android: value="Channel ID"
android:name="UMENG_ CHANNEL"/>
//build.gradle
android{
productFlavors{
google{
manifestPlaceholders.put("UMENG_ CHANNEL", "google")
}
baidu{
manifestPlaceholders.put("UMENG_ CHANEL", "baidu")
}
}
//改進(jìn):通過(guò)productFlavors批量修改
android{
productFlavors{
google{
}
baidu{
}
ProductFlavors.all{ flavor->
manifestPlaceholders.put("UMENG_ CHANEL", name)
}
}
a. 使用共享庫(kù)
- android sdk庫(kù):系統(tǒng)會(huì)自動(dòng)鏈接
- 共享庫(kù):獨(dú)立庫(kù)炫掐,不會(huì)被系統(tǒng)自動(dòng)鏈接魁莉,使用時(shí)需要在AndroidManifest通過(guò)
<uses-library>
指定
//聲明需要使用maps共享庫(kù),true表示如果手機(jī)系統(tǒng)不滿足將不能安裝該應(yīng)用
<uses-library
android:name="com.google.android.maps"
android:required="true"
/>
- add-ons庫(kù):存于add-ons目錄下募胃,大部分由第三方廠商或公司開(kāi)發(fā)旗唁,會(huì)被自動(dòng)解析添加到classpath
- optional可選庫(kù):位于platforms/android-xx/optional目錄下,通常為了兼容舊版本的API痹束,使用時(shí)需要手動(dòng)添加到classpath
b. 批量修改生成的apk文件名
- 類(lèi)型:
-
applicationVariants
:僅僅適用于Android應(yīng)用Gradle插件 -
libraryVariants
:僅僅適用于Android庫(kù)Gradle插件 -
testVariants
:以上兩種Gradle插件都使用
-
-
示例:
applicationVariants
是一個(gè)DomainObjectCollection集合检疫,通過(guò)all方法遍歷每一個(gè)ApplicationVariant,這里有g(shù)oogleRelease和googleDebug兩個(gè)變體祷嘶;然后判斷名字是否以.apk結(jié)尾屎媳,如果是就修改其文件名夺溢。示例中共有。
c.動(dòng)態(tài)生成版本信息
- 原始方式:由
defaultConfig
中的versionName
指定 - 分模塊方式:把版本號(hào)等配置抽出放在單獨(dú)的文件里烛谊,并用
ext{}
括起來(lái)企垦,通過(guò)apply from將其引入到build.gradle,版本信息就被當(dāng)作擴(kuò)展屬性直接使用了 - 從git的tag中獲取
- 從屬性文件中動(dòng)態(tài)獲取和遞增
d.隱藏簽名文件信息
- 必要性:為保證簽名信息安全晒来,最好直接放在項(xiàng)目中,而是放在服務(wù)器上
-
一種思路:
- 服務(wù)器:配置好環(huán)境變量郑现,打包時(shí)直接使用
- 本地:直接使用android提供的debug簽名
- 在signingConfigs加入以下判斷
signingConfigs {
if (System.env.KEYSTORE_PATH != null) {
//打包服務(wù)器走這個(gè)邏輯
storeFile file(System.env.KEYSTORE_PATH)
keyAlias System.env.ALIAS
keyPassword System.env.KEYPASS
storePassword System.env.STOREPASS
} else {
//當(dāng)不能從環(huán)境變量取到簽名信息時(shí)梦碗,使用本地debug簽名
storeFile file('debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
}
e.動(dòng)態(tài)添加自定義的資源
- 針對(duì)res/values中的資源龄减,除了使用xml定義,還可以通過(guò)Android Gradle定義
-
方法:resValue(String type, String name, String value)
- type:資源類(lèi)型,如有string匾寝、id、bool
- name:資源名稱(chēng)毅哗,以便在工程中引用
- value:資源值
productFlavors{
google{
resValue 'string', 'channel_tips', 'google渠道歡迎你'
}
}
以google為例率寡,在debug模式下,資源文件保存目錄:build/generated/res/resValues/google/debug/values/generated.xml
f.Java編譯選項(xiàng)
通過(guò)compileOptions{}
閉包進(jìn)行編譯配置废累,可配置項(xiàng):
- encoding:配置源文件的編碼
- sourceCompatibility:配置Java源代碼的編譯級(jí)別
- targetCompatibility:配置生成Java字節(jié)碼的版本
android{
compileOptions{
encoding = 'utf-8'
sourceCompatibility = JavaVersion.VERSI0N_ 1_ 6
targetCompatibility = JavaVersion.VERSION_ 1_ 6
}
}
g. adb選項(xiàng)配置
通過(guò)adbOptions{}
閉包進(jìn)行adb配置邓梅,可配置項(xiàng):
- timeOutInMs:設(shè)置執(zhí)行adb命令的超時(shí)時(shí)間,單位毫秒
- installOptions:設(shè)置adb install安裝設(shè)置項(xiàng)
- -l:鎖定該應(yīng)用程序
- -r:替換已存在的應(yīng)用程序邑滨,即強(qiáng)制安裝
- -t:允許測(cè)試包
- -s:把應(yīng)用程序安裝到SD卡上
- -d:允許進(jìn)行降級(jí)安裝日缨,即安裝版本比手機(jī)自帶的低
- -g:為該應(yīng)用授予所有運(yùn)行時(shí)的權(quán)限
android{
adbOptions{
timeOutInMs = 5*1000
installOptions '-r', '-s'
}
}
h.DEX選項(xiàng)配置
通過(guò)dexOptions {}
閉包進(jìn)行dex配置,可配置項(xiàng):
- incremental:配置是否啟用dx的增量模式掖看,默認(rèn)值為false
- javaMaxHeapSize:配置執(zhí)行dx命令時(shí)為其分配的最大堆內(nèi)存
- jumboMode:配置是否開(kāi)啟jumbo模式
- preDexLibraries:配置是否預(yù)dex Libraries庫(kù)工程匣距,默認(rèn)值為true,開(kāi)啟后會(huì)提高增量構(gòu)建的速度
- threadCount:配置Android Gradle運(yùn)行dx命令時(shí)使用的線程數(shù)量