轉(zhuǎn)至:http://blog.csdn.net/heqiangflytosky/article/details/50853268
Gradle是一種構(gòu)建工具,它拋棄了基于XML的構(gòu)建腳本,取而代之的是采用一種基于Groovy的內(nèi)部領(lǐng)域特定語言,建議可以先熟悉一下Groovy腳本。
gradle明明一般是./gradlew +參數(shù),gradlew代表gradle wrapper,意思是gradle的一層包裝,大家可以理解為在這個項(xiàng)目本地就封裝了gradle,即gradle wrapper, 在gradle/wrapper/gralde-wrapper.properties文件中聲明了它指向的目錄和版本。只要下載成功即可用grdlew wrapper的命令代替全局的gradle命令。
./gradlew -v版本號
./gradlew clean清除app目錄下的build文件夾
./gradlew build檢查依賴并編譯打包
這里注意的是./gradlew build命令把debug、release環(huán)境的包都打出來,如果正式發(fā)布只需要打Release的包,該怎么辦呢,下面介紹一個很有用的命令assemble, 如:
./gradlew assembleDebug編譯并打Debug包
./gradlew assembleRelease編譯并打Release的包
除此之外,assemble還可以和productFlavors結(jié)合使用:
./gradlew installReleaseRelease模式打包并安裝
./gradlew uninstallRelease卸載Release模式包
比如我們想根據(jù)不同的參數(shù)來進(jìn)行不用的編譯配置,可以在./gradlew中加入自定義參數(shù)。
./gradlew assembleDebug -Pcustom=true
就可以在build.gradle中使用下面代碼來判斷:
if(project.hasProperty('custom')){
}
1
2
3
1
2
3
assemble結(jié)合Build Variants來創(chuàng)建task
assemble還能和Product Flavor結(jié)合創(chuàng)建新的任務(wù),其實(shí)assemble是和Build Variants一起結(jié)合使用的,而Build Variants = Build Type + Product Flavor,舉個例子大家就明白了:
如果我們想打包 wandoujia 渠道的release版本,執(zhí)行如下命令就好了:
./gradlew assembleWandoujiaRelease
如果我們只打wandoujia渠道版本,則:
./gradlew assembleWandoujia
此命令會生成wandoujia渠道的Release和Debug版本
同理我想打全部Release版本:
./gradlew assembleRelease
這條命令會把Product Flavor下的所有渠道的Release版本都打出來。
總之,assemble命令創(chuàng)建task有如下用法:
assemble: 允許直接構(gòu)建一個Variant版本,例如assembleFlavor1Debug。
assemble: 允許構(gòu)建指定Build Type的所有APK,例如assembleDebug將會構(gòu)建Flavor1Debug和Flavor2Debug兩個Variant版本。
assemble: 允許構(gòu)建指定flavor的所有APK,例如assembleFlavor1將會構(gòu)建Flavor1Debug和Flavor1Release兩個Variant版本。
Gradle構(gòu)建腳本 build.gradle:
Gradle屬性文件 gradle.properties
Gradle設(shè)置文件 settings.gradle
先看整個項(xiàng)目的gradle配置文件:
buildscript {? ? repositories {? ? ? ? jcenter()? ? }? ? dependencies {? ? ? ? classpath'com.android.tools.build:gradle:1.3.0'// NOTE: Donotplace your application dependencies here; they belong? ? ? ? //inthe individualmodulebuild.gradle files? ? }}allprojects {? ? repositories {? ? ? ? jcenter()? ? }}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
內(nèi)容主要包含了兩個方面:一個是聲明倉庫的源,這里可以看到是指明的jcenter(), 之前版本則是mavenCentral(),jcenter可以理解成是一個新的中央遠(yuǎn)程倉庫,兼容maven中心倉庫,而且性能更優(yōu)。
另一個是聲明了Androidgradle plugin的版本,android studio 1.0正式版必須要求支持gradle plugin 1.0的版本
某個Moudle的gradle配置文件:
buildscript{? ? repositories {? ? ? ? maven { url'http://*********'}}? ? dependencies{? ? ? ? classpath'com.android.tools.build:gradle:1.3.1'}}
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
buildscript{}設(shè)置腳本的運(yùn)行環(huán)境。
repositories{}支持java依賴庫管理,用于項(xiàng)目依賴。
dependencies{}依賴包的定義。支持maven/ivy,遠(yuǎn)程,本地庫,也支持單文件。如果前面定義了repositories{}maven 庫,則使用maven的依賴庫,使用時只需要按照用類似于com.android.tools.build:gradle:0.4,gradle 就會自動的往遠(yuǎn)程庫下載相應(yīng)的依賴。
//聲明是Android程序apply plugin:'com.android.application'
1
2
1
2
apply plugin:聲明構(gòu)建的項(xiàng)目類型。如果是庫的話就加
apply plugin:'com.android.library'
1
1
android {// 編譯SDK的版本compileSdkVersion22// build tools的版本buildToolsVersion"23.0.1"http://aapt配置aaptOptions {//不用壓縮的文件noCompress'pak','dat','bin','notice'//打包時候要忽略的文件ignoreAssetsPattern"!.svn:!.git"http://分包multiDexEnabledtrue//--extra-packages是為資源文件設(shè)置別名:意思是通過該應(yīng)用包名+R,com.android.test1.R和com.android.test2.R都可以訪問到資源additionalParameters'--extra-packages','com.android.test1','--extra-packages','com.android.test2'}//默認(rèn)配置defaultConfig {//應(yīng)用的包名applicationId"com.example.heqiang.androiddemo"minSdkVersion21targetSdkVersion22versionCode1versionName"1.0"}//編譯配置compileOptions {// java版本sourceCompatibility JavaVersion.VERSION_1_7? ? ? ? targetCompatibility JavaVersion.VERSION_1_7? ? }//源文件目錄設(shè)置sourceSets {? ? ? ? main {//jni lib的位置jniLibs.srcDirs = jniLibs.srcDirs <<'src/jniLibs'//定義多個資源文件夾,這種情況下,兩個資源文件夾具有相同優(yōu)先級,即如果一個資源在兩個文件夾都聲明了,合并會報錯。res.srcDirs = ['src/main/res','src/main/res2']? ? ? ? }? ? }//簽名配置signingConfigs {? ? ? ? debug {? ? ? ? ? ? keyAlias'androiddebugkey'keyPassword'android'storeFilefile('keystore/debug.keystore')? ? ? ? ? ? storePassword'android'}? ? }? ? buildTypes {//release版本配置release {? ? ? ? ? ? debuggablefalse// 是否進(jìn)行混淆minifyEnabledtrue//去除沒有用到的資源文件,要求minifyEnabled為true才生效shrinkResourcestrue// 混淆文件的位置proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.txt'signingConfig signingConfigs.debug//ndk的一些相關(guān)配置,也可以放到defaultConfig里面。//指定要ndk需要兼容的架構(gòu)(這樣其他依賴包里mips,x86,arm-v8之類的so會被過濾掉)ndk {? ? ? ? ? ? ? ? abiFilter"armeabi"}? ? ? ? }//debug版本配置debug {? ? ? ? ? ? debuggabletrue// 是否進(jìn)行混淆minifyEnabledfalse//去除沒有用到的資源文件,要求minifyEnabled為true才生效shrinkResourcestrue// 混淆文件的位置proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.txt'signingConfig signingConfigs.debug//ndk的一些相關(guān)配置,也可以放到defaultConfig里面。//指定要ndk需要兼容的架構(gòu)(這樣其他依賴包里mips,x86,arm-v8之類的so會被過濾掉)ndk {? ? ? ? ? ? ? ? abiFilter"armeabi"}? ? ? ? }? ? }// lint配置lintOptions {//移除lint檢查的errorabortOnErrorfalse//禁止掉某些lint檢查disable'NewApi'}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
android{}設(shè)置編譯android項(xiàng)目的參數(shù),構(gòu)建android項(xiàng)目的所有配置都寫在這里。
除了上面寫的,在android{}塊中可以包含以下直接配置項(xiàng):
productFlavors{ }產(chǎn)品風(fēng)格配置,ProductFlavor類型
testOptions{ }測試配置,TestOptions類型
dexOptions{ }dex配置,DexOptions類型
packagingOptions{ }PackagingOptions類型
jacoco{ }JacocoExtension類型。 用于設(shè)定 jacoco版本
splits{ }Splits類型。
幾點(diǎn)說明:
文件開頭apply plugin是最新gradle版本的寫法,以前的寫法是apply plugin: 'android', 如果還是以前的寫法,請改正過來。
minifyEnabled也是最新的語法,很早之前是runProguard,這個也需要更新下。
proguardFiles這部分有兩段,前一部分代表系統(tǒng)默認(rèn)的android程序的混淆文件,該文件已經(jīng)包含了基本的混淆聲明,免去了我們很多事,這個文件的目錄在 sdk目錄/tools/proguard/proguard-android.txt, 后一部分是我們項(xiàng)目里的自定義的混淆文件,目錄就在app/proguard-rules.txt, 如果你用Studio 1.0創(chuàng)建的新項(xiàng)目默認(rèn)生成的文件名是proguard-rules.pro, 這個名字沒關(guān)系,在這個文件里你可以聲明一些第三方依賴的一些混淆規(guī)則。最終混淆的結(jié)果是這兩部分文件共同作用的。
aaptOptions更多介紹http://blog.csdn.net/heqiangflytosky/article/details/51009123
repositories {? ? flatDir {? ? ? ? //本地jar依賴包路徑dirs'../../../../main/libs'}}
1
2
3
4
5
6
1
2
3
4
5
6
dependencies {? ? ? ? compilefiles('libs/android-support-v4.jar')//在flatDir.dirs下面找依賴的aarcompile (name:'ui', ext:'aar')// 編譯extras目錄下的ShimmerAndroid模塊compile project(':extras:ShimmerAndroid')// 編譯CommonSDK模塊,但是去掉此模塊中對com.android.support的依賴,防止重復(fù)依賴報錯compile (project(':CommonSDK')) { exclude group:"com.android.support"}? ? ? ? provided fileTree(dir:'src/android5/libs',include: ['*.jar'])? ? ? ? provided'com.android.support:support-v4:21.0.3'provided project(':main-host')}
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
compile和provided
compile表示編譯時提供并打包進(jìn)apk。
provided表示只在編譯時提供,不打包進(jìn)apk。
exclude防止重復(fù)依賴
include
CommonSDK模塊的定義可以參考settings.gradle
其他的介紹可以參考 依賴庫管理。
看到上面的兩個一模一樣的repositories和dependencies了嗎?他們的作用是不一樣的,在buildscript里面的那個是插件初始化環(huán)境用的,用于設(shè)定插件的下載倉庫,而外面的這個是設(shè)定工程依賴的一些模塊和遠(yuǎn)程library的下載倉庫的。
這個文件是全局的項(xiàng)目配置文件,里面主要聲明一些需要加入gradle的module。
一般在setting.gradle中主要是調(diào)用include方法,導(dǎo)入工程下的各個子模塊。
那我們在setting.gradle里面還能寫什么呢?因?yàn)閟etting.gradle對應(yīng)的是gradle中的Settings對象,那查下Settings的文檔(https://docs.gradle.org/current/dsl/org.gradle.api.initialization.Settings.html),看下它都有哪些方法,哪些屬性,就知道在setting.gradle能寫什么了;
include':AndroidDemo'include':CommonSDK'project(':CommonSDK').projectDir =newFile(settingsDir,'../../CommonSDK/')
1
2
3
4
1
2
3
4
include調(diào)用后,生成了一個名為:CommonSDK的Project對象,project(':CommonSDK')取出這個對象,設(shè)置Project的projectDir屬性。projectDir哪里來的?請看Project類的文檔。
dependencies {//單文件依賴compilefiles('libs/android-support-v4.jar')//某個文件夾下面全部依賴compile fileTree(dir:'src/android6/libs',include: ['*.jar'])? ? ? ? compile (name:'ui', ext:'aar')? ? compile (project(':CommonSDK')) { exclude group:"com.android.support"}? ? ? ? provided fileTree(dir:'src/android5/libs',include: ['*.jar'])? ? ? ? provided'com.android.support:support-v4:21.0.3'provided project(':main-host')}
1
2
3
4
5
6
7
8
9
10
11
1
2
3
4
5
6
7
8
9
10
11
gradle同時支持maven,ivy,以maven作為例子:
repositories {//從中央庫里面獲取依賴mavenCentral()//或者使用指定的本地maven 庫maven{? url"file://F:/githubrepo/releases"}//或者使用指定的遠(yuǎn)程maven庫maven{? url"https://github.com/youxiachai/youxiachai-mvn-repo/raw/master/releases"} } dependencies {//應(yīng)用格式: packageName:artifactId:versioncompile'com.google.android:support-v4:r13'}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
對于項(xiàng)目依賴android library的話,在這里需要使用gradle mulit project機(jī)制。
Mulit project設(shè)置是gradle約定的一種格式,如果需要編譯某個項(xiàng)目之前,要先編譯另外一個項(xiàng)目的時候,就需要用到。結(jié)構(gòu)如下(來自于官方文檔):
MyProject/| settings.gradle+ app/| build.gradle+ libraries/? + lib1/| build.gradle+ lib2/| build.gradle
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
需要在workplace目錄下面創(chuàng)建settings.gradle的文件,然后在里面寫上:
include':app',':libraries:lib1',':libraries:lib2'
1
1
例如:
include':AndroidDemo'include':CommonSDK'project(':CommonSDK').projectDir =newFile(settingsDir,'../../CommonSDK/')
1
2
3
4
1
2
3
4
如此,gradle mutil project 就設(shè)置完畢。
對于app project如果需要應(yīng)用libraries目錄下的lib1,只需要在app project的build.gradle文件里的依賴中這么寫:
compileproject(':libraries:lib1')
1
1
類似前面的
providedproject(':main-host')
1
1
即可完成,寫完以后可以用gradle AndroidDependencies可以檢查依賴狀況
主要借助
android{
productFlavors{
……
}}
1
2
3
4
5
1
2
3
4
5
來實(shí)現(xiàn)。
網(wǎng)上多是類似友盟的配置,copy過來:
http://blog.csdn.net/maosidiaoxian/article/details/42000913
https://segmentfault.com/a/1190000004050697
在AndroidManifest.xml里面寫上:
1
2
3
1
2
3
里面的Channel_ID就是渠道標(biāo)示。我們的目標(biāo)就是在編譯的時候這個值能夠自動變化。
android {? ? ? productFlavors {? ? ? ? xiaomi {? ? ? ? ? ? manifestPlaceholders = [UMENG_CHANNEL_VALUE:"xiaomi"]? ? ? ? }? ? ? ? _360 {? ? ? ? ? ? manifestPlaceholders = [UMENG_CHANNEL_VALUE:"_360"]? ? ? ? }? ? ? ? baidu {? ? ? ? ? ? manifestPlaceholders = [UMENG_CHANNEL_VALUE:"baidu"]? ? ? ? }? ? ? ? wandoujia {? ? ? ? ? ? manifestPlaceholders = [UMENG_CHANNEL_VALUE:"wandoujia"]? ? ? ? }? ? }? }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
或者批量修改
android {? ? ? productFlavors {? ? ? ? xiaomi {}? ? ? ? _360 {}? ? ? ? baidu {}? ? ? ? wandoujia {}? ? }? ? ? productFlavors.all{? ? ? ? flavor -> flavor.manifestPlaceholders= [UMENG_CHANNEL_VALUE: name]? ? }}
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
然后用./gradlew assembleRelease這條命令會把Product Flavor下的所有渠道的Release版本都打出來。
assemble: 允許構(gòu)建指定flavor的所有APK,例如assembleFlavor1將會構(gòu)建Flavor1Debug和Flavor1Release兩個Variant版本。
在上面當(dāng)中,我們也可以指定一個默認(rèn)的渠道名,如果需要的話。指定默認(rèn)的值是在defaultConfig節(jié)點(diǎn)當(dāng)中添加如下內(nèi)容:
manifestPlaceholders =[ CHANNEL_NAME:"Unspecified"]
1
1
這里的Unspecified換成你實(shí)際上的默認(rèn)的渠道名。
使用manifestPlaceholders的這種配置,同樣適用于manifest的其他配置。比如你需要在不同渠道發(fā)布的apk里面,指定不同的啟動Activity。比如在豌豆莢里面發(fā)布的,啟動的Activity顯示的是豌豆莢首發(fā)的界面,應(yīng)用寶里面啟動的是應(yīng)用寶首發(fā)的界面(哈哈,有點(diǎn)壞),你就可以對你的activity的值使用{activity_name}的方式,然后在productFlavors里面配置這個{activity_name}的值。
我們可以在項(xiàng)目的根目錄創(chuàng)建一個gradle配置文件config.gradle,內(nèi)容如下:
ext{? ? android=[? ? ? ? ? ? compileSdkVersion:22,? ? ? ? ? ? buildToolsVersion:"23.0.1",? ? ? ? ? ? minSdkVersion:21,? ? ? ? ? ? targetSdkVersion:22,? ? ? ? ? ? versionCode:1,? ? ? ? ? ? versionName:"1.0"]? ? dependencies=[? ? ? ? ? ? compile:'com.android.support:support-v4:21.0.3',? ? ? ? ? ? compile: (project(':CommonSDK')) { excludegroup:"com.android.support"},? ? ? ? ? ? provided: fileTree(dir:'src/android5/libs', include: ['*.jar']),? ? ? ? ? ? provided: project(':main-host')? ? ]}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
targetSdkVersion的版本還有依賴庫的版本升級都在這里進(jìn)行統(tǒng)一管理,所有的module以及主項(xiàng)目都從這里同意讀取就可以了。
在build.gradle文件中加入:
applyfrom:"config.gradle"
1
1
意思是所有的子項(xiàng)目或者所有的modules都可以從這個配置文件中讀取內(nèi)容。
android節(jié)點(diǎn)讀取ext中android對應(yīng)項(xiàng),dependencies讀取dependencies對應(yīng)項(xiàng),如果配置有變化就可以只在config.gradle中修改,是不是很方便進(jìn)行配置的管理的。