Gradle 入門到精通(三)

前言

根據我們上一篇的介紹,我們知道了項目的結構以及構建的流程,根據上面的知識,我們知道了構建的規則實際就是我們寫在build.gradle的內容。gradle android插件讀取這個文件的內容後,最後完成構建工作。在講解實際內容前,我先提供一個網站給大家,因爲gradle android 插件 是通過dsl語言編寫的,所以我們需要知道在什麼地方獲取相應的api。

7 build.gradle文件分析

https://docs.gradle.org/3.5/dsl/

https://google.github.io/android-gradle-dsl/current/

第一個網站是gradle官方提供的dsl,第二個網站是google提供的dsl查詢手冊

7.1 根目錄的build.gradle文件

我們來打開根目錄下面的build.gradle文件,這個文件是整個項目的配置文件,我們一般是放置一些基礎的配置。

上圖是build.gradle文件的內容

7.1.1 buildscript

buildscript{} 這個是基礎配置,所有的子模塊都會讀取到這個配置裏面的內容,當構建開始的時候,就開始讀取這個 buildscript{} 裏面的內容。

repositories{} 這個模塊的內容告訴gradle 去什麼地址下載第三方的庫。

jcenter() 代表 https://bintray.com/bintray/jcenter

mavenCentral() 代表使用maven的服務器 https://search.maven.org/

但是有一個問題就是上面的兩個網站在中國訪問速度慢

buildscript {
    repositories {
        maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
    }
}

可以使用阿里雲的maven服務

7.1.2 allprojects

allprojects 一般是配置所有模塊的共同使用的內容。

    allprojects {
        repositories {
                jcenter()
      }
    }

這個是默認的配置,代表所有的子modle都是從jcenter獲取第三方包的。我建議大家可以改成下面的寫法

     allprojects {
         repositories {
           maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
     }
   }

7.1.3 gradle插件以及gradle版本的關係

在根目錄上面的build.gradle的版本我們可以設置gradle 插件的版本號,初學者經常搞不懂插件與gradle的關係。特別是個版本之間的關係,下面我們來講講插件設置的方式。

最後的序號就是插件的版本號,注意插件不是gradle,插件是根據gradle特性編寫爲完成需求的jar包,插件依賴於gradle。

 dependencies {
       classpath 'com.android.tools.build:gradle:2.3.0'

    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
   }

如果你使用的是2.3版本的插件,必須使用gradle3.3以上的版本。

如果你使用的是2.2版本的插件,必須使用gradle2.14.1以上的版本。

基本原則就是對照上面的表,看看你使用的是什麼版本的插件。

那gradle的版本設置在哪裏設置呢?我們打開gradle文件夾找到gradle-wrapper.properties文件,如下圖所示

最後我再介紹一個方法,經常有同學說打開一個項目很久,其實就是去下載gradle.我們可以根據上面的這個表來手動下載gradle。然後放置到相應的文件夾內,下面的兩張圖片是插件的文件目錄和gradle的文件目錄

7.2 子項目的build.gradle

一般在稍微大一點的項目中,我們都按照業務邏輯分好不同的模塊。根目錄下的build.gradle是對所有模塊起效果的基礎配置,而每個模塊下的build.gradle是這個模塊的詳細構建的配置,下面我們來學習一下有哪些內容。

上面的這張圖片是默認的build的內容。我們看到內容可以分成三份。

7.2.1 apply

apply plugin: 'com.android.application'

這句話告訴gradle使用什麼類型的插件進行構建。上面的是構建應用的,如果是構建庫文件的是有下面的

 apply plugin: 'com.android.library'

7.2.2 dependencies{} 依賴配置

這個模塊是聲明項目的依賴,爲什麼我們要配置依賴呢?我們的項目大部分需要使用第三方庫,而第三庫很有可能還有其他的依賴,比如說Okhttp。這個依賴的內容由gradle進管理,免除了開發者下載、導入、設置等繁瑣的炒作。這個內容不是android gradle 插件提供了,是gradle提供的,也就是說不止android,java,c++,只要是使用gradle構建的項目都能夠使用這個模塊聲明。

這個模塊是聲明項目的依賴,可以依賴本地的文件,遠程的資源庫,本地的library庫。詳細的參數我們可以查詢gradle Dsl的工具頁面。

https://docs.gradle.org/current/userguide/artifact_dependencies_tutorial.html

