Gradle是什么球凰?
Gradle 是以Groovy為基礎(chǔ)狮腿,面向java應(yīng)用,基于DSL語法的自動化構(gòu)建工具呕诉。是google引入缘厢,替換ant和maven的新工具,其依賴兼容maven和ivy甩挫。
使用gradle的目的:
更容易重用資源和代碼;
可以更容易創(chuàng)建不同的版本的程序贴硫,多個類型的apk包;
更容易配置伊者,擴展;
更好的IDE集成英遭;
首先明確gradle跟maven一樣,也有一個配置文件亦渗,maven里面是叫pom.xml挖诸,而在gradle中是叫build.gradle。Android Studio中的android項目通常至少包含兩個build.gradle文件法精,一個是project范圍的多律,另一個是module范圍的,由于一個project可以有多個module搂蜓,所以每個module下都會對應(yīng)一個build.gradle狼荞。這么說有點抽象,看下面這個圖:
1. Project中build.gradle
project下的build.gradle是基于整個project的配置帮碰,主要配置gradle 版本及 全局依賴倉庫相味、庫或者其他全部參數(shù)。
android studio 現(xiàn)在重要倉庫采用jcenter(),之前版本放在mavenCentral收毫。
另外有時還沒有加入jcenter()倉庫的第三方庫攻走,也需要在這里配置他們的庫地址殷勘。
需要在這里配置,才能將第三方庫拉下來
buildscript {
//構(gòu)建過程依賴的倉庫
repositories {
jcenter()
}
//構(gòu)建過程需要依賴的庫
dependencies {
//聲明的是gradle插件的版本
classpath 'com.android.tools.build:gradle:2.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
//這里面配置整個項目依賴的倉庫,這樣每個module就不用配置倉庫了
repositories {
jcenter()
maven {
// LeanCloud 的包倉庫
url "http://mvn.leancloud.cn/nexus/content/repositories/releases"
}
}
}
//配置全局變量
ext {
// module依賴庫公共版本號
SupportXVersion = '23.2.0'
GsonVersion = '2.6.2'
LeanCloudVersion = 'v3.13.4'
JunitVersion = '4.12'
compileSdkVersion = 22
buildToolsVersion = "23.0.1"
minSdkVersion = 10
targetSdkVersion = 22
versionCode = 34
versionName = "v2.6.1"
}
注:大家可能很奇怪昔搂,為什么倉庫repositories需要聲明兩次玲销,這其實是由于它們作用不同,buildscript中的倉庫是gradle腳本自身需要的資源摘符,而allprojects下的倉庫是項目所有模塊需要的資源
2. module中build.gradle
//申明使用插件贤斜,表明要編譯的內(nèi)容和產(chǎn)物,
//com.android.application 表明該module 為android 應(yīng)用
//com.android.library 表明為library庫
//java 表名是java庫
apply plugin: 'com.android.application'
//安卓構(gòu)建過程需要配置的參數(shù)
android {
//編譯SDK的版本
compileSdkVersion COMPILE_SDK_VERSION as int
//buildtool 的版本
buildToolsVersion BUILD_TOOLS_VERSION
/默認配置逛裤,會同時應(yīng)用到debug和release版本上
defaultConfig {
//應(yīng)用包名
applicationId APPLICATION_ID
//支持最小android sdk 版本
minSdkVersion MIN_SDK_VERSION as int
// 目標版本
targetSdkVersion TARGET_SDK_VERSION as int
//應(yīng)用版本號
versionCode VERSION_CODE as int
//應(yīng)用版本名稱
versionName VERSION_NAME
/// 配置生成的 BuildConfig 文件中的常量瘩绒,代碼引用直接
buildConfigField "String", "LOG_TAG", LOG_TAG // 日志tag
buildConfigField "String", "LOG_HTTP_TAG", LOG_TAG_HTTP // http日志tag
buildConfigField "String", "LOG_WEB_TAG", LOG_TAG_WEB // web日志tag
// 默認是UMENG_CHANNEL_VALUE為umeng
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "umeng"]
// dex突破65535的限制
multiDexEnabled true
}
//java版本號
compileOptions{
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
//簽名
signingConfigs {
release {
//簽名文件
storeFile file(STORE_FILE)
storePassword STORE_PASSWORD
keyAlias KEY_ALIAS
keyPassword KEY_PASSWORD
}
}
// 為了解決部分第三方庫重復(fù)打包了META-INF的問題
packagingOptions {
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
}
//移除lint檢測的error
lintOptions {
abortOnError false
}
//編譯類型
//其中debug, release是gradle默認自帶的兩個build type, 當(dāng)然你可以定義其他類型带族。
//可以針對不停編譯的版本中配置不同的參數(shù)锁荔,比如混淆、簽名等蝙砌。preview
buildTypes {
debug {
minifyEnabled false
zipAlignEnabled false
shrinkResources false
}
preview {
debuggable false // 是否保留調(diào)試信息
minifyEnabled true //是否混淆
zipAlignEnabled true // 包優(yōu)化
shrinkResources true // 移除不必要的資源
// 簽名
signingConfig signingConfigs.release
// 代碼混淆規(guī)則文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
//加上后綴
applicationIdSuffix ".release"
minifyEnabled true //是否混淆
zipAlignEnabled true // zip對齊優(yōu)化
shrinkResources true // 移除不必要的資源
// 不顯示Log
buildConfigField "boolean", "LOG_DEBUG", "false"
// 簽名
signingConfig signingConfigs.release
//混淆文件的位置
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
// 多渠道
productFlavors {
//可以設(shè)置不同渠道渠道號阳堕,應(yīng)用名稱
dev { // 開發(fā)
buildConfigField "String", "CHANNEL_NUMBER", '"11111"'
}
'360' {
buildConfigField "String", "CHANNEL_NUMBER", '"11112"'
}
GooglePlay {
buildConfigField "String", "CHANNEL_NUMBER", "11113"'
}
// 多渠道批量替換
productFlavors.all { flavor ->
//批量修改Manifest占位符替換
//在Manifest使用`${UMENG_CHANNEL_VALUE}`,`LEANCLOUD_CHANNEL_VALUE`,打包時將替換成渠道名,例如UMENG_CHANNEL_VALUE="dev";
flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name, LEANCLOUD_CHANNEL_VALUE: name]
// Project Properties->_myAPPBuildVersionName择克,用于程序集成下命令行修改
if (project.hasProperty('_myAPPBuildVersionName')) {
defaultConfig.versionName = _myAPPBuildVersionName
}
}
//定義變量
//gradle 可以用def定義一些值例如:def KeyPassword = "123123"
def releaseTime() {
return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}
// 批量打包
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def fileName
if (variant.buildType.name.equals('release')) {
// myAPP_v版本號_渠道名.apk
fileName = "myAPP_v${variant.versionName}_${variant.productFlavors[0].name}.apk"
} else {
// myAPP_v版本號_渠道名_時間_編譯類型名.apk
fileName = "myAPP_v${variant.versionName}_${variant.productFlavors[0].name}_${releaseTime()}_${variant.buildType.name}.apk"
}
output.outputFile = new File(outputFile.parent + "/${variant.buildType.name}", fileName)
}
}
}
}
//依賴第三方庫
dependencies {
//編譯libs目錄下所以jar包
//compile files('libs/xxx.jar') 導(dǎo)入一個特定jar包
compile fileTree(dir: 'libs', include: ['*.jar'])//導(dǎo)入所有的jar包
compile project(':core')
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
compile 'com.android.support:recyclerview-v7:23.1.1'
compile 'com.android.support:cardview-v7:23.1.1'
}
注意:
- buildToolsVersion這個需要你本地安裝該版本才行恬总,很多人導(dǎo)入新的第三方庫,失敗的原因之一是build version的版本不對肚邢,這個可以手動更改成你本地已有的版本或者打開 SDK Manager 去下載對應(yīng)版本壹堰。
- proguardFiles這部分有兩段,前一部分代表系統(tǒng)默認的android程序的混淆文件骡湖,該文件已經(jīng)包含了基本的混淆聲明贱纠,免去了我們很多事,這個文件的目錄在 /tools/proguard/proguard-android.txt , 后一部分是我們項目里的自定義的混淆文件勺鸦,目錄就在 app/proguard-rules.pro ,在這個文件里你可以聲明一些第三方依賴的一些混淆規(guī)則并巍,最終混淆的結(jié)果是這兩部分文件共同作用的。
- 一般重要的信息,例如簽名信息捉兴,可以直接將信息寫到gradle.properties翩活,然后在然后在build.gradle中引用即可。
- 多渠道的關(guān)鍵在于定義不同的product flavor蠕趁。
注意:這里的flavor名如果是數(shù)字開頭,必須用引號引起來。 -
buildTypes
是指建構(gòu)的類型懈息,一般只用兩種默認類型 debug 和 release ,顧名思義 debug 用來配置開發(fā)過程中的一些內(nèi)容摹恰;release 用來配置正式發(fā)布版本的內(nèi)容辫继。有時我們需要發(fā)布介于debug與release之間的preview 版本怒见。
3. Project中setting.gradle
這個文件是全局的項目配置文件,里面主要聲明Project中所包括的所有module姑宽,
//一個Project中所包括的所有module
include ':app', ':model',':lib', ':core'
4. Project中g(shù)radle.properties
gradle.properties為gradle的配置文件遣耍,里面可以定義一些常量供build.gradle使用,比如可以配置簽名相關(guān)信息如keystore位置炮车,密碼舵变,keyalias等,build.gradle就可以直接引用
gradle 中的一些配置參數(shù)建議寫到gradle.properties
//編譯版本信息
APPLICATION_ID = com.jin.myAPP
COMPILE_SDK_VERSION = 23
BUILD_TOOLS_VERSION = 23.0.1
MIN_SDK_VERSION = 15
TARGET_SDK_VERSION = 1
VERSION_CODE = 1
VERSION_NAME = 1.0.0.0
//keystore信息
STORE_FILE = ../app/mykey.keystore
STORE_PASSWORD = your password
KEY_ALIAS = your alias
KEY_PASSWORD = your password
5. ext配置全局參數(shù)
project的build.gradle中的ext可以為各位module進行全局配置參數(shù),防止各個module之間的不統(tǒng)一瘦穆,不可控纪隙。而且當(dāng)我們升級sdk、build tool扛或、target sdk等绵咱,幾個module都要更改,非常的麻煩熙兔。
ext {
compileSdkVersion = 22
buildToolsVersion = "23.0.1"
minSdkVersion = 10
targetSdkVersion = 22
versionCode = 34
versionName = "v2.6.1"
}
然后在各自module的build.gradle中引用:
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId "com.xxx.xxx"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
}
}
6. resValue 定義資源麸拄。
例如resValue "string" 就是字符串資源,可以用R.String 來引用對應(yīng)的字符串資源
android {
defaultConfig {
resValue "string", "build_time", buildTime()
resValue "string", "build_host", hostName()
resValue "string", "build_revision", revision()
}
}
def buildTime() {
return new Date().format("yyyy-MM-dd HH:mm:ss")
}
def hostName() {
return System.getProperty("user.name") + "@" +InetAddress.localHost.hostName
}
def revision() {
def code = new ByteArrayOutputStream()
exec {
commandLine 'git', 'rev-parse', '--short', 'HEAD'
standardOutput = code
}
return code.toString()
}
上述代碼實現(xiàn)了動態(tài)的添加了3個字符串資源: build_time黔姜、build_host拢切、build_revision, 然后在其他地方可像如引用字符串一樣使用如下:
// 在Activity里調(diào)用
getString(R.string.build_time) // 輸出2015-11-07 17:01
getString(R.string.build_host) // 輸出jay@deepin,這是我的電腦的用戶名和PC名
getString(R.string.build_revision) // 輸出3dd5823, 這是最后一次commit的sha值
7. PlaceHolder
manifest的一些值我們可以用PlaceHolder處理秆吵。例如
<meta-data
android:name="UMENG_CHANNEL"
android:value="${UMENG_CHANNEL_VALUE}" />
在gradle中改成
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "360"]
可以放在defaultConfig
中設(shè)置默認值淮椰,或者放在productFlavors
中根據(jù)不同渠道修改成不同值∧杉牛或者批量修改
productFlavors.all {
flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}
8. 導(dǎo)入某個project
如果你的app是多模塊的主穗,假設(shè)有兩個模塊app和lib,并且app模塊是依賴lib的,這時候我們就需要在app模塊的build.gradle中的dependencies結(jié)點下配置依賴:
compile project(':lib')
并且你需要在settings.gradle中把lib模塊包含進來:
include ':lib',':app'
此外毙芜,這種情況下lib模塊是作為庫存在的忽媒,因而它的build.gradle中的插件聲明通常應(yīng)該是這樣的:
apply plugin: 'com.android.library'
而且,作為library的模塊lib的build.gradle文件的defaultConfig中是不允許聲明applicationId的腋粥,這點需要注意晦雨。
9. 引用本地aar:
- 首先將你的庫通過android studio 運行打包成aar文件。運行后在/build/output/aar文件夾中隘冲。
- 首先將aar文件放到模塊的libs目錄下闹瞧,然后在該模塊的build.gradle中聲明flat倉庫:
repositories{
flatDir {
dirs 'libs'
}
}
- 最后在dependencies結(jié)點下依賴該aar模塊:
dependencies{
compile (name:'xxx',ext:'aar')
}
10. BuildConfig
在build.gradle中配置buildConfigField參數(shù),編譯后會在..\app\build\generated\source\buildConfig文件夾下會自動生成對應(yīng)版本對應(yīng)module的BuildConfig.java展辞。BuildConfig就會包含對應(yīng)版本的配置信息奥邮。程序中可以直接引用這些數(shù)據(jù)。例如BuildConfig.DEBUG。
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String BUILD_TYPE = "debug";
public static final String FLAVOR = "360";
public static final int VERSION_CODE = 45;
public static final String VERSION_NAME = "3.2.0.0";
// Fields from build type: debug
public static final String HOST_IMG_SERVER = "img";
public static final String HOST_SERVER = "test";
// Fields from product flavor: 360
public static final String CHANNEL_NUMBER = "232100";
}
11. module 調(diào)整目錄結(jié)構(gòu)sourceSets
默認情況下洽腺,java文件和resource文件分別在src/main/java和src/main/res目錄下脚粟,在build.gradle文件,andorid{}里面添加下面的代碼蘸朋,便可以將java文件和resource文件放到src/java和src/resources目錄下珊楼。
sourceSets {
main {
java {
srcDir 'src/java'
}
resources {
srcDir 'src/resources'
}
}
}
更簡便的寫法是:
sourceSets {
min.java.srcDirs = ['src/java']
min.resources.srcDirs = ['src/resources']
}
12. Gradle常用命令
上面大家接觸了一些命令如 ./gradlew -v ./gradlew clean ./gradlew build, 這里注意是./gradlew, ./代表當(dāng)前目錄,gradlew代表 gradle wrapper度液,意思是gradle的一層包裝厕宗,大家可以理解為在這個項目本地就封裝了gradle,即gradle wrapper堕担, myAPP/gradle/wrapper/gralde-wrapper.properties**文件中聲明了它指向的目錄和版本已慢。只要下載成功即可用grdlew wrapper的命令代替全局的gradle命令。
理解了gradle wrapper的概念霹购,下面一些常用命令也就容易理解了佑惠。
- ./gradlew 下載更新gradle
- ./gradlew -v 版本號
- ./gradlew assemble 構(gòu)建項目輸出
- ./gradlew check 運行檢測和測試任務(wù)
- ./gradlew clean 清除9GAG/app目錄下的build文件夾
- ./gradlew build 運行check和assemble,檢查依賴并編譯打包
這里注意的是 ./gradlew build 命令把debug、release環(huán)境的包都打出來齐疙,如果正式發(fā)布只需要打Release的包膜楷,該怎么辦呢,下面介紹一個很有用的命令 assemble<build type="" name="">, 如</build> - ./gradlew assembleDebug 編譯并打Debug包
- ./gradlew assembleRelease 編譯并打Release的包所有渠道的
- ./gradlew assembleWandoujiaRelease 編譯并打包豌豆莢的Release版本
- ./gradlew assembleWandoujia 編譯并打包豌豆莢的所有版本
- ./gradlew installRelease Release模式打包并安裝
- ./gradlew uninstallRelease 卸載Release模式包