零散知識(shí)點(diǎn)總結(jié)(1) - Gradle 使用配置總結(jié)

一、統(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)查看:

Gradle View.png

重啟之后,點(diǎn)擊View -> Tool Windows -> Gradle View,之后會(huì)在最下方生成一個(gè)窗口,我們通過(guò)這個(gè)窗口就可以看到對(duì)應(yīng)項(xiàng)目的依賴關(guān)系:
Gradle View Result.png

2.2 命令查看

除此之外,我們也可以使用以下的命令:

./gradlew -q app:dependencies

同樣可以獲得類似的結(jié)果:

命令.png

注意上圖,如果標(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)有了:


2017-02-09 15:27:38屏幕截圖.png

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

Force.png

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)系為:

2017-02-09 15:54:02屏幕截圖.png

當(dāng)然,exclude后的參數(shù)有groupmodule,可以分別單獨(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下的repositoriesgradle腳本自身需要的資源,
  • 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
  • targetSdkVersionAndroid提供向前兼容的重要依據(jù)。(targetSdkVersion is the main way Android provides forward compatibility
    因?yàn)殡S著Android系統(tǒng)的升級(jí),某個(gè)api或者模塊的行為有可能發(fā)生改變,但是為了保證老APK的行為和以前兼容,只要APKtargetSdkVersion不變,那么即使這個(gè)APK安裝在新的Android系統(tǒng)上,那么行為還是保持老的系統(tǒng)上的行為。
    系統(tǒng)在調(diào)用某個(gè)api或者模塊的時(shí)候,會(huì)先檢查調(diào)用的APKtargetSdkVersion,來(lái)決定執(zhí)行什么行為。

minSdkVersiontargetSdkVersion最終會(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è)模塊BrowserScannerSDK,那么就需要:
include ':Browser'
include ':ScannerSDK'
project(':ScannerSDK').projectDir = new File(settingsDir, './ScannerSDK/')
  • gradle文件夾
    里面有兩個(gè)文件,gradle-wrapper.jargradle-wrapper.properties,后者當(dāng)中指定了gradle的版本。
distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
  • gradlewgradlew.bat
    分別是Linuxwindows下的批處理文件,它們的作用是根據(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

Task2.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 StudioGradle組件默認(rèn)提供了debugrelease兩個(gè)默認(rèn)配置,這里主要用于是否需要混淆,是否調(diào)試。
  • productFlavors產(chǎn)品渠道,在實(shí)際發(fā)布中,根據(jù)不同渠道,可能需要使用不同的包名,甚至是不同的代碼。
  • buildVaiants:每個(gè)buildTypesproductFlavors組成一個(gè)buildvariant

以上我們討論的buildTypesproductFlavors可以通過(guò)每個(gè)Module中的build.gradleandroid標(biāo)簽來(lái)配置。

下面,我們先看一下不同的productFlavors,分別用來(lái)支持讀取不同的文件和替換不同的字符串。

7.1 引用不同的代碼

我們首先在app/src目錄下新建兩個(gè)目錄,分別對(duì)應(yīng)兩個(gè)Flavor,再在其中建立相同名字的文件Constant.java,對(duì)里面的某個(gè)常量賦予不同的值。

Flavor.png

  • 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ì)得到不同的值:

2017-02-10 16:15:51屏幕截圖.png

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í)梳理系列:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容