1.build.gradle講解
首先我將一個(gè)demo項(xiàng)目中的一份build.gradle拿出來講解下
apply plugin: 'com.android.application'
apply plugin: 'com.jakewharton.butterknife'
android {
//簽名配置
signingConfigs {
//簽名Name
config {
//簽名別名
keyAlias 'gjn'
//簽名別名密碼
keyPassword '11223344'
//簽名文件位置
storeFile file('D:/project/MyDemo/gjnKey.jks')
//簽名密碼
storePassword '11223344'
}
}
//開發(fā)環(huán)境版本號(hào)
compileSdkVersion 26
//默認(rèn)配置
defaultConfig {
//Id
applicationId "com.gjn.mydemo"
//最小支持版本號(hào)
minSdkVersion 19
//運(yùn)行版本號(hào)
targetSdkVersion 25
//appCode
versionCode 1
//app版本號(hào)
versionName "1.0"
//測(cè)試相關(guān)
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
//Build類型 默認(rèn)有release和debug兩個(gè)版本
buildTypes {
release {
//是否開始混淆
minifyEnabled false
//混淆文件路徑
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
//打包時(shí)候調(diào)用的簽名
signingConfig signingConfigs.config
//在BuildConfig生成一個(gè)String類型的Host=release_Host
//即 public static final String Host = "release_Host";
buildConfigField "String", "Host", "\"release_Host\""
//編譯之后會(huì)在res文件中的string.xml中加入一個(gè)string類型的app_name1=myMode
//即 <string name="app_name1">myMode</string>
resValue "string", "app_name1", "myMode"
//修改build之后的app名稱
//這邊編譯出來的名字是 release_1.0.apk
//這個(gè)寫法是Android Studio 3.0之后的方法
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "${variant.name}_${variant.versionName}.apk"
}
}
}
debug {
//為Id添加后綴 這邊生成新的Id為com.gjn.mydemo.debug
applicationIdSuffix ".debug"
//這邊下面和上面是一樣
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField("String", "Host", "\"debug_Host\"")
resValue("string", "app_name1", "myModedebug")
//占位符 替換AndroidManifest.xml 中的${test_key}字符
//AndroidManifest.xml中的源代碼為
//<meta-data android:name="TEST_KEY" android:value="${test_key}"/>
//替換之后
//<meta-data android:name="TEST_KEY" android:value="debug_key"/>
manifestPlaceholders = ["test_key": "debug_key"]
}
}
//多版本
productFlavors{
//dev版本
dev{
manifestPlaceholders = ["test_key": "release_key"]
}
//free版本
free{
//這邊在提下敌厘,由于free也會(huì)有release和debug兩個(gè)版本
//release的Id為com.gjn.mydemo.free
//debug的Id為com.gjn.mydemo.free.debug
applicationIdSuffix ".free"
manifestPlaceholders = ["test_key": "free_key"]
}
}
//遍歷了全部版本
productFlavors.all{
//設(shè)置統(tǒng)一Code Android Studio 3.0之后需要設(shè)置這個(gè)屬性 不然構(gòu)建多版本的時(shí)候會(huì)報(bào)錯(cuò)
flavorDimensions("versionCode")
}
}
//導(dǎo)入第三方之類的jar aar 等 就不說了
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support:design:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
implementation 'com.jakewharton:butterknife:8.7.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.7.0'
implementation 'com.github.bumptech.glide:glide:3.7.0'
implementation 'com.google.code.gson:gson:2.8.0'
implementation 'com.squareup.okhttp3:okhttp:3.8.1'
implementation 'io.reactivex.rxjava2:rxjava:2.1.1'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
}
我將大部分內(nèi)容都設(shè)置了備注,可以看到很多常用的屬性設(shè)置朽合。還有許多其他的俱两,后續(xù)在補(bǔ)充
2.Groovy講解
這邊我稍微對(duì)Groovy的語法和邏輯說一點(diǎn)!
首先說下
關(guān)于注釋之類和java是一樣的
- 字符串
在java中就只有一種"android"
而Groovy中有
單行'android'
, "android"
多行 '''android'''
, """android""
還有/.../
曹步,${...}
- 集合(List宪彩,Map)
List
創(chuàng)建和初始化
def list = [1,'hello',false]
這邊不需要List中的每個(gè)類型都相同,當(dāng)然Map也一樣讲婚。
使用
println list[1] //輸出 hello
println list[-1] //輸出 false
list[1] = 5 //5 替換 hello
list[0] = "android" //android 替換 1
list << "gjn" //追加 gjn
list.each { l -> //遍歷整個(gè)list
println l //每次輸出一項(xiàng)
}
結(jié)果
hello
false
android
5
false
gjn
Map
創(chuàng)建和初始化
def map = [1:'hello',android:233,b:false]
使用
println map[1] //輸出 hello
println map.b //輸出 false
map << [2:33] //追加 2:33
map.each { k,v-> //遍歷map
println k+":"+v
}
結(jié)果
hello
false
1:hello
android:233
b:false
2:33
- 數(shù)組
關(guān)于數(shù)組
groovy 其實(shí)沒有嚴(yán)格區(qū)分?jǐn)?shù)組和集合尿孔,數(shù)組的定義和使用方法跟集合一樣,只是你需要強(qiáng)制聲明為數(shù)組筹麸,否則默認(rèn)為集合活合。
創(chuàng)建和初始化
String[] arrString = ['hello',"android","""groovy
=============="""]
def arrNum = [1,2,3] as int[]
直接String[]和Java一樣是創(chuàng)建數(shù)組
as int[]是把a(bǔ)rrNum設(shè)置為數(shù)組,不然就會(huì)變成集合
使用
arrString.each {str->
println str
}
arrNum.each {num->
println num
}
結(jié)果
hello
android
groovy
==============
1
2
3
-
遍歷
groovy中的遍歷有2個(gè)each{...}
和all{...}
遍歷在上面的數(shù)組和集合都使用了物赶,大體上都知道使用了白指。
拿第一個(gè)說下each就是Java中的foreach
list.each { l -> //遍歷整個(gè)list
println l //每次輸出一項(xiàng)
}
其實(shí)就等于Java中的
List<String> list = new ArrayList<>();
for(String l : list){
System.out.println(l);
}
all和each的使用是一樣的,區(qū)別我查了下酵紫,有提到是each使用的是迭代告嘲,不能實(shí)時(shí)修改值错维,all使用的是拾取對(duì)象,可以修改值橄唬。好比ArrayList和CopyOnWriteArrayList的區(qū)別吧赋焕!
我也不太確定,只是在 Android Gradle 3.0.0-alpha2 plugin, Cannot set the value of read-only property 'outputFile'
中有看到仰楚。
- 方法簡(jiǎn)化使用
groovy的一個(gè)特性
groovy 定義方法時(shí)可以不聲明返回類型和參數(shù)類型隆判,也可以不需要 return 語句,最后一行代碼默認(rèn)就是返回值缸血。使用的時(shí)候也可以不需要添加括號(hào)蜜氨。
使用1
def add(a,b){
a+b
}
def str = add 1,2
println str //結(jié)果為3
結(jié)果1
3
這邊我們就能發(fā)現(xiàn)很多在build.gradle中的參數(shù)的真實(shí)代碼
例如
compileSdkVersion 26
就是 compileSdkVersion(26)
applicationId "com.gjn.mydemo"
就是 applicationId("com.gjn.mydemo")
等等
使用2
def getmap(Map map){
map.each {
println it.key + ":" + it.value
}
}
def map = [1:"hello",2:true]
getmap map
def map2 = [add:'groovy']
getmap map2
getmap add:'groovy test'
結(jié)果2
1:hello
2:true
add:groovy
add:groovy test
這次使用我們就發(fā)現(xiàn)了一個(gè)getmap add:'groovy test'
和build.gradle中的apply plugin: 'com.android.application'
很像有沒有。
如果按照我們上面的寫法捎泻,那么原本的apply方法就是
apply plugin: 'com.android.application'
等于
def map = [plugin: 'com.android.application']
apply(map)
- 閉包
閉包是 groovy 的一大特性,例如build.gradle中的android{...}
埋哟,defaultConfig{...}
笆豁,buildTypes{...}
,dependencies{...}
等 這些都是閉包的使用
使用
def add(a,Closure c){
println a + c.call()
}
add(1,{2+3})
add 1,{
5+6
}
結(jié)果
6
12
使用2
def myprintln(Closure c){
println c.call()
}
myprintln {
123
}
myprintln {
"Msss"
}
myprintln {
123+"Msss"
}
結(jié)果2
123
Msss
123Msss
Android Studio的build.gradle代碼整合優(yōu)化
繼續(xù)來說關(guān)于build.gradle代碼優(yōu)化赤赊。這邊我們拿最開始的build.gradle代碼進(jìn)行優(yōu)化闯狱。
說是優(yōu)化,其實(shí)就是吧一些東西寫在另一個(gè)gradle文件下抛计,然后直接調(diào)用就好了哄孤。而且把部分參數(shù)寫在另一個(gè)gradle中,修改這些代碼的時(shí)候吹截,就根本不需要Sync build.gradle代碼瘦陈,也算加快了編譯速度吧!
首先我們?cè)陧?xiàng)目的project目錄下新建一個(gè)config.gradle文件
注:要讓config.gradle代碼能夠在app的build.gradle中使用波俄,在主項(xiàng)目的build.gradle中加入 apply from:'config.gradle'
表示導(dǎo)入config文件代碼
具體位置如下
apply from:'config.gradle'
buildscript {
repositories {
....
}
dependencies {
....
}
}
allprojects {
repositories {
....
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
創(chuàng)建好config.gradle文件之后寫入一個(gè)ext{}
默認(rèn)如下
ext{
}
然后我們看下晨逝,哪些可以寫在config中
這邊我選了簽名相關(guān)、APP的版本懦铺、正式版和測(cè)試版之間相同的數(shù)據(jù)設(shè)置捉貌、加載第三方庫(kù)dependencies相關(guān)這幾項(xiàng)
所以我在config中加入
ext{
SigningConfigs = [
]
DefaultConfig = [
]
Release = [
]
Debug = [
]
Dependencies = [
]
}
之后我們對(duì)比原來的build.gradle進(jìn)行配置config文件
ext{
SigningConfigs = [
keyAlias : 'gjn',
keyPassword : '11223344',
storeFile : 'D:/project/MyDemo/gjnKey.jks',
storePassword : '11223344'
]
DefaultConfig = [
versionCode : 1,
versionName : "1.0"
]
Release = [
"Host_bcf":"release_Host",
"appname_res": "myMode",
"test_key_mp": "release_key"
]
Debug = [
"Host_bcf":"debug_Host",
"appname_res": "myModedebug",
"test_key_mp": "debug_key"
]
Dependencies = [
appcompat:'com.android.support:appcompat-v7:26.1.0',
design:'com.android.support:design:26.1.0',
constraint:'com.android.support.constraint:constraint-layout:1.0.2',
butterknife:'com.jakewharton:butterknife:8.7.0',
glide:'com.github.bumptech.glide:glide:3.7.0',
gson:'com.google.code.gson:gson:2.8.0',
okhttp:'com.squareup.okhttp3:okhttp:3.8.1',
rxjava:'io.reactivex.rxjava2:rxjava:2.1.1',
rxandroid:'io.reactivex.rxjava2:rxandroid:2.0.1',
retrofit:'com.squareup.retrofit2:retrofit:2.3.0',
adapterrxjava2:'com.squareup.retrofit2:adapter-rxjava2:2.3.0',
convertergson:'com.squareup.retrofit2:converter-gson:2.3.0',
]
}
現(xiàn)在看下如何在build.gradle中使用
首先先創(chuàng)建好對(duì)應(yīng)的def
def sc = rootProject.ext.SigningConfigs
def dc = rootProject.ext.DefaultConfig
def r = rootProject.ext.Release
def d = rootProject.ext.Debug
def dep = rootProject.ext.Dependencies
之后就只要在用到的地方把原來的參數(shù)替換掉就好了
好比
//簽名配置
signingConfigs {
//簽名Name
config {
//簽名別名
keyAlias 'gjn'
//簽名別名密碼
keyPassword '11223344'
//簽名文件位置
storeFile file('D:/project/MyDemo/gjnKey.jks')
//簽名密碼
storePassword '11223344'
}
}
就變成了
//簽名配置
signingConfigs {
//簽名Name
config {
//簽名別名
keyAlias sc.keyAlias
//簽名別名密碼
keyPassword sc.keyPassword
//簽名文件位置
storeFile file(sc.storeFile)
//簽名密碼
storePassword sc.storePassword
}
}
使用是很簡(jiǎn)單的,這邊要提及下第三方庫(kù)導(dǎo)入相關(guān)冬念,這邊可以用上面學(xué)的groovy循環(huán)直接一次性全部加進(jìn)去趁窃。可以省略很多代碼急前。
直接改成
dep.each{ k,v->
implementation v
}
就等于加入了第三方引用
修改后的build.gradle如下
apply plugin: 'com.android.application'
apply plugin: 'com.jakewharton.butterknife'
def sc = rootProject.ext.SigningConfigs
def dc = rootProject.ext.DefaultConfig
def r = rootProject.ext.Release
def d = rootProject.ext.Debug
def dep = rootProject.ext.Dependencies
android {
//簽名配置
signingConfigs {
//簽名Name
config {
//簽名別名
keyAlias sc.keyAlias
//簽名別名密碼
keyPassword sc.keyPassword
//簽名文件位置
storeFile file(sc.storeFile)
//簽名密碼
storePassword sc.storePassword
}
}
//開發(fā)環(huán)境版本號(hào)
compileSdkVersion 26
//默認(rèn)配置
defaultConfig {
//Id
applicationId "com.gjn.mydemo"
//最小支持版本號(hào)
minSdkVersion 19
//運(yùn)行版本號(hào)
targetSdkVersion 25
//appCode
versionCode dc.versionCode
//app版本號(hào)
versionName dc.versionName
//測(cè)試相關(guān)
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
//Build類型 默認(rèn)有release和debug兩個(gè)版本
buildTypes {
release {
//是否開始混淆
minifyEnabled false
//混淆文件路徑
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
//打包時(shí)候調(diào)用的簽名
signingConfig signingConfigs.config
//在BuildConfig生成一個(gè)String類型的Host=release_Host
//即 public static final String Host = "release_Host";
buildConfigField "String", "Host", "\"${r.Host_bcf}\""
//編譯之后會(huì)在res文件中的string.xml中加入一個(gè)string類型的app_name1=myMode
//即 <string name="app_name1">myMode</string>
resValue "string", "app_name1", "${r.appname_res}"
//修改build之后的app名稱
//這邊編譯出來的名字是 release_1.0.apk
//這個(gè)寫法是Android Studio 3.0之后的方法
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "${variant.name}_${variant.versionName}.apk"
}
}
}
debug {
//為Id添加后綴 這邊生成新的Id為com.gjn.mydemo.debug
applicationIdSuffix ".debug"
//這邊下面和上面是一樣
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField("String", "Host", "\"${d.Host_bcf}\"")
resValue("string", "app_name1", "${d.appname_res}")
//占位符 替換AndroidManifest.xml 中的${test_key}字符
//AndroidManifest.xml中的源代碼為
//<meta-data android:name="TEST_KEY" android:value="${test_key}"/>
//替換之后
//<meta-data android:name="TEST_KEY" android:value="debug_key"/>
manifestPlaceholders = ["test_key": "${d.test_key_mp}"]
}
}
//多版本
productFlavors{
//dev版本
dev{
manifestPlaceholders = ["test_key": "${r.test_key_mp}"]
}
//free版本
free{
//這邊在提下醒陆,由于free也會(huì)有release和debug兩個(gè)版本
//release的Id為com.gjn.mydemo.free
//debug的Id為com.gjn.mydemo.free.debug
applicationIdSuffix ".free"
manifestPlaceholders = ["test_key": "free_key"]
}
}
//遍歷了全部版本
productFlavors.all{
//設(shè)置統(tǒng)一Code Android Studio 3.0之后需要設(shè)置這個(gè)屬性 不然構(gòu)建多版本的時(shí)候會(huì)報(bào)錯(cuò)
flavorDimensions("versionCode")
}
}
//導(dǎo)入第三方之類的jar aar 等 就不說了
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.7.0'
dep.each{ k,v->
implementation v
}
}
這樣就把一些build.gradle中的配置分離出來了。到時(shí)候需要修改的時(shí)候叔汁,大部分只需要修改config文件就好了统求。其實(shí)優(yōu)化下來检碗,也就導(dǎo)入第三方庫(kù)這塊算是優(yōu)化了(:з」∠)
Gradle打包
關(guān)于說打包之前,先說下Gradle的3個(gè)操作
復(fù)制Copy
刪除Delete
壓縮Zip
- Copy
下面做一個(gè)任務(wù)码邻,將/src/main/xml下的*.xml文件復(fù)制到/build/xml文件夾下
task CopyXml(type: Copy){
includeEmptyDirs = false
destinationDir = file('build')
from( 'src/main/xml') {
include '**.xml'
into ('xml')
}
}
- Delete
刪除任務(wù)就是吧剛才的文件夾刪除
task DeleteXml(type: Delete){
delete 'build/xml', 'src/main/xml'
followSymlinks = true
}
效果就不截圖了折剃。就是刪除掉了兩個(gè)文件夾
- Zip
壓縮任務(wù)。將app目錄下的app.iml文件壓縮到build目錄下的adc.zip中的zip文件夾下像屋。
task ZipTest(type: Zip){
destinationDir = file('build')
archiveName = 'abc.zip'
from('.'){
include('app.iml')
into('zip')
}
}
知道了上面3個(gè)操作怕犁。就可以開始進(jìn)行Gradle打包操作了!
以下項(xiàng)目example為例子原例子代碼
.
├── example
│ ├── build.gradle
│ ├── example.iml
│ ├── proguard-rules.pro
│ └── src
├── libs
│ ├── armeabi
│ ├── armeabi-v7a
│ ├── com.umeng.fb.5.3.0.jar
│ ├── mips
│ └── x86
├── releasenote.txt
└── res
├── anim
├── drawable
├── drawable-xhdpi
├── layout
├── values
└── values-zh
首先我們要知道己莺,打包一個(gè)jar需要哪些步驟
- 編譯工程(源代碼)導(dǎo)出jar文件
- 復(fù)制"example"工程到"outputs/example"目錄
- 復(fù)制jar文件到"outputs/libs"目錄
- 復(fù)制資源文件到"outputs/res"目錄
- 把 "outputs" 目錄壓縮成 zip 文件
之后就可以寫入代碼了
task dabao(type:Zip, dependsOn:build) {
destinationDir = file('outputs')
duplicatesStrategy = 'exclude'
archiveName = 'com.umeng.fb.' + android.defaultConfig.versionName + '.zip'
from('/'){
include 'releasenote.txt'
}
into('example') {
from '../example' exclude '**/build/**'
}
from('src/main/res'){
into 'res'
}
from('libs'){
into 'libs'
}
from(zipTree('build/outputs/aar/sdk-release.aar')){
include 'classes.jar'
rename 'classes.jar','com.umeng.fb.' + android.defaultConfig.versionName + '.jar'
into 'libs'
}
}
資料
Gradle 完整指南(Android)
看不懂的build.gradle代碼
學(xué)點(diǎn)Groovy來理解build.gradle代碼
如果像寫代碼一樣寫Gradle腳本
Gradle使用技巧總結(jié)