Apk構(gòu)建總結(jié)之二構(gòu)建工具(Ant、Maven镊尺、Gradle)

一. 構(gòu)建工具

1.什么是構(gòu)建工具朦佩?

在進行編程操作的時候,我們經(jīng)常會遇到很多與編程無關(guān)的項目管理工作庐氮。如下載依賴吕粗、編譯源碼、單元測試旭愧、項目部署等操作颅筋。
一般的,小型項目我們可以手動實現(xiàn)這些操作输枯,然而大型項目這些工作則相對復(fù)雜议泵。所以我們需要用到構(gòu)建工具。
構(gòu)建工具是幫助我們實現(xiàn)一系列項目管理桃熄、測試和部署操作的工具先口。構(gòu)建工具可以把源代碼生成可執(zhí)行應(yīng)用程序的過程自動化的程序(例如Android app生成apk)。
構(gòu)建工具包括編譯瞳收、連接跟把代碼打包成可用的或可執(zhí)行的形式碉京。

總的來說構(gòu)建的自動化是編寫或使一大部分任務(wù)自動執(zhí)行的一個動作,而這些任務(wù)則是軟件開發(fā)者的日常螟深,像是:

  • 下載依賴谐宙。
  • 將源代碼編譯成二進制代碼。
  • 打包生成的二進制代碼界弧。
  • 進行單元測試凡蜻。
  • 部署到生產(chǎn)系統(tǒng)。

2.為什么要使用構(gòu)建工具垢箕?

比如我們要寫一個Java程序划栓,一般的步驟也就是編譯,測試条获,打包忠荞。這個構(gòu)建的過程,如果文件比較少帅掘,我們可以手動使用java, javac, jar命令去做這些事情委煤。
但當(dāng)工程越來越大,文件越來越多锄开,這個事情就不是那么地令人開心了素标。因為這些命令往往都是很機械的操作。但是我們可以把機械的東西交給機器去做萍悴。

Java世界中主要有三大構(gòu)建工具:Ant头遭、Maven和Gradle寓免。

一. Java構(gòu)建工具

1.java平臺常用的構(gòu)建工具之Ant.

Ant 是由 Java 編寫的構(gòu)建工具,它的核心代碼是由Java編寫的计维,因此具有平臺無關(guān)性袜香,構(gòu)建腳本是XML格式的(默認(rèn)為bulid.xml)。
例如:下面列出一個ant工具所使用的build.xml:

<?xml version="1.0" encoding="UTF-8" ?>  
<project name="HelloWorld" default="run" basedir=".">  
<property name="src" value="src"/>  
<property name="dest" value="classes"/>  
<property name="jarfile" value="hello.jar"/>  
<target name="init">  
   <mkdir dir="${dest}"/>  
</target>  
<target name="compile" depends="init">  
   <javac srcdir="${src}" destdir="${dest}"/>  
</target>  
<target name="build" depends="compile">  
   <jar jarfile="${jarfile}" basedir="${dest}"/>  
</target>  
<target name="test" depends="build">  
   <java classname="test.ant.HelloWorld" classpath="${hello_jar}"/>  
</target>  
<target name="clean">  
   <delete dir="${dest}" />  
   <delete file="${hello_jar}" />  
</target>  
</project> 

ant的構(gòu)建腳本還是比較清楚的鲫惶。ant定義了五個任務(wù)蜈首,init, compile, build, test, clean。每個任務(wù)做什么都定義清楚了欠母。
打包之前要先編譯欢策,所以通過depends來指定依賴的路徑。如果在命令行里執(zhí)行ant build赏淌,那就會先執(zhí)行compile踩寇,而compile又依賴于init,所以就會先執(zhí)行init六水。有了這個東西以后俺孙,我們只要一條命令:

ant test

就可以執(zhí)行編程,打包掷贾,測試了睛榄。為開發(fā)者帶來了很大的便利。
但是ant有一個很致命的缺陷想帅,那就是沒辦法管理依賴场靴。我們一個工程,要使用很多第三方工具博脑,不同的工具憎乙,不同的版本。
每次打包都要自己手動去把正確的版本拷到lib下面去叉趣,這個工作既枯燥還特別容易出錯。為了解決這個問題该押,maven登場了疗杉。

2.java平臺常用的構(gòu)建工具之maven.

Maven作為后來者,繼承了Ant的項目構(gòu)建功能蚕礼,同樣采用了XML作為構(gòu)建腳本的格式烟具。Maven具有依賴管理和項目管理的功能,提供了中央倉庫奠蹬,能幫助我們自動下載庫文件朝聋。
maven最核心的改進就在于提出倉庫這個概念。我可以把所有依賴的包囤躁,都放到倉庫里去冀痕,在我的工程管理文件里荔睹,標(biāo)明我需要什么什么包,什么什么版本言蛇。
在構(gòu)建的時候僻他,maven就自動幫我把這些包打到我的包里來了。我們再也不用操心著自己去管理幾十上百個jar文件了腊尚。這了達到這個目標(biāo)吨拗,maven提出,要給每個包都標(biāo)上坐標(biāo)婿斥,這樣劝篷,便于在倉庫里進行查找。
所以民宿,使用maven構(gòu)建和發(fā)布的包都會按照這個約定定義自己的坐標(biāo)娇妓,例如:

<?xml version="1.0" encoding="utf-8"?>
<project ...xmlns...>
    <groupId>cn.hinus.recruit</groupId>
    <artifactId>Example</artifactId>
    <version>0.1.0-SNAPSHOT</version>
         
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
    </dependencies>
</project>

這樣,就定義了包的坐標(biāo)是cn.hinus.recruit:Example:0.1.0-SNAPSHOT勘高,而我的工程要依賴junit:junit:4.10峡蟋。那么maven就會自動去幫我把junit打包進來
。如果我本地沒有junit华望,maven還會幫我去網(wǎng)上下載蕊蝗。下載的地方就是遠(yuǎn)程倉庫,我們可以通過repository標(biāo)簽來指定遠(yuǎn)程倉庫赖舟。
maven里拋棄了ant中通過target定義任務(wù)的做法蓬戚,而是引入了生命周期的概念。

maven的缺點有:
  • maven是使用xml進行配置的宾抓,語法不簡潔子漩。
  • maven在約定優(yōu)于配置這條路上走太遠(yuǎn)了。就是說石洗,maven不鼓勵你自己定義任務(wù)幢泼,它要求用戶在maven的生命周期中使用插件的方式去工作。這有點像設(shè)計模式中的模板方法模式讲衫。
    說通俗一點缕棵,就是我使用maven的話,想靈活地定義自己的任務(wù)是不行的

3.java平臺常用的構(gòu)建工具之Gradle.