如果英語好的同學可以看到,gradle支持了4種依賴的模式。

  • compile 意思是告訴gradle編譯代碼是需要使用的依賴。
  • runtime 產品代碼在運行時需要的依賴。
  • testCompile 編譯測試代碼時所需要的依賴。
  • testRuntime 運行測試時需要的依賴。

其中 runtime會包括compile的依賴。 testRuntime會包括testCompile的依賴。但是很遺憾的是,android gradle plugings不支持runtime,所以android只包含上面的compile、testCompile兩種模式。

那爲什麼會有兩種不一樣的模式了,其實是這樣的,比如在java Web中,編譯的時候需要的是servlet的依賴,但是運行的時候,就由服務器的容器提供,所以需要分開來,但是在android中,基本上使用的依賴就是一起把類文件編譯打包到apk,所以沒有runtime與compile的區別。

7.2.2.1 compile 編譯時導入依賴

遠程依賴

compile是gradle依賴使用最多的關鍵字,在build.gradle中使用了compile後,gradle就會去repositories中加載,我們看看如果在我們的項目中使用了OKHTTP的寫法是怎麼寫的呢?

 compile 'com.squareup.okhttp3:okhttp:3.8.0'

這個是最簡單的寫法,我們剛開始從eclipse轉到android studio開發的時候就知道整兒寫了,但是世界實際這個一個簡短的寫法。規範的寫法應用是這樣。

 compile group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.8.0'

同步完成後,我們可以在External Libraries下面找到添加的依賴

)

本地依賴

gradle 提供了下載遠程依賴包的能力,這個方式也是目前最流行的方式,但是考慮到國情等情況,我們也經常需要使用本地的jar包、AAR包、libery依賴。下面我們來學習這幾種依賴的寫法

本地jar包
  compile fileTree(include: ['*.jar'], dir: 'libs')

上面這句話就把libs下面的jar包,導入到項目中,也就是綁定到項目的classPath.也可以單獨制定某一個jar包。

  compile files('libs/xxxx.jar')

上面的這兩種方法都是導入jar包的方法,如果需要導入aar包,我們需要按照下面的來寫。

本地aar包
 repositories {
     flatDir {
        dirs 'libs'
    }
}

增加一個本地的源目錄。將aar文件放入libs文件夾。

 compile(name: '不帶後綴的文件名', ext: 'aar')

同步完成後就可以使用導入的類庫了。

library依賴

我們可以在項目中創建不同的module,創建的model的時候我們可以選擇創建一個不同的類型。

)

上圖是我們創建一個新的module的時候可以選擇的選項,通常我們選擇的是第一個,代表這個是一個可執行的項目。第二個代碼是一個libery庫,它與一般的項目不同,libery項目不能運行,libery項目最後會生成一個aar包,aar包與jar包類似。jar包是將編譯的class打包的壓縮包,aar包不止包括了class還有項目的資源生成的壓縮包。

上面我們學習了怎麼依賴一個aar包,下面我們來學習一下怎麼依賴一個library項目,常見的有兩種方法:

1 編寫代碼依賴

在需要依賴的模塊上面的build.gradle文件內,查找到dependencies{}模塊。添加以下代碼:

 compile project(':名稱')

在冒號後面輸入模塊的名稱

2 ide添加依賴

我們在項目上面點擊右鍵打開moduleseting

7.2.3 android{} 構建詳細配置

