一、統(tǒng)一管理依賴版本
1.1 在根目錄下,新建config.gradle
文件
ext {
android = [
compileSdkVersion: 23,
buildToolsVersion: "23.0.3",
applicationId: "com.example.lizejun.repogradle",
minSdkVersion: 14,
targetSdkVersion: 23,
versionCode: 1,
versionName: "1.0",
testInstrumentationRunner: "android.support.test.runner.AndroidJUnitRunner"
]
dependencies = [
"support-v4" : 'com.android.support:support-v4:23.2.0',
"support-v7" : 'com.android.support:appcompat-v7:23.2.0'
]
}
android
用來(lái)管理SDK
版本、版本號(hào)等,dependencies
用來(lái)管理依賴庫(kù)的版本,它們都是一個(gè)數(shù)組,用逗號(hào)來(lái)分割,數(shù)組的每個(gè)元素都是key:value
的格式。
1.2 在根目錄下的build.gradle
,新增:
apply from: "config.gradle"
1.3 在根目錄下的各個(gè)Module
或者Library
中的build.gradle
文件中,引用對(duì)應(yīng)的key
:
android {
compileSdkVersion rootProject.ext.android.compileSdkVersion
buildToolsVersion rootProject.ext.android.buildToolsVersion
defaultConfig {
applicationId rootProject.ext.android.applicationId
minSdkVersion rootProject.ext.android.minSdkVersion
targetSdkVersion rootProject.ext.android.targetSdkVersion
versionCode rootProject.ext.android.versionCode
versionName rootProject.ext.android.versionName
testInstrumentationRunner rootProject.ext.android.testInstrumentationRunner
}
}
dependencies {
compile rootProject.ext.dependencies["support-v7"]
}
二、查看依賴關(guān)系
2.1 工具查看
依賴樹(shù)的查看可以通過(guò)Android Studio
的插件Gradle View
來(lái)查看:
重啟之后,點(diǎn)擊
View -> Tool Windows -> Gradle View
,之后會(huì)在最下方生成一個(gè)窗口,我們通過(guò)這個(gè)窗口就可以看到對(duì)應(yīng)項(xiàng)目的依賴關(guān)系:2.2 命令查看
除此之外,我們也可以使用以下的命令:
./gradlew -q app:dependencies
同樣可以獲得類似的結(jié)果:
注意上圖,如果標(biāo)記了
(*)
,那么表示這個(gè)依賴被忽略了,這是因?yàn)槠渌敿?jí)依賴中也依賴了這個(gè)傳遞的依賴,Gradle
會(huì)自動(dòng)分析下載最合適的依賴。
三、標(biāo)識(shí)符
由于多個(gè)頂級(jí)依賴當(dāng)中,可能包含了相同的子依賴,但是它們的版本不同,這時(shí)候?yàn)榱诉x擇合適的版本,那么就需要使用一些必要的操作符來(lái)管理子依賴。
3.1 Transitive
默認(rèn)為true
,表示gradle
自動(dòng)添加子依賴項(xiàng),形成一個(gè)多層樹(shù)形結(jié)構(gòu);設(shè)置為false
,則需要手動(dòng)添加每個(gè)依賴項(xiàng)。
3.1.1 統(tǒng)一指定Transitive
configurations.all {
transitive = false
}
dependencies {
compile rootProject.ext.dependencies["support-v7"]
}
最終得到的結(jié)果是,可以看到前面的子依賴項(xiàng)都沒(méi)有了:
3.1.2 單獨(dú)指定Transitive
dependencies {
compile ('com.android.support:appcompat-v7:23.2.0') {
transitive = false
}
}
3.2 Force
用來(lái)表示強(qiáng)制設(shè)置某個(gè)模塊的版本:
configurations.all {
resolutionStrategy {
force 'com.android.support:support-v4:23.1.0'
}
}
之后打印,發(fā)現(xiàn)其依賴的包版本變成了23.1.0
:
3.3 exclude
該標(biāo)識(shí)符用來(lái)設(shè)置不編譯指定的模塊
3.3.1 全局配置某個(gè)模塊
configurations {
all *.exclude group : 'com.android.support', module: 'support-v4'
}
此時(shí)的依賴關(guān)系為:
當(dāng)然,
exclude
后的參數(shù)有group
和module
,可以分別單獨(dú)使用,會(huì)排除所有匹配項(xiàng)。
3.3.2 單獨(dú)給某個(gè)模塊exclude
compile ('com.android.support:appcompat-v7:23.2.0') {
exclude group : 'com.android.support', module: 'support-v4'
}
也會(huì)和上面獲得相同的結(jié)果
四、版本沖突
4.1 相同配置下的版本沖突
同一配置下,某個(gè)模塊的不同版本同時(shí)被依賴時(shí),默認(rèn)使用最新版,Gradle
同步時(shí)不會(huì)報(bào)錯(cuò)。
五、Gradle
詳解
基本配置:AS
中的Android
項(xiàng)目通常至少包含兩個(gè)build.gradle
,一個(gè)是Project
范圍的,另一個(gè)是Module
范圍的,由于一個(gè)Project
可以有多個(gè)Module
,所以每個(gè)Module
下都會(huì)對(duì)應(yīng)一個(gè)build.gradle
。
5.1 Project
下的build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
apply from: "config.gradle"
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.1'
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
-
buildscript
下的repositories
是gradle
腳本自身需要的資源, -
allprojects
下的repositories
是項(xiàng)目所有模塊需要的資源。
5.2 模塊的build.gradle
//聲明插件,表明這是一個(gè)Android程序;如果是庫(kù),那么應(yīng)當(dāng)是com.android.library
apply plugin: 'com.android.application'
//Android構(gòu)建過(guò)程需要配置的參數(shù)
android {
//編譯版本
compileSdkVersion rootProject.ext.android.compileSdkVersion
//buildTool版本
buildToolsVersion rootProject.ext.android.buildToolsVersion
//默認(rèn)配置,同時(shí)應(yīng)用到debug和release版本上
defaultConfig {
applicationId rootProject.ext.android.applicationId
minSdkVersion rootProject.ext.android.minSdkVersion
targetSdkVersion rootProject.ext.android.targetSdkVersion
versionCode rootProject.ext.android.versionCode
versionName rootProject.ext.android.versionName
testInstrumentationRunner rootProject.ext.android.testInstrumentationRunner
}
//配置debug和release版本的一些參數(shù),例如混淆,簽名配置等
buildTypes {
//release版本
release {
minifyEnabled false //是否開(kāi)啟混淆
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' //混淆文件位置
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile rootProject.ext.dependencies["support-v7"]
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
testCompile 'junit:junit:4.12'
}
下面對(duì)Android
構(gòu)建過(guò)程中需要配置的參數(shù)做一些解釋:
-
compileSdkVersion
:告訴gradle
用那個(gè)Android SDK
的版本編譯你的應(yīng)用,修改它不會(huì)改變運(yùn)行時(shí)的行為,因?yàn)樗粫?huì)被包含進(jìn)入最終的APK
中;因此,推薦使用最新的SDK
編譯;如果使用Suppport Library
,那么compileSdkVersion
必須要大于等于它的大版本號(hào)。 -
minSdkVersion
:應(yīng)用最低可運(yùn)行的要求;它必須要大于等于你所依賴的庫(kù)的minSdkVersion
; -
targetSdkVersion
:Android
提供向前兼容的重要依據(jù)。(targetSdkVersion is the main way Android provides forward compatibility
)
因?yàn)殡S著Android
系統(tǒng)的升級(jí),某個(gè)api
或者模塊的行為有可能發(fā)生改變,但是為了保證老APK
的行為和以前兼容,只要APK
的targetSdkVersion
不變,那么即使這個(gè)APK
安裝在新的Android
系統(tǒng)上,那么行為還是保持老的系統(tǒng)上的行為。
系統(tǒng)在調(diào)用某個(gè)api
或者模塊的時(shí)候,會(huì)先檢查調(diào)用的APK
的targetSdkVersion
,來(lái)決定執(zhí)行什么行為。
minSdkVersion
和targetSdkVersion
最終會(huì)被包含進(jìn)入最終的APK
文件中,如果你查看生成的AndroidManifest.xml
,那么會(huì)發(fā)現(xiàn):
<uses-sdk android:targetSdkVersion="23" android:minSdkVersion="7" />
所以,我們一般遵循的規(guī)則是:
minSdkVersion (lowest possible) <= targetSdkVersion == compileSdkVersion (latest SDK)
5.3 gradle
相關(guān)文件
-
gradle.properties
配置文件,可以定義一些常量供build.gradle
使用,比如可以配置簽名相關(guān)信息,例如keystore
位置、密碼、keyalias
等。 -
settings.gradle
用來(lái)配置多模塊的,如果你的項(xiàng)目有兩個(gè)模塊Browser
和ScannerSDK
,那么就需要:
include ':Browser'
include ':ScannerSDK'
project(':ScannerSDK').projectDir = new File(settingsDir, './ScannerSDK/')
-
gradle
文件夾
里面有兩個(gè)文件,gradle-wrapper.jar
和gradle-wrapper.properties
,后者當(dāng)中指定了gradle
的版本。
distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
-
gradlew
和gradlew.bat
分別是Linux
和windows
下的批處理文件,它們的作用是根據(jù)gradle-wrapper.properties
文件中的distributionUrl
下載對(duì)應(yīng)的gradle
版本,這樣即使環(huán)境沒(méi)有安裝gradle
也可以編譯。
5.4 gradle
倉(cāng)庫(kù)
gradle
有三種倉(cāng)庫(kù):maven/ivy/flat本地
。
maven{
url "..."
}
ivy{
url "..."
}
flatDir{
dirs 'xxx'
}
有些倉(cāng)庫(kù)取了別名:
repositories{
mavenCentral()
jcenter()
mavenLocal()
}
5.5 gradle
任務(wù)
通過(guò)以下指令,可以看到支持的任務(wù):
./gradlew tasks
Task1.png
六、常見(jiàn)問(wèn)題
6.1 導(dǎo)入本地Jar
包
導(dǎo)入單個(gè)jar
文件:
compile files('libs/xxx.jar')
導(dǎo)入libs
的多個(gè)jar
文件:
compile fileTree(dir: 'libs', include: ['*.jar'])
6.2 導(dǎo)入maven
庫(kù)
compile 'groupId:artifactId:version'
6.3 導(dǎo)入Project
在導(dǎo)入之前,需要在settings.gradle
中把模塊包含進(jìn)來(lái),例如前面的ScannerSDK
模塊:
compile project(':ScannerSDK')
6.4 聲明第三方maven
庫(kù)
如果項(xiàng)目中需要的一些庫(kù)文件不再中央倉(cāng)庫(kù)中,而是在某個(gè)特定地址里,那么就需要在Project
中的build.gradle
中的allprojects
結(jié)點(diǎn)下或者直接配到某個(gè)模塊中:
allprojects {
repositories {
maven {
url '地址'
}
}
}
6.5 依賴第三方aar
compile 'com.aaa.xxx:core:1.0.1@aar'
6.6 將庫(kù)導(dǎo)出為aar
首先,你的項(xiàng)目必須是一個(gè)庫(kù)項(xiàng)目,之后在build.gradle
中進(jìn)行配置:
apply plugin : 'com.android.library'
之后,進(jìn)入到該項(xiàng)目中,執(zhí)行gradle
命令:
./gradlew assembleRelease
生成的aar
放在/build/output/aar
文件當(dāng)中
6.7 引用本地aar
首先,將aar
文件拷貝到對(duì)應(yīng)目錄下,然后在該模塊的build.gradle
中聲明flat
倉(cāng)庫(kù):
repositories{
flatDir{
dirs '以build.gradle為根目錄的相對(duì)路徑'
}
}
之后,在dependencies
結(jié)點(diǎn)下依賴該aar
模塊:
dependencies{
compile (name:'xxx',ext:'aar')
}
七、多版本打包
在此之前,我們先了解幾個(gè)基本的概念:
-
buildTypes
:構(gòu)建類型,Android Studio
的Gradle
組件默認(rèn)提供了debug
和release
兩個(gè)默認(rèn)配置,這里主要用于是否需要混淆,是否調(diào)試。 -
productFlavors
:產(chǎn)品渠道,在實(shí)際發(fā)布中,根據(jù)不同渠道,可能需要使用不同的包名,甚至是不同的代碼。 -
buildVaiants
:每個(gè)buildTypes
和productFlavors
組成一個(gè)buildvariant
。
以上我們討論的buildTypes
和productFlavors
可以通過(guò)每個(gè)Module
中的build.gradle
的android
標(biāo)簽來(lái)配置。
下面,我們先看一下不同的productFlavors
,分別用來(lái)支持讀取不同的文件和替換不同的字符串。
7.1 引用不同的代碼
我們首先在app/src
目錄下新建兩個(gè)目錄,分別對(duì)應(yīng)兩個(gè)Flavor
,再在其中建立相同名字的文件Constant.java
,對(duì)里面的某個(gè)常量賦予不同的值。
-
constantFlavor1
:
package com.example.lizejun.repogradle;
public class Constant {
public static final String NAME = "flavor1";
}
-
constantFlavor2
:
package com.example.lizejun.repogradle;
public class Constant {
public static final String NAME = "flavor2";
}
我們的app
下的build.gradle
中的android
標(biāo)簽下添加如下幾行代碼,讓兩個(gè)Flavor
分別引用不同的Constant
文件:
sourceSets {
constantFlavor1 {
java.srcDirs = ['src/constantFlavor1', 'src/constantFlavor1/java', 'src/constantFlavor1/java/']
}
constantFlavor2 {
java.srcDirs = ['src/constantFlavor2', 'src/constantFlavor2/java', 'src/constantFlavor2/java/']
}
}
productFlavors {
constantFlavor1 {}
constantFlavor2 {}
}
之后我們進(jìn)行打包,可以得到以下不同安裝包,這兩個(gè)apk
如果在其中引用的了NAME
,那么它會(huì)得到不同的值:
7.2 自定義buildConfig
類
如果我們只需要定義一些簡(jiǎn)單的值,那么我們可以用buildConfig
類:
productFlavors {
constantFlavor1 {
buildConfigField "boolean", "BOOLEAN_VALUE", "true"
}
constantFlavor2 {
buildConfigField "boolean", "BOOLEAN_VALUE", "false"
}
}
7.3 占位符
productFlavors {
constantFlavor1 {
buildConfigField "boolean", "BOOLEAN_VALUE", "true"
manifestPlaceholders = [label:"constantFlavor1"]
}
constantFlavor2 {
buildConfigField "boolean", "BOOLEAN_VALUE", "false"
manifestPlaceholders = [label:"constantFlavor2"]
}
}
之后,我們?cè)僭?code>AndroidManifest.xml中引用它:
android:label="${label}"
7.4 簽名配置
首先是在android
標(biāo)簽下,我們使用signingConfigs
來(lái)配置不同的簽名類型
signingConfigs {
eng {
keyAlias 'androiddebugkey'
keyPassword 'android'
storeFile file('debug.keystore')
storePassword 'android'
}
prd {
keyAlias 'androiddebugkey'
keyPassword 'android'
storeFile file('debug.keystore')
storePassword 'android'
}
}
之后,再在buildTypes
的各個(gè)分支中引用對(duì)應(yīng)的簽名配置:
buildTypes {
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.eng
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.prd
}
}
7.5 依賴
有時(shí)候,我們需要在不同的buildTypes
下,引用不同的依賴,例如內(nèi)存泄露的檢測(cè)工具,我們希望在debug
版本時(shí)檢查內(nèi)存泄露,并在發(fā)生時(shí)在桌面上生成圖標(biāo),但是在release
版本上我們并不希望這么做,這時(shí)候我們可以這么寫(xiě):
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
這樣,release
版本就不會(huì)在桌面生成內(nèi)存泄露的圖標(biāo)。
更多文章,歡迎訪問(wèn)我的 Android 知識(shí)梳理系列:
- Android 知識(shí)梳理目錄:http://www.lxweimin.com/p/fd82d18994ce
- 個(gè)人主頁(yè):http://lizejun.cn
- 個(gè)人知識(shí)總結(jié)目錄:http://lizejun.cn/categories/