gradle充分地使用了maven的現(xiàn)有資源涉兽。繼承了maven中倉庫招驴,坐標(biāo),依賴這些核心概念枷畏。文件的布局也和maven相同别厘。但同時,它又繼承了ant中target的概念拥诡,我們又可以重新定義自己的任務(wù)了触趴。
Gradle不用XML氮发,它使用基于Groovy的專門的DSL或者或Kotlin DSL,從而使Gradle構(gòu)建腳本變得比用Ant和Maven寫的要簡潔清晰雕蔽。
Gradle樣板文件的代碼很少折柠,這是因為它的DSL被設(shè)計用于解決特定的問題:貫穿軟件的生命周期,從編譯批狐,到靜態(tài)檢查扇售,到測試,直到打包和部署嚣艇。Google采用Gradle作為Android OS的默認(rèn)構(gòu)建工具承冰。

// Apply the java plugin to add support for Java
apply plugin: 'java'

// In this section you declare where to find the dependencies of your project
repositories {
    // Use 'jcenter' for resolving your dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}

// In this section you declare the dependencies for your production and test code
dependencies {
    // The production code uses the SLF4J logging API at compile time
    compile 'org.slf4j:slf4j-api:1.7.21'

    // Declare the dependency for your favourite test framework you want to use in your tests.
    // TestNG is also supported by the Gradle Test task. Just change the 
    // testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add 
    // 'test.useTestNG()' to your build script.
    testCompile 'junit:junit:4.12'
}

二. Gradle,Gradle Wrapper和Android Plugin for Gradle。

1. Gradle

Gradle是個構(gòu)建系統(tǒng)食零,能夠簡化你的編譯困乒、打包、測試過程贰谣。
gradle下載地址

2. Gradle Wrapper

Gradle Wrapper稱為Gradle包裝器娜搂,是對Gradle的一層包裝。使用Gradle Wrapper可以在沒有安裝Gradle的情況下使用吱抚。
為什么需要Gradle Wrapper呢百宇?比如在一個開發(fā)團隊中,如果每進來一個成員秘豹,都需要在計算機中安裝Gradle携御,這個時候運行Gradle的環(huán)境和版本就會對構(gòu)建結(jié)果帶來不確定性。
針對這個問題既绕,Gradle提供了一個解決方案啄刹,那就是Gradle Wrapper,它是一個腳本凄贩,可以在計算機沒有安裝Gradle的情況下運行Gradle構(gòu)建誓军,并且能夠指定Gradle的版本,
開發(fā)人員可以快速啟動并運行Gradle項目疲扎,而不必手動安裝谭企,這樣就標(biāo)準(zhǔn)化了項目,從而提高了開發(fā)效率评肆。
Gradle Wrapper生成的文件如下:

|____gradle
| |____wrapper
| | |____gradle-wrapper.jar  //具體業(yè)務(wù)邏輯
| | |____gradle-wrapper.properties  //配置文件
|____gradlew  //Linux 下可執(zhí)行腳本
|____gradlew.bat  //Windows 下可執(zhí)行腳本

打開gradle/wrapper/gradle-wrapper.properties 文件就可以修改配置了。根據(jù)此配置Gradle Wrapper會自動下載合適的Gradle版本非区。默認(rèn)情況下瓜挽,下載位置是在$USER_HOME/.gradle/wrapper/dists。

#規(guī)定了解壓后的gradle包放在哪里(一般是在~/.gradle/wrapper/dists目錄)
distributionBase=GRADLE_USER_HOME 
distributionPath=wrapper/dists
#規(guī)定了gradle的zip包放在哪里
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
#規(guī)定了使用哪個版本的gradle編譯項目征绸,這個地址可以配置成服務(wù)器地址或者本地地址
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip

3. Android Plugin for Gradle

Android Studio構(gòu)建系統(tǒng)基于Gradle久橙,Android Plugin for Gradle添加了一些特定于構(gòu)建Android應(yīng)用程序的功能俄占。雖然Android插件通常與Android Studio保持同步更新,
但插件(以及Gradle系統(tǒng)的其余部分)可獨立于Android Studio運行并單獨更新淆衷。
在android studio中缸榄,項目的根目錄下的build.gradle中會配置如下代碼:

buildscript {
    
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.0'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

這個dependencies中的gradle:3.2.0代表的就是使用gradle 插件版本 3.2.0.在編譯過程中,如果gradle插件版本與gradle版本不匹配祝拯,編譯就會失敗.
目前在使用的gradle與gradle插件版本的對應(yīng)甚带。


gradle插件對應(yīng)gradle版本

三. Android項目中配置gradle

1.頂級Gradle文件。

頂級 build.gradle 文件位于項目根目錄佳头,用于定義適用于項目中所有模塊的構(gòu)建配置鹰贵。 默認(rèn)情況下,此頂級構(gòu)建文件使用 buildscript 代碼塊來定義項目中所有模塊共用的 Gradle 存儲區(qū)和依賴項康嘉。

/**
 * 構(gòu)建塊是您配置存儲庫和的位置
 * Gradle本身的依賴關(guān)系 - 意思是碉输,你不應(yīng)該包含依賴關(guān)系
 * 在這里你的模塊。 例如亭珍,此塊包含Android插件
 * Gradle作為依賴項敷钾,因為它提供了Gradle的附加指令
 * 需要構(gòu)建Android應(yīng)用程序模塊。
 */
buildscript {
    /**
     * 存儲庫塊配置Gradle使用的存儲庫
     * 搜索或下載依賴項肄梨。 Gradle預(yù)先配置對遠(yuǎn)程的支持
     * 依賴倉庫阻荒,如JCenter,Maven Central和Ivy峭范。 您也可以使用本地
     * 存儲庫或定義您自己的遠(yuǎn)程存儲庫财松。 下面的代碼定義
     * JCenter作為存儲庫Gradle應(yīng)該用來查找它的依賴項。
     *
     * 使用Android Studio 3.0及更高版本創(chuàng)建的新項目也包括
     * 谷歌的Maven存儲庫纱控。
     */
    repositories {
        google()
        jcenter()
    }
    /**
     * dependencies塊配置Gradle需要使用的依賴項
     * 建立你的項目辆毡。 以下行添加了Gradle的Android插件
     * 版本3.2.0作為類路徑依賴項。
     */
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.0'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
/**
 * allprojects塊是您配置存儲庫和的地方
 * 項目中所有模塊使用的依賴項甜害,例如第三方插件
 * 或lib舶掖。 但是,您應(yīng)該在其中配置特定于模塊的依賴項
 * 每個模塊級的build.gradle文件尔店。 對于新項目眨攘,Android Studio
 * 默認(rèn)情況下包括JCenter和Google的Maven存儲庫,但事實并非如此
 * 配置任何依賴項(除非您選擇需要某些依賴項的模板)嚣州。
 */

allprojects {
    repositories {
        google()
        jcenter()
    }
}
  • buildScript塊的repositories主要是為了表示只有編譯工具才會用這個倉庫鲫售,獲取腳本依賴插件。
  • allprojects塊的repositories用于多項目構(gòu)建该肴,為所有項目提供共同所需依賴包情竹。而子項目可以配置自己的repositories以獲取自己獨需的依賴包。

2.模塊級Gradle文件匀哄。

apply plugin: 'com.android.application'

android {
    //compilesdkversion指定Android API級別的Gradle應(yīng)用于
    //編譯你的應(yīng)用程序秦效。這意味著您的應(yīng)用程序可以使用
    //此級別及更低級別的API雏蛮。
    compileSdkVersion 28
    //buildToolsVersion指定Gradle用于構(gòu)建應(yīng)用程序的SDK構(gòu)建工具,命令行工具和編譯器的版本阱州。 您需要使用SDK Manager下載構(gòu)建工具挑秉。
    //此屬性是可選的,因為默認(rèn)情況下插件使用推薦版本的構(gòu)建工具苔货。
    buildToolsVersion "28.0.3"
    //defaultConfig塊封裝了所有構(gòu)建變體的默認(rèn)設(shè)置和條目犀概,
    // 并且可以從構(gòu)建系統(tǒng)動態(tài)覆蓋main / AndroidManifest.xml中的某些屬性。
    // 您可以配置產(chǎn)品flavor以覆蓋應(yīng)用程序的不同版本的這些值蒲赂。
    defaultConfig {
        //applicationId唯一標(biāo)識要發(fā)布的包阱冶。
        //但是,您的源代碼仍應(yīng)引用包名稱
        //由main / AndroidManifest.xml文件中的package屬性定義滥嘴。
        applicationId "com.yousheng.myapplication"
        //定義運行應(yīng)用程序所需的最低API級別木蹬。
        minSdkVersion 15
        //指定用于測試應(yīng)用程序的API級別。
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    //您可以在buildTypes塊中配置多個構(gòu)建類型若皱。
    // 默認(rèn)情況下镊叁,構(gòu)建系統(tǒng)定義了兩種構(gòu)建類型:debug和release。該
    //調(diào)試構(gòu)建類型未在默認(rèn)構(gòu)建配置中顯式顯示走触,
    // 但它包含調(diào)試工具晦譬,并使用調(diào)試密鑰進行簽名。 發(fā)布
    // 構(gòu)建類型應(yīng)用Proguard設(shè)置互广,默認(rèn)情況下不簽名敛腌。
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
//依賴項在模塊級構(gòu)建配置文件中阻止
//指定僅構(gòu)建模塊本身所需的依賴項。
dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
}

  • apply plugin 表示應(yīng)用了一個插件惫皱,該插件一般有兩種值可選:
    一種為'com.android.application'像樊,表示該模塊為應(yīng)用程序模塊,可以直接運行旅敷;另一種為'com.android.library'生棍,表示該模塊為庫模塊,只能作為代碼庫依附于別的應(yīng)用程序模塊來運行媳谁。
  • android{}涂滴,在這個閉包中我們可以配置項目構(gòu)建的各種屬性。
  • buildToolsVersion 構(gòu)建工具的版本晴音,其中包括了打包工具aapt柔纵、dx等等〈冈辏可以用高版本的build-tool去構(gòu)建一個低版本的sdk工程首量。
  • compileSdkVersion 用于指定項目的編譯版本,這里指定成28表示使用Android 8.0系統(tǒng)的SDK編譯苍蔬。只影響編譯時的行為癣蟋,不影響運行時的行為渴逻。代碼中可用的api也要與該聲明版本對應(yīng)酝惧,高于聲明版本的api則無法找到嘉抒、使用缀拭。Support庫的大版本號要與compileSdkVersion的大版本號相同
  • minSdkVersion 指明應(yīng)用程序運行所需的最小API level犬耻。如果Android設(shè)備的系統(tǒng)API level低于android:minSdkVersion設(shè)定的值杠人,那么android系統(tǒng)會阻止用戶安裝這個應(yīng)用勋乾。如果指明了這個屬性,并且在項目中使用了高于這個API level的API嗡善, 那么會在編譯時報錯辑莫。
  • targetSdkVersion 表示你在該目標(biāo)版本上已經(jīng)做過了充分的兼容性處理和測試性處理,系統(tǒng)將會為你的應(yīng)用程序啟用一些最新的功能和特性罩引。應(yīng)用運行時使用的sdk版本
    例如:
    android6.0(api 23)系統(tǒng)的動態(tài)權(quán)限檢查功能各吨;targetSdkVersion<23時:該應(yīng)用安裝在android6.0的手機上后,不會執(zhí)行android6.0系統(tǒng)以上特有的動態(tài)權(quán)限檢查邏輯袁铐,而是仍繼續(xù)執(zhí)行以前的權(quán)限檢查邏輯揭蜒。
    當(dāng)targetSdkVersion變?yōu)?3后:android6.0系統(tǒng)的動態(tài)權(quán)限檢查特性將生效。

一般minSdkVersion <targetSdkVersion<= compileSdkVersion剔桨;最好別隨意更改targetSdkVersion屉更,更改targetSdkVersion必須做好兼容。

  • buildTypes 封裝此項目的所有構(gòu)建類型配置洒缀。

四 .Gradle添加構(gòu)建依賴項

要為您的項目添加依賴項瑰谜,請在您的 build.gradle 文件的 dependencies 程序塊中指定依賴項配置。
例如:以下這個應(yīng)用模塊的 build.gradle 文件包括三種不同類型的依賴項:

apply plugin: 'com.android.application'

android { ... }

dependencies {
    // 依賴于本地庫模塊
    implementation project(":mylibrary")

    // 對本地文件的依賴性(jar,arr等)
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    //依賴于遠(yuǎn)程文件
    implementation 'com.example.android:app-magic:12.3'
}

1. 本地library模塊依賴树绩。

implementation project(":mylibrary")

這段代碼聲明名為“mylibrary”的 Android 庫模塊的依賴項(該名稱必須匹配使用 settings.gradle文件中的 include: 定義的庫名稱)萨脑。
在構(gòu)建您的應(yīng)用時,構(gòu)建系統(tǒng)會編譯庫模塊葱峡,并將生成的編譯內(nèi)容打包到 APK中砚哗。

2. 本地二進制文件依賴項。

implementation fileTree(dir: 'libs', include: ['*.jar'])

Gradle 聲明項目 module_name/libs/ 目錄中 JAR 文件的依賴項(因為 Gradle 會讀取 build.gradle 文件的相對路徑)砰奕。
或者蛛芥,您也可以像下面這樣指定單獨的文件:

implementation files('libs/foo.jar', 'libs/bar.jar')

Gradle 聲明項目 module_name/libs/ 目錄中 aar 文件的依賴項:

android {
    ...
    repositories {
        flatDir {
            dirs 'libs'
        }
    }
}
dependencies {
    implementation(name: 'mylibrary-release', ext: 'aar')
}

3. 遠(yuǎn)程二進制文件依賴項。

縮寫形式:

implementation 'com.example.android:app-magic:12.3'

全寫形式:

implementation group: 'com.example.android', name: 'app-magic', version: '12.3'

這段代碼聲明“com.example.android”命名空間組內(nèi)“app-magic”庫 12.3 版本的依賴項军援。

注意:
1.與此類似的遠(yuǎn)程依賴項要求您聲明相應(yīng)的
遠(yuǎn)程代碼庫仅淑,Gradle 應(yīng)在其中尋找該庫。 如果本地尚不存在該庫胸哥,Gradle 會在構(gòu)建需要它時(例如涯竟,當(dāng)您點擊 Sync Project with Gradle Files 或當(dāng)您運行構(gòu)建時)從遠(yuǎn)程站點獲取該庫。
2.指定依賴項時,不應(yīng)使用動態(tài)版本號庐船,比如 'com.android.tools.build:gradle:3.+'银酬。 使用此功能,可能會導(dǎo)致意外版本更新和難以解析版本差異筐钟。

mvnrepository倉庫

五. Gradle依賴倉庫

1. 為何要使用遠(yuǎn)程依賴揩瞪?

手動管理依賴將會帶來很大麻煩。首先必須定位到該依賴文件位置篓冲,然后下載jar文件李破,復(fù)制該文件到項目,然后引用它們壹将。
通常這些jar文件還沒有具體的版本號嗤攻,所以還必須去記憶它們的版本號,這樣當(dāng)需要更新的時候诽俯,才會知道需要替換成哪個版本妇菱。
同時必須將該依賴包放在svn或者git上,這樣其他同事才可以不用手動去下載這些依賴jar惊畏。為了解決這些問題恶耽,就引入了遠(yuǎn)程依賴。

2. 遠(yuǎn)程依賴倉庫分類

試想一下如果我們要把依賴放在遠(yuǎn)程颜启,首先就要有一個存放依賴的倉庫吧偷俭,所以maven倉庫就是干這件事的。
在 Maven 的術(shù)語中缰盏,倉庫是一個位置(place)涌萤,例如目錄,可以存儲所有的工程 jar 文件口猜、library jar 文件负溪、插件或任何其他的工程指定的文件。

Maven 倉庫有三種類型:

  • 本地倉庫(local)
  • 遠(yuǎn)程倉庫(remote)
  • 中央倉庫(central)济炎,(遠(yuǎn)程倉庫的一種)在android開發(fā)中最常用
本地倉庫

Maven本地倉庫是在計算機上的一個文件夾川抡,用來存放所有的 jar等文件,本地倉庫是遠(yuǎn)程倉庫的一個緩沖和子集须尚,當(dāng)你構(gòu)建Maven項目的時候崖堤,首先會從本地倉庫查找資源,如果沒有耐床,那么Maven會從遠(yuǎn)程倉庫下載到你本地倉庫密幔。這樣在你下次使用的時候就不需要從遠(yuǎn)程下載了。如果你所需要的jar包版本在本地倉庫沒有撩轰,而且也不存在于遠(yuǎn)程倉庫胯甩,Maven在構(gòu)建的時候會報錯昧廷,這種情況可能發(fā)生在有些jar包的新版本沒有在Maven倉庫中及時更新。需要由自己維護偎箫。Maven 本地倉庫默認(rèn)被創(chuàng)建在 %USER_HOME% 目錄下木柬。

遠(yuǎn)程倉庫

如果我們是library的作者,我們不想把library放到中央倉庫的服務(wù)器上面镜廉,也可以放在自己定義的特有的maven倉庫服務(wù)器上弄诲,這個時候如果別人想使用我們的library就需要先引入我們的倉庫地址才能使用。

中央倉庫

也是屬于遠(yuǎn)程倉庫的一種這個倉庫是由Maven社區(qū)管理娇唯,由Sonatype公司提供服務(wù),其中包含了大量常用的庫寂玲。且很容易被Apache Ant塔插、Gradle和其他的構(gòu)建工具使用,需要通過網(wǎng)絡(luò)訪問拓哟,通過:http://search.maven.org/#browse 開發(fā)者就可以在里面找到自己所需要的代碼庫想许。

遠(yuǎn)程倉庫和中央倉庫的區(qū)別:
遠(yuǎn)程倉庫一般是由公司或團隊創(chuàng)建的一個倉庫,由公司或團隊維護断序;中央倉庫也是屬于遠(yuǎn)程倉庫的一種不過它是互聯(lián)網(wǎng)上的倉庫流纹,由Maven團隊維護;

3. 依賴搜索順序

Maven 依賴搜索順序

當(dāng)我們執(zhí)行 Maven 構(gòu)建命令時违诗,Maven 開始按照以下順序查找依賴的庫:

  • 步驟 1 : 在本地倉庫中搜索漱凝,如果找不到,執(zhí)行步驟 2诸迟,如果找到了則執(zhí)行其他操作茸炒。
  • 步驟 2 : 在中央倉庫中搜索,如果找不到阵苇,并且有一個或多個遠(yuǎn)程倉庫已經(jīng)設(shè)置壁公,則執(zhí)行步驟 4,如果找到了則下載到本地倉庫中已被將來引用绅项。
  • 步驟 3 : 如果遠(yuǎn)程倉庫沒有被設(shè)置紊册,Maven 將簡單的停滯處理并拋出錯誤(無法找到依賴的文件)。
  • 步驟 4 : 在一個或多個遠(yuǎn)程倉庫中搜索依賴的文件快耿,如果找到則下載到本地倉庫來被引用囊陡,否則 Maven 將停止處理并拋出錯誤(無法找到依賴的文件)。

2. Maven常見的遠(yuǎn)程倉庫

常見的倉庫
MavenCentral倉庫

Maven Central 則是由sonatype.org維護的Maven倉庫润努。你可以在這里看到整個倉庫关斜。
在Android項目的build.gradle 文件中如下定義倉庫,就能使用Maven Central了:

buildscript {
    repositories {
        mavenCentral()
    }
}
allprojects {
    repositories {
        mavenCentral()
    }
}

下載的本地倉庫文件地址:

windows: C:\Users\用戶名\.gradle\caches\modules-2\files-2.1
OSX: /Users/用戶名/.gradle/caches/modules-2/files-2.1

Android Studio早期版本使用的是mavenCentral铺浇,后來切換到j(luò)center了痢畜。

jcenter倉庫

jcenter是一個由 bintray.com維護的Maven倉庫
在Android項目的的build.gradle 文件中如下定義倉庫,就能使用jcenter了:

buildscript {
    repositories {
        jcenter()
    }
}
allprojects {
    repositories {
        jcenter()
    }
}

下載的本地倉庫文件地址:

windows: C:\Users\用戶名\.gradle\caches\modules-2\files-2.1
OSX: /Users/用戶名/.gradle/caches/modules-2/files-2.1

注意,雖然jcenter和Maven Central 都是標(biāo)準(zhǔn)的 android library倉庫丁稀,但是它們維護在完全不同的服務(wù)器上吼拥,由不同的人提供內(nèi)容,兩者之間毫無關(guān)系线衫。在jcenter上有的可能 Maven Central 上沒有凿可,反之亦然。

Android為何有兩個標(biāo)準(zhǔn)的倉庫授账?
事實上兩個倉庫都具有相同的使命:提供Java或者Android library倉庫儲存服務(wù)枯跑。上傳到哪個(或者都上傳)取決于開發(fā)者。起初白热,Android Studio 選擇Maven Central作為默認(rèn)倉庫敛助。
如果你使用老版本的Android Studio創(chuàng)建一個新項目,mavenCentral()會自動的定義在build.gradle中屋确。但是Maven Central的最大問題是對開發(fā)者不夠友好纳击。上傳library異常困難。
同時還因為諸如安全方面的其他原因攻臀,Android Studio團隊決定把默認(rèn)的倉庫替換成jcenter焕数。如今一旦使用最新版本的Android Studio創(chuàng)建一個項目,jcenter()自動被定義刨啸,而不是mavenCentral()堡赔。
至于為何google替換成jcenter的理由,下面是幾個主要的原因:

  • jcenter是全世界最大的Java倉庫呜投,因此在Maven Central 上有的加匈,在jcenter上也極有可能有。換句話說jcenter是Maven Central的超集仑荐。
  • 上傳library到倉庫很簡單雕拼,不需要像在 Maven Central上做很多復(fù)雜的事情。
  • jcenter通過CDN發(fā)送library粘招,使用的是https協(xié)議啥寇,安全性更高,而Android Studio 0.8版本mavenCentral使用的是http協(xié)議
  • jcenter性能方面比mavenCentral更優(yōu)
  • mavenCentral會自動下載很多與IDE相關(guān)的index洒扎,而這些用到的少辑甜,且不是必需

注:不管是jcenter還是Maven Central ,兩者都是Maven倉庫袍冷。

自建遠(yuǎn)程倉庫

除了兩個標(biāo)準(zhǔn)的中央倉庫之外磷醋,如果我們使用的library的作者是把該library放在自己的服務(wù)器上,我們還可以自己定義特有的Maven倉庫服務(wù)器胡诗。
Twitter的Fabric.io 就是這種情況邓线,它們在https://maven.fabric.io/public上維護了一個自己的Maven倉庫淌友。
如果你想使用Fabric.io的library,你必須自己如下定義倉庫的url骇陈。

repositories {
    maven { url 'https://maven.fabric.io/public' }
}

然后在里面使用相同的方法獲取一個library震庭。

dependencies {
    compile 'com.crashlytics.sdk.android:crashlytics:2.2.4@aar'
    //新版as用 implementation 代替 compile
}

library上傳到標(biāo)準(zhǔn)的服務(wù)器與自建服務(wù)器倉庫,哪種方法更好呢你雌?這個需要看自身的需求器联。如果將自己的library公開,使得其他的開發(fā)者也能使用婿崭,則自建服務(wù)器倉庫拨拓。

google倉庫

在gradle4.1以后,添加了新的語法google()氓栈,用于引用google自有的倉庫千元,很方便。由于google的倉庫是不支持瀏覽的颤绕,只支持下載,所以不便于研究被依賴的aar源文件祟身。
可以通過以下的網(wǎng)址查看支持支持下載的包: google
在Android項目的的build.gradle 文件中如下定義倉庫奥务,就能使用google了:

buildscript {
    repositories {
        google()
    }
}   
allprojects {
    repositories {
        google()
    }
}

下載的本地倉庫文件地址:

windows: C:\Users\用戶名\.gradle\caches\modules-2\files-2.1
OSX: /Users/用戶名/.gradle/caches/modules-2/files-2.1

當(dāng)然Android Studio自帶了一些庫,支持庫在sdk中袜硫,gradle插件一般在Android Studio安裝目錄氯葬。

jitpack倉庫

JitPack提供的倉庫。在Android項目的build.gradle 文件中如下定義倉庫婉陷,就能使用JitPack了:

buildscript {
    repositories {
          maven { url "https://jitpack.io" }
    }
}   
allprojects {
    repositories {
         maven { url "https://jitpack.io" }
    }
}

4. 遠(yuǎn)程倉庫鏡像(阿里云的國內(nèi)鏡像)

在國內(nèi)使用jcenter帚称、mavenCentral及google三個遠(yuǎn)程倉庫,GradleSync會很慢秽澳,goole倉庫甚至需要科學(xué)上網(wǎng)才能訪問闯睹。為了加快Gradle Sync速度,可以優(yōu)先使用阿里云鏡像 倉庫作為下載源担神。
如果下載相關(guān)依賴失敗楼吃,可以嘗試用鏡像倉庫地址。

buildscript {
    repositories {
        maven{ url 'https://maven.aliyun.com/repository/public'}
        maven { url 'https://maven.aliyun.com/repositories/jcenter' }
        maven { url 'https://maven.aliyun.com/repositories/google' }
        maven { url 'https://maven.aliyun.com/repository/central' }
        //jcenter()
        //mavenCentral()
        //google()
    }
}
     
allprojects {
    repositories {
        maven{ url 'https://maven.aliyun.com/repository/public'}
        maven { url 'https://maven.aliyun.com/repositories/jcenter' }
        maven { url 'https://maven.aliyun.com/repositories/google' }
        maven { url 'https://maven.aliyun.com/repository/central' }
        maven { url "https://jitpack.io" }
        //jcenter()
        //mavenCentral()
        //google()
    }
}

阿里云倉庫地址

六. Gradle引入依賴方式

如果你想在Android項目中引入一個第三方library到你的項目妄讯,你只需添加如下的一行代碼到模塊的build.gradle文件中孩锡。

dependencies {
    compile 'com.squareup.okhttp:okhttp:2.4.0 
    //新版本as為implementation,代替compile
}

就是如此簡單的一行代碼亥贸,你就可以使用這個library了躬窜。引用一個library的代碼需要3個部分,即:
GROUP_ID炕置、ARTIFACT_ID荣挨、VERSION
在這句代碼里面的

  • GROUP_ID 是com.squareup.okhttp男韧, 有可能在同樣的上下文中存在多個不同功能的library。如果library具有相同的group垦沉,那么它們將共享一個GROUP_ID煌抒。通常我們以開發(fā)者包名緊跟著library的group名稱來命名,比如com.squareup.okhttp厕倍。
  • ARTIFACT_ID 是okhttp寡壮, 就是library的真實名稱。
  • VERSION 是2.4.0 就是版本號而已讹弯,雖然可以是任意文字况既,建議設(shè)置為x.y.z的形式,如果喜歡還可以加上beta這樣的后綴组民。

上面以Square library的一個例子棒仍。你可以看到每個都可以很容易的分辨出library和開發(fā)者的名稱。

添加了上面的依賴之后臭胜,Gradle會詢問Maven倉庫服務(wù)器這個library是否存在莫其,如果存在,gradle會獲得請求library的路徑耸三,一般這個路徑都是這樣的形式:GROUP_ID/ARTIFACT_ID/VERSION_ID乱陡。
比如可以在http://jcenter.bintray.com/com/squareup/otto/1.3.7
https://oss.sonatype.org/content/repositories/releases/com/squareup/otto/1.3.7/
下獲得com.squareup: okhttp:2.4.0的library文件。然后Android Studio 將下載這些文件到我們的電腦上仪壮,與我們的項目一起編譯憨颠。整個過程就是這么簡單。

從倉庫上下載的library只是存儲在倉庫服務(wù)器上的jar 或者aar文件而已积锅。有點類似于自己去下載這些文件爽彤,拷貝然后和項目一起編譯。但是使用gradle依賴管理的最大好處是你除了添加幾行文字之外啥也不做缚陷。
添加完依賴就會下載庫然后和項目一起編譯适篙。

在 dependencies {}內(nèi),您可以使用幾種不同依賴項配置中的一種(例如上文所示的 implementation)聲明庫依賴項蹬跃。 每項依賴項配置都為 Gradle 提供有關(guān)如何使用依賴項的不同說明匙瘪。
下表介紹您可以在 Android 項目中對依賴項使用的每種配置。 此表還將這些配置與自 Android Gradle Plugin 3.0.0 起棄用的配置進行比較蝶缀。

新配置 已棄用配置 行為
implementation compile Gradle 會將依賴項添加到編譯類路徑丹喻,并將依賴項打包到構(gòu)建輸出。但是翁都,當(dāng)您的模塊配置 implementation 依賴項時碍论,會告知 Gradle 您不想模塊在編譯時將依賴項泄露給其他模塊。使用此依賴項配置而不是 apicompile(已棄用)柄慰,可以顯著縮短構(gòu)建時間鳍悠,因為它可以減少構(gòu)建系統(tǒng)需要重新編譯的模塊數(shù)量税娜。例如,如果 implementation 依賴項更改了其 API藏研,Gradle 只會重新編譯該依賴項和直接依賴它的模塊敬矩。大多數(shù)應(yīng)用和測試模塊都應(yīng)使用此配置。
api compile Gradle 會將依賴項添加到編譯類路徑蠢挡,并構(gòu)建輸出弧岳。當(dāng)模塊包括 api 依賴項時,會告知 Gradle 模塊想將該依賴項間接導(dǎo)出至其他模塊业踏,以使這些模塊在運行時和編譯時均可使用該依賴項禽炬。此配置的行為類似于 compile (現(xiàn)已棄用),但您應(yīng)僅對需要間接導(dǎo)出至其他上游消費者的依賴項慎重使用它勤家。 這是因為腹尖,如果 api 依賴項更改了其外部 API,Gradle 會重新編譯可以在編譯時訪問該依賴項的所有模塊伐脖。 因此热幔,擁有大量 api 依賴項會顯著增加構(gòu)建時間。 如果不想向不同的模塊公開依賴項的 API讼庇,庫模塊應(yīng)改用 implementation 依賴項断凶。
compileOnly provided Gradle 只會將依賴項添加到編譯類路徑(即不會將其添加到構(gòu)建輸出)。如果是創(chuàng)建 Android 模塊且在編譯期間需要使用該依賴項巫俺,在運行時可選擇呈現(xiàn)該依賴項,則此配置會很有用肿男。如果使用此配置介汹,則您的庫模塊必須包含運行時條件,以便檢查是否提供該依賴項舶沛,然后妥善更改其行為嘹承,以便模塊在未提供依賴項的情況下仍可正常工作。這樣做不會添加不重要的瞬時依賴項如庭,有助于縮減最終 APK 的大小叹卷。 此配置的行為類似于 provided (現(xiàn)已棄用)。
runtimeOnly apk Gradle 只會將依賴項添加到構(gòu)建輸出坪它,供運行時使用骤竹。也就是說,不會將其添加到編譯類路徑往毡。 此配置的行為類似于 apk(現(xiàn)已棄用)蒙揣。
annotationProcessor compile 要在庫中添加注解處理器依賴項,則必須使用 annotationProcessor 配置將其添加到注解處理器類路徑开瞭。這是因為使用此配置可分離編譯類路徑與注解處理器類路徑止潮,從而提升構(gòu)建性能点把。如果 Gradle 在編譯類路徑上找到注解處理器拼缝,則會停用 避免編譯功能,這樣會增加構(gòu)建時間(Gradle 5.0 和更高版本會忽略編譯類路徑上的注解處理器)瓷炮。如果 JAR 文件包含以下文件,則 Android Gradle Plugin 會假定依賴項是注解處理器:META-INF/services/javax.annotation.processing.Processor递宅。 如果插件檢測到編譯類路徑上包含注解處理器娘香,則會生成構(gòu)建錯誤。

要為您的本地測試和設(shè)備化測試添加 implementation 依賴項恐锣,需要使用下面這樣的代碼:

dependencies {
    // Adds a remote binary dependency only for local tests.
    testImplementation 'junit:junit:4.12'

    // Adds a remote binary dependency only for the instrumented test APK.
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
  • implementation: 會添加依賴到編譯路徑茅主,并且會將依賴打包到輸出(aar或apk),但是在編譯時不會將依賴的實現(xiàn)暴露給其他module土榴,也就是只有在運行時其他module才能訪問這個依賴中的實現(xiàn)诀姚。只能在內(nèi)部使用此模塊,比如我在一個libiary中使用implementation依賴了gson庫玷禽,然后我的主項目依賴了libiary赫段,那么,我的主項目就無法訪問gson庫中的方法矢赁。
  • api: 會添加依賴到編譯路徑糯笙,并且會將依賴打包到輸出(aar或apk),與implementation不同撩银,這個依賴可以傳遞给涕,其他module無論在編譯時和運行時都可以訪問這個依賴的實現(xiàn)

implementation 和api的區(qū)別:


App Module依賴于LibraryA ,而LibraryA依賴了LibraryB。如果LibraryALibraryB的依賴用的是 implementation關(guān)鍵字额获。那么LibraryB中的接口够庙,僅僅只能給 LibraryA 使用,App Module 是無法訪問到 LibraryB 提供的接口的。如果LibraryALibraryB 的依賴用的是 api關(guān)鍵字,則LibraryB中的接口抄邀,不僅可以給 LibraryA 使用,而且還可以給App Module使用耘眨。

  • compileOnly Gradle把依賴加到編譯路徑,編譯時使用境肾,不會打包到輸出(aar或apk)剔难。這可以減少輸出的體積,在只在編譯時需要奥喻,在運行時可選的情況偶宫。


    如果App Module依賴于A Lib、B Lib环鲤、C Lib读宙。A LibB Lib也依賴于C Lib。此時我們就可以讓A LibB Lib通過compileOnly去依賴于C Lib楔绞。減少依賴沖突的可能性结闸。

  • runtimeOnly 與compileOnly對應(yīng)唇兑,gradle添加依賴只打包到APK,運行時使用桦锄,但不會添加到編譯路徑,會導(dǎo)致編譯無法通過,一般是不會用到扎附。

  • annotationProcessor 用于注解處理器的依賴配置。

注:Android Plugin for Gradle 3.0.0+ 不再支持 android-apt 插件结耀。

七. 依賴管理

1. Gradle命令查看依賴層級樹.

打開terminal控制臺命令.

gradlew :app(模塊名):dependencies  //列出所有的依賴
gradlew :app(模塊名):dependencies >log.txt //查看依賴關(guān)系保存到log.txt文件夾下面
gradlew -q dependencies app:dependencies --configuration releaseRuntimeClasspath                
//列出某一環(huán)境下的依賴(實例為releaseRuntimeClasspath)

關(guān)于其他配置類型參數(shù)可以通過如下命令獲得:

gradlew dependencies --info

同一個庫存在 多個版本時, gradle 會自動 使用最高版本的庫 應(yīng)用到 所有地方,如果后面帶有 “(*)” 的庫就表示 這個庫 有被覆蓋過留夜。

2. 使用Gradle View插件查看依賴層級樹。

  1. 在plugins中找到Gradle View插件安裝,重啟As图甜。
  2. 在View->Tool windows->找到Gradle View點擊碍粥。


3. 傳遞依賴。

在Maven倉庫中黑毅,構(gòu)件通過POM(一種XML文件)來描述相關(guān)信息以及傳遞性依賴嚼摩。Gradle 可以通過分析該文件,獲取所有的依賴以及依賴的依賴和依賴的依賴的依賴。
例如:



可以看到矿瘦,我們的項目依賴了hibernate,然而hibernate卻依賴了一眾別的依賴.借助Gradle的傳遞性依賴特性枕面,你無需再你的腳本中把這些依賴都聲明一遍,你只需要簡單的一行缚去,Gradle便會幫你將傳遞性依賴一起下載下來潮秘。

  implementation 'org.hibernate:hibernate-core:3.6.3.Final'

傳遞依賴特性可以輕松地通過transitive參數(shù)進行開啟或關(guān)閉,傳遞性依賴可以采用指定 transitive = false 的方式來關(guān)閉依賴傳遞特性,也可以采用添加@jar(@aar)的方式忽略該依賴的所有傳遞性依賴易结。

implementation ('org.hibernate:hibernate-core:3.6.3.Final'){
        transitive = false
    }

或者:

 implementation 'org.hibernate:hibernate-core:3.6.3.Final@jar'

查看依賴關(guān)系為:


全局性的關(guān)閉依賴傳遞特性:

dependencies {
configurations.all {
   transitive = false
}
...
}

4. 排除依賴枕荞。

有些時候你可能需要排除一些傳遞性依賴中的某個模塊,此時便不能靠單純的關(guān)閉依賴傳遞特性來解決了搞动。這時exclude就該登場了买猖。exclude可以解決部分依賴傳遞問題。

  • 依賴沖突時滋尉,如果有兩個依賴引用了相同jar包的不同版本時,默認(rèn)情況下gradle會采用最新版本的jar包飞主,此時可以通過排除選項來排除狮惜。
  • 運行期無需此模塊的。
  • 無法正常獲取到此傳遞依賴碌识,遠(yuǎn)程倉庫都不存在的碾篡。
  • 版權(quán)原因需要排除的。
    比如說我需要對依賴模塊mylibrary的support appcompat-v7和support support-annotations進行排除則可以使用:
   implementation('cn.qqtheme.framework:WheelPicker:1.5.1') {
        exclude group:'com.android.support' ,module: 'support-v4'
        exclude group:'com.android.support' ,module: 'support-annotations'
    }

排除前:



排除后:


八. AAR包.

1.aar對比jar的優(yōu)勢筏餐。

  • jar文件:只包含class文件和清單文件开泽,不包含資源文件,比如圖片等所有的 res下的資源文件魁瞪。
  • aar文件:包含class文件以及res下的所有的資源文件穆律。

2.創(chuàng)建aar包惠呼。


4.aar包容易出現(xiàn)的問題。

aar不得包含 assets 原始資源

工具不支持在庫模塊中使用原始資源文件(保存在 assets/ 目錄中)峦耘。應(yīng)用使用的任何原始資源都必須存儲在應(yīng)用模塊自身的 assets/ 目錄中剔蹋。

minSdkVersion問題

AAR 作為相關(guān)應(yīng)用模塊的一部分編譯,因此辅髓,庫模塊中使用的 API 必須與應(yīng)用模塊支持的平臺版本兼容泣崩,所以 AAR 中的 minSdkVersion 要盡量的設(shè)置低一點。

AAR 內(nèi)部三方庫依賴的問題
使用 Android Studio 打包出來的 AAR 洛口,不會將其依賴的三方庫打包進去矫付。

例如,library Test 依賴了 okhttp第焰,打包成了 Test.aar ,app 使用本地方式引用了 Test.aar买优,但是無法使用 okhttp,為了不報錯樟遣,app還需要添加 okhttp 依賴而叼。
為什么 Android Studio 不能將Lib的多個依賴打包進AAR文件的原因是:將不同的library打包在一起,涉及到資源和配置文件智能合并豹悬,所以是個比較復(fù)雜的問題葵陵,同時也容易造成相同的依賴沖突。
這個問題可以通過使用 Maven 依賴解決瞻佛。因為 library Module 上傳 Maven 后脱篙,會生成 一個 .pom 文件,記錄 library Module 的依賴伤柄。
當(dāng) Gradle 依賴 Maven 上的這個庫時绊困,會通過 pom 文件下載對應(yīng)依賴。如果不想要對應(yīng)依賴的話适刀,可以通過下面的方法關(guān)閉 Gradle 的依賴傳遞秤朗。

//正常依賴
implementation 'com.chemao.android:chemao-sdk:1.2.3'

//關(guān)閉全部依賴傳遞-方法1
implementation 'com.chemao.android:chemao-sdk:1.2.3@aar'

//關(guān)閉全部依賴傳遞-方法2
implementation('com.chemao.android:chemao-sdk:1.2.3') {
        transitive = false
}

所以不建議使用本地aar的兩個原因:

  1. aar中的第三個庫無法使用遠(yuǎn)程依賴
  2. 如果使用本地maven,需要每個參與開發(fā)的人員都配置一個本地的maven倉庫,不現(xiàn)實
多級aar引用導(dǎo)致的問題

問題描述
ModuleLib B引用了一個aar,ModuleApp A引用了ModuleLib B,此時就會報找不到Lib的問題。


問題分析
對于 ModuleApp A來說笔喉,他們依賴了ModuleLib B取视,不管用不用,他們都會去把ModuleLib B的依賴走一遍常挚,當(dāng)走到添加的aar本地依賴時作谭,他們?nèi)フ襛ar的路徑也需要給出,而且給的方式如果是libs這樣的路徑奄毡,它會去找自己包下的libs折欠,里邊自然沒有。
解決方式

在ModuleApp A中給出ModuleLib B的lib目錄:

android {
    ...
    repositories {
      flatDir {
            dirs  'libs','../ModuleLib B Name/libs'
        }
    }
}
aar包中的資源文件重復(fù)了

資源文件重復(fù)了,主工程的資源文件會直接覆蓋aar包中的文件锐秦,并且不會有任何報錯或者提示咪奖,最終aar包中也會直接用主工程的資源文件,所以需要注意命名方式农猬。暫時沒有更好的解決方法赡艰。

九. support支持庫.

1. 添加support支持庫的原因

Google為啥要弄這么多支持庫,直接放到sdk里面不好么斤葱? 參閱官方文檔有下面3個原因:

  • 向后兼容
    比如慷垮,我們開發(fā)的App需要支持的minSdkVersion=9,targetSdkVersion=11揍堕,在程序里使用了android 3.0 (API level 11)提供的ActionBar類料身,使用compileSdkVersion=11成功編譯出apk。在android 3.0的設(shè)備上完美運行衩茸,但是app在android 2.3的設(shè)備就會crash芹血,報找不到ActionBar的錯誤。這很好理解楞慈,因為舊版本上沒有新版本里新增的類幔烛。為了避免使用了最新功能開發(fā)的app只能在最新系統(tǒng)的設(shè)備上運行的尷尬,官方把新版系統(tǒng)framework中新增加的接口提出來放到了Android Support Library(支持包)中囊蓝,開發(fā)者在遇到上面的情況時饿悬,就可以使用支持包中具有同樣功能的ActionBar類,這個支持包會打包進App里聚霜,這樣使用了新版本系統(tǒng)上功能的App也可以向后兼容以前的老系統(tǒng)版本設(shè)備了狡恬。
    使用支持包中的類除了讓我們免于判斷App運行的系統(tǒng)版本外,還可以使App在各個版本保持同樣的用戶體驗蝎宇。如在5.0以下系統(tǒng)使用material design弟劲。
    App編譯時用的android sdk(android.jar)不會打包進我們的App中。因為App編碼是使用android.jar中的接口就是android設(shè)備里系統(tǒng)框架層(framework)對外提供的接口姥芥。

  • 提供不適合打包進framework的功能
    Android官方對App開發(fā)提供了推薦設(shè)計兔乞,希望Android應(yīng)用都有相對一致的交互設(shè)計來減少用戶的使用成本,希望三方App類似系統(tǒng)應(yīng)用從而完美融入到Android生態(tài)系統(tǒng)中凉唐。但是這都僅僅是推薦庸追,不要求開發(fā)者一定要這樣,如果有這種需求就可以使用官方支持包提供的這些功能熊榛,避免重復(fù)造輪子。如支持包中的DrawerLayout腕巡、Snackbar等類都是這種情況玄坦。

  • 為了支持不同形態(tài)的設(shè)備
    通過使用支持包來在不同形態(tài)設(shè)備上提供功能,如手機、電視煎楣、可穿戴設(shè)備等豺总。

2. support分類:

android-support-v4
compile "com.android.support:support-v4

2011年4月份,谷歌推出最低兼容到1.6版本系統(tǒng)的包择懂。
eclipse新建工程時喻喳,都默認(rèn)包含了,里面有類似Fragment困曙,NotificationCompat表伦,LoadBroadcastManager,ViewPager慷丽,PageTabAtrip蹦哼,Loader,F(xiàn)ileProvider 等等控件要糊。V4包含了V7和V13的基礎(chǔ)功能纲熏。

android-support-v7
compile "com.android.support:appcompat-v7:xx.xx"

2014年 I/O大會時推出,最低兼容Android2.1系統(tǒng)锄俄。最新的v7包增加了很多material design的兼容類和素材局劲,其中涉及的內(nèi)容有Theme、value奶赠、布局鱼填、新的控件、新的動畫實現(xiàn)方式车柠,包含了support-v4的全部內(nèi)容剔氏。但是v7是要依賴v4這個包的,也就是如果要使用竹祷,兩個包得同時被引用谈跛。
android studio在創(chuàng)建工程的時候默認(rèn)導(dǎo)入了v7工程,并且將style使用了兼容style塑陵。

android-support-v13

為平板開發(fā)推出的版本兼容包感憾,最低兼容Android3.2的系統(tǒng)×罨ǎ可以說Android 3.x系統(tǒng)都是平板專用系統(tǒng)阻桅。但是3.x系統(tǒng)失敗了,所以使用v13的包沒有任何價值。

3. androidX

從android9.0 (API28)開始, support庫將會進行改動, V7: 28.0.0將會是support庫的終結(jié)版本兼都。未來新的特性和改進都會進入Androidx包嫂沉。其主要原因是support庫的命名已經(jīng)越來越令人迷惑 ,包越來越臃腫扮碧。
依賴包的變化從:

api 'com.android.support:appcompat-v7:28.0.0'

變成了:

api 'androidx.appcompat:appcompat:1.0.0'

需要注意的是趟章,build.gradle中的插件版本要在3.2.0以上才可以杏糙。


image.png

十. AndroidManifest合并沖突.

1. 問題描述

Android Studio 項目每個依賴的module中都可以有一個AndroidManifest.xml文件,但最終的APK 文件只能包含一個 AndroidManifest.xml 文件蚓土。在構(gòu)建應(yīng)用時宏侍,Gradle 構(gòu)建會將所有清單文件合并到一個封裝到 APK 的清單文件中。例如在app的manifest中有application節(jié)點下有l(wèi)abel屬性.app所依賴的mylibrary的manifest中application節(jié)點下也有l(wèi)abel屬性,打包的時候則會出現(xiàn)問題:



打開manifest可以看到合并的信息中有報錯:


2. 解決問題

清單文件屬性沖突時:用tools:replace="屬性名"解決蜀漆。例如上面例子是label屬性存在沖突就可以使用:

 tools:replace="label"

參考資料:
構(gòu)建工具的進化:ant, maven, gradle
Android官方文檔之targetSdkVersion等介紹
Android官方文檔之支持庫
Android studio gradle系列二
構(gòu)建工具的進化:ant, maven, gradle

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谅河,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子确丢,更是在濱河造成了極大的恐慌绷耍,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蠕嫁,死亡現(xiàn)場離奇詭異锨天,居然都是意外死亡,警方通過查閱死者的電腦和手機剃毒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門病袄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人赘阀,你說我怎么就攤上這事益缠。” “怎么了基公?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵幅慌,是天一觀的道長。 經(jīng)常有香客問我轰豆,道長胰伍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任酸休,我火速辦了婚禮骂租,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘斑司。我一直安慰自己渗饮,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布宿刮。 她就那樣靜靜地躺著互站,像睡著了一般。 火紅的嫁衣襯著肌膚如雪僵缺。 梳的紋絲不亂的頭發(fā)上胡桃,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天,我揣著相機與錄音磕潮,去河邊找鬼翠胰。 笑死懊纳,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的亡容。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼冤今,長吁一口氣:“原來是場噩夢啊……” “哼闺兢!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起戏罢,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤屋谭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后龟糕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體桐磁,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年讲岁,在試婚紗的時候發(fā)現(xiàn)自己被綠了我擂。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡缓艳,死狀恐怖校摩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情阶淘,我是刑警寧澤衙吩,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站溪窒,受9級特大地震影響坤塞,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜澈蚌,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一摹芙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧惜浅,春花似錦瘫辩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至裸影,卻和暖如春挣轨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背轩猩。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工卷扮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留荡澎,地道東北人。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓晤锹,卻偏偏與公主長得像摩幔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子鞭铆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,107評論 2 356

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