android 模塊的是該模塊的詳細設置,android app 的大部分的構建的內容都是在這個模塊內配置的。

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.2"
    defaultConfig {
        applicationId "com.it520.x5webview"
        minSdkVersion 15
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

上面是android studio爲我們創建的內容。

 compileSdkVersion 24

告訴 Gradle 用哪個 Android SDK 版本編譯你的應用,建議使用最新的SDK 進行編譯。在現有代碼上使用新的編譯檢查可以獲得很多好處,避免新棄用的 API ,並且爲使用新的 API 做好準備。

buildToolsVersion "24.0.2"

構建工具的版本,其中包括了打包工具aapt、dx等等。這個工具的目錄位於..your_sdk_path/build-tools/XX.XX.XX,注意這個工具和gradle版本有關係。

buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

buildTypes 用來設置應用的構建版本。默認的情況會創建兩個版本,1個版本是release(發佈版),1個版本是debug(開發版)。默認的情況下,只顯示了release的配置。我們一般都是在buildType中設置好相應的簽名文件、打包加密方式、冗餘資源等。

https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.BuildType.html#com.android.build.gradle.internal.dsl.BuildType:minifyEnabled

上面的文檔是buildType支持的所有的屬性

  • applicationIdSuffix 包名的後綴
  • versionNameSuffix 版本的後綴

上面兩個是我們在區分不同版本的時候增加的後綴名稱

  • signingConfig

上面這個配置是設置打包的簽名

  • shrinkResources
  • minifyEnabled

    上面的配置是去除冗餘資源

    defaultConfig {…}

    默認配置,這裏的代碼塊配置的在後面的各個構建變體(這裏理解成不同的版本)都能夠使用,這裏面設置的值,在不同的構建變體內還可以再修改成具體的值。

    上面的配置是IDE默認生成的。瞭解默認的腳本後,我們來看看詳細的配置。

7.2.3.1 簽名配置 SigningConfig

我們生成一個apk需要經過一個過程就是給這個app進行簽名的過程,這個過程我們要設置應用的簽名,有同學不明白,爲啥咱們調試的時候不需要?實際上默認提供了一個調試的簽名文件.在mac系統的位置在~/.android
在windows系統的位置在(C:\Documents and Settings[User Name].android)(C:\Users.android)這兩個位置中。我們可以看到一個文件叫做debug.keystore。這個文件就是我們的調試的簽名文件。

但是在正式包的時候,我們是不能使用調試的簽名文件的,我們需要使用對應的簽名文件。

首先我們要生成一個簽名文件,

生成完成後,我們要配置這個應用的簽名,配置簽名一般有以下幾個參數,詳細的參數請查看

https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.SigningConfig.html

上圖的4個值分別是 簽名的別名,簽名的密碼,簽名的位置,簽名的密碼

 signingConfigs {
      debug {
      }
        realse {
            keyAlias 'xmg'
            keyPassword '123456'
            storeFile file('/Users/kay/Desktop/release_key.jks')
            storePassword '123456'
       }
    }

定義了兩種類型的簽名配置。

設置好籤名配置,我們要給不同類型的構建設置簽名。

 buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.realse
        }
        debug{
            applicationIdSuffix ".debug"
            versionNameSuffix "huangkai"
        }
    }

在上面的代碼,我們給發佈版設置了簽名配置。

爲了驗證簽名配置的情況,我們切換到Terminal對話框,在對話框下輸入以下命令

./gradlew assembleRelease

除了可以使用配置的情況,我們也可以使用ide來配置達到一樣的效果。

7.2.3.2 定製版本 productFlavors

我們現在在中國開發要面對大量的渠道商(360市場、小米商店、應用寶),爲了統計不同的渠道商,我們需要提供不同的版本。這樣就會給開發者增加大量的開發任務,而且也出現代碼管理的問題。原來在eclipse的環境下,我們需要將代碼複製多份,再運行打包腳本,打包成不同的渠道包。但是現在使用gradle進行代碼管理,我們就不需要在做這個了,我們可以使用gradle來定製不同的版本,最後gradle會根據一定的規則把代碼或者資源進行融合,最後生成我們需要的apk。

在android{}模塊內部增加以下的代碼

  productFlavors{

      free{

      }
      pay{

      }
  }

我們定義了當前的應用有兩個版本,一個是free(免費),pay(收費)。我們預計要打兩個版本的包。這裏組合起來有四個版本。

  • freeDebug
  • freeRelease
  • payDebug
  • payRelease
定製版本的資源合併

gradle把不同版本的文件夾下的資源進行合併與替換,假設free與pay版本的區別在與某個資源文件。

我們在src文件中創建相關的資源文件夾。

接着我們在各個資源夾中創建一個string.xml資源文件,接着編寫以下內容

!!!! 注意,在各個資源文件夾下的內容要不一樣纔看得到區別。

接着我們編寫一個activity放置在main文件夾內,在activity的佈局顯示這個字符串title。

在左下方選擇相應的構建類型,比如說我們選擇的是payDebug

編寫代碼完成後,我們可以使用命令行來構建相應的版本。

 ./gradlew assembleFreeRelease

總結一下,同名的資源文件可以存在不同的版本文件內。

定製版本的java合併

上面的例子我們是通過一個資源來區分應用的版本,在實際的開發中,也存在這樣的情況,不同的版本可能有不一樣的業務邏輯,所以我們可能需要在不同的版本里面處理java代碼。

首先我們還是在之前的項目結構上面進行開發,這裏有兩個版本,一個free,一個pay。

首先我們先選擇一個build variants,在這裏我們選擇payDebug。

選擇完成後,我們打開pay文件夾,我們需要創建一個Activity。我們知道java代碼再android studio下面默認是存放在java文件夾下的。所以我們需要創建一個Java文件夾。

同樣的步驟我們在free文件夾也操作一遍

我們發現了free 和 pay 的Java文件夾顏色不一樣,pay的變成了藍色,free還是普通的黃色。

我們嘗試新建一個class。

很明顯在free文件上面沒法新建類。爲什麼呢?

因爲我們之前選擇的payDebug,ide就只編譯了pay文件夾下面的Java類。如果我們選擇了freeDebug,情況就剛好相反。

我們在free 和 pay 下面創建了兩個同名的activity,並指派了不同的界面。分別運行後,發現每次運行只能選其中一種顯示。

接着我們在main文件夾下面創建一個類,Util。接着我們無論在free或者pay下面都無法創建同名的類了,均會提示我們重複創建類錯誤。

總結一下:

  • 1 main 文件夾下有A類,那個其他版本的文件夾內不能有同名的類A
  • 2 不同版本的相同的文件A類,運行的時候請選擇相應的build variants

上面的例子是我們使用productFlavors合併了java代碼。

7.2.3.3 定製版本組合 flavorDimensions

在項目中,我們可能會碰到這樣的需求,我們可能需要對某個版本提供特殊的功能,但是這個功能與當前的定製版本代碼差別不大,如果根據每個定製版本都再新建一個定製版本出來就優點複雜了。比如說我們根據上面的例子來說,當前的應用提供了兩個定製版本,一個是pay,一個是free。但是項目在測試的時候,測試組希望根據版本提供有log消息和沒有log消息的版本。根據之前的我們需要新建payLog,payNoLog,freeLog,freeNoLog等版本。看起來還行吧,但是如果不止兩個而是5個版本,pay,free,….free5,而且log和noLog的區別可能就是幾句代碼。那個這個項目的結構就太過複雜了。這個時候,我們就可以使用定製版本組合。

定製版本組合怎麼操作呢,我們根據需求將代碼分成不同的組,不同的組代表不同的功能,組和組可以互相組合,最終形成需要的版本。相對於productFlavors,flavorDimensions是productFlavors的補充選擇,可以讓我們版本定製更靈活。

以上面的例子來說:

我們可以將版本的需求分成兩個維度,一個是支付狀態,一個是輸出消息狀態。

 flavorDimensions "log","pay_status"

首先定義兩個維度。下面我們要指定版本屬於哪個維度。

productFlavors {

    withLog{
        dimension "log"
    }
    noLog{
        dimension "log"
    }

    free {
        dimension "pay_status"
    }
    pay {
        dimension "pay_status"
    }

}

最後gradle會自動組合版本

7.2.3.4 定製版本依賴

我們在上面的內容學習了依賴的寫法,但是之前我們學習依賴的時候,這個依賴的是對這個項目整體生效的。意思就是項目所有的版本都生效,但是在實際開發中,我們可能會碰到這樣的情況,比如說我們開發一個應用,這個應用分成收費版本和免費版本。收費版本不需要顯示廣告。免費版本因爲沒有付費,需要顯示廣告。在這裏我們需要對我們的定製版本的依賴做細化的區分。原來在eclipse的時候,我們只能通過複製多一份代碼來進行實現。現在我們可以同過gradle實現。

 free {
        dimension "pay_status"

        dependencies {
            freeCompile 'com.bm.photoview:library:1.4.1'
        }
    }

在上面的代碼我們在版本定製內部添加了一個xxxxCompile的標籤,這個意思就是告訴gradle是什麼版本的依賴。xxxx是這個版本的名稱。

7.2.3.5 packagingOptions 打包選項

我們可以使用這個參數來告訴Gradle什麼文件打包到apk內,什麼文件不打包,重複文件如何處理等。

  • pickFirst 路徑,如果文件匹配這個路徑,只有第一個文件打包進apk
  • Merge 合併兩個文件進入apk,第二個文件會在第一個文件後
  • Exclude 不打包的文件的路徑

    packagingOptions {
    //以下文件不加入apk裏
    exclude ‘LICENSE.txt’
    }

未完待續……

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章