buildTypes——安卓gradle

目錄
1、前言
2、buildTypes
3、buildType
一、buildTypes存在形式
二、buildTypes 中屬性的意義
三、buildTypes 中方法的意義
4、寫在最後
html

1、前言

上一篇博客 分享了defaultConfig 中可配置參數的含義,今天咱們來分享另外一個咱們也很熟悉的 buildTypesjava

2、buildTypes

buildTypes 也是存在於每一個應用級模塊中的 android 下的,即以下所示,是每次構建完項目以後自動生成的結構。android

android {
    buildTypes{
    	release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}
複製代碼

buildTypes 能夠配置咱們須要的構建類型,例如咱們經常使用到的 「測試類型」 和 「本地類型」,則可使用以下配置git

buildTypes{
    // 發佈類型
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
    // 測試類型,給測試人員
    debug {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
    // 本地類型,和後端聯調使用
    local {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}
複製代碼

增長完這些配置後,咱們能夠在 android studio 看到多了 「debug」 和 「local」 兩個能夠構建的類型,在 「點擊運行」 時,便會使用咱們所選擇的構建類型。假設此時選擇的是 「debug」 類型,咱們此時運行代碼,則是 debug 下的配置參數。 github

固然運行編譯成 apk 時,也不例外,各自使用的也是各自類型的配置。

而這裏所說的 「release」,「debug」,「local」,三個構建類型其實即是三個 buildTypebuildType 所能配置的參數即是咱們今天要來捋清楚的。windows

3、buildType

buildType 官方文檔傳送門後端

一、buildType存在形式

從上一篇博客咱們知道,每一個配置最終會被映射爲一個類,或是一個屬性、或一個方法。buildType 也不例外,他會被映射爲 com.android.build.gradle.internal.dsl.BuildType,繼承結構以下android-studio

咱們從新看一下 DefaultConfig 的繼承結構,能夠看到都會繼承到 BaseConfigImpl 類,說明二者會有必定的交集。這也說明了爲何咱們看 gradle 文件時,總感受一個配置參數哪裏都能出現的狀況(後面會進行更多的比較,來解除咱們這種疑惑)瀏覽器

二、buildType 中屬性的意義

咱們先來一個約定,避免使用的代碼過於冗長。bash

buildTypes{
    debug {
	// 咱們下面的 「使用方法」 代碼都是基於這一塊,除非特殊說明。
    }
}
複製代碼

2.1 applicationIdSuffix

  • 類型:String
  • 描述:會追加在 applicationId 字符串的後面,造成最終的包名
  • 值得一提:在 defaultConfig 中也有這個屬性,但通常不會使用。而會在 buildTypes 中使用,這樣可讓包名不一樣,同時安裝多個類型的應用。例如咱們上面所提到的 release包、debug包、local包,均可以同時存在而不會覆蓋,方便調試。
  • 使用方法:
debug {
    applicationIdSuffix '.debug'
}
複製代碼

2.2 consumerProguardFiles

  • 類型:List< File >
  • 描述:這個屬性只做用於咱們建立的 library 中,包括咱們以aar形式導入的 library ,或是直接建立的 library。它的做用是,負責該 library 被進行編譯時的混淆規則,咱們在 主App 的模塊下則能夠不用再管理各個 library 的混淆規則,會直接使用各個 library 的混淆規則文件。
  • 值得一提:這個屬性 和 proguardFiles 的區別在於,consumerProguardFiles 會被 主App模塊 做爲混淆文件使用導入,而 proguardFiles 則不會。
  • 使用方法:
debug {
    consumerProguardFiles 'consumer-rules.pro'
    ......省略其餘配置
}

// 由於該屬性是一個 List<File> 類型,若是須要多個文件配置,則以下所示
debug {
    consumerProguardFiles 'consumer-rules.pro','zincPower-rules.pro'
    ......省略其餘配置
}
複製代碼

2.3 crunchPngs

  • 類型:boolean
  • 描述:是否對 PNG 圖片進行壓縮處理。設置爲true時,會對未進行最佳壓縮的PNG資源進行壓縮,但也會增長構建時間。
  • 值得一提:默認狀況下,release 類型是開啓的,debug 類型則爲關閉。
  • 使用方法:
debug {
    crunchPngs false
    ......省略其餘配置
}
複製代碼

2.4 debuggable

  • 類型:boolean
  • 描述:是否能夠對應用進行調試。
  • 值得一提:release 的構建類型默認爲不可調試,即爲false。而 debug 默認爲true,既能夠調試。所謂的 沒法調試 即下圖的 「蟲子」 標記沒法讓應用啓動,而正常的運行是能夠的。
  • 使用方法:
debug {
    debuggable true
}
複製代碼

2.5 javaCompileOptions

  • 類型:JavaCompileOptions
  • 描述:配置編譯時 java 的一些參數,例如咱們使用 annotationProcessor 時所須要的參數。
  • 使用方法:
debug {
    javaCompileOptions {
        annotationProcessorOptions{
    		arguments = []
    		classNames ''
    		....
    	}
    }
    ......省略其餘配置
}
複製代碼

JavaCompileOptions 能夠配置的具體參數,請進傳送門

2.6 jniDebuggable

  • 類型:boolean
  • 描述:是否能夠對應用的 native 代碼進行調試
  • 值得一提:release 的構建類型默認爲不可調試 native 代碼,即爲false。而 debug 默認爲true,既能夠調試 native 代碼。沒法對 native 代碼調試,指的是即便在native方法打了斷點,代碼也不會被 「停住」。
  • 使用方法:
debug {
    jniDebuggable true
}
複製代碼

2.7 manifestPlaceholders

  • 類型:Map<String, Object>
  • 描述:配置能夠在 AndroidManifest.xml 中使用的參數。
  • 使用方法: 這裏想配置咱們應用的 logo 爲測試版本的logo,方便測試人員區分不一樣類型的包,則能夠在 gradle 中使用下面這段
debug {
    manifestPlaceholders = [APP_LOGO_ICON: "@mipmap/ic_logo"]
}
複製代碼

而後在 AndroidManifest.xml 中使用,使用 ${你配置的變量名}

// 在 application 中使用替換,還須要多添加 tools:replace 這一標籤,將咱們須要替換的名稱寫上,例如這裏的 android:icon
<application android:allowBackup="true" android:icon="${APP_LOGO_ICON}" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" tools:replace="android:icon">
......
複製代碼

2.8 minifyEnabled

  • 類型:boolean
  • 描述:是否開啓混淆,代碼優化。true開始,false則關閉。
  • 使用方法:
debug {
    minifyEnabled true
}
複製代碼

2.9 proguardFiles

  • 類型:List< File >
  • 描述:配置混淆規則文件,只有 minifyEnabled 設置爲 true 的時候會使用這個參數,文件中須要申明哪些文件不被優化和混淆。
  • 值得一提:由於被混淆後端代碼,類名和方法名都會有所變化,因此進行反射會失敗,這是咱們就須要進行申明他們不被混淆。(這裏只是舉了使用這個參數的一個場景,若是應用原本是正常的,開了混淆後,出現了莫名奇妙的bug,那就思考下是否由於混淆致使了這一bug
  • 使用方法:
debug {
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
複製代碼

2.10 multiDexEnabled

64K 引用限制問題官方文檔 傳送門

  • 類型:Boolean
  • 描述:是否開啓分包。由於安卓中方法索引值爲兩個字節,四位十六進制的一個數值,即[0, 0xffff],因此最大方法數爲65536個。一旦超出了,就須要進行分包,因此咱們就須要開啓這個參數。
  • 使用方法:
android{
    buildTypes {
    	debug {
    		multiDexEnabled true
    		...
    	}
    }
}

// 添加依賴
dependencies {
    // 若是使用的爲 AndroidX,則使用下面這個導入
    // implementation 'androidx.multidex:multidex:2.0.1'
    // 若是不使用 AndroidX,則使用下面這段
    compile 'com.android.support:multidex:1.0.3'
}
複製代碼

有兩種開啓 MultiDex 方法:

// 第一種:讓你應用的 Application 繼承 MultiDexApplication。
public class MyApplication extends MultiDexApplication {

}

// 第二種:重寫應用的 Application 方法 attachBaseContext
public class MyApplication extends Application {

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }
}
複製代碼

最後別忘了在 AndroidManifest.xml 中使用咱們在上面的 Application。

2.11 multiDexKeepFile

  • 類型:File
  • 描述:將咱們須要的類打包進主包,即 classs.dex。咱們在第 2.10 小點,分享到使用了多包處理,有時咱們須要將一些主要的類打包進主包,則可使用該屬性。
  • 使用方法:
debug {
    multiDexKeepFile file('multidex-config.txt')
    ...
}
複製代碼

multidex-config.txt 中的書寫則以下,每個文件則爲一行

com/example/MyClass.class
com/example/TestClass.class
複製代碼

2.12 multiDexKeepProguard

  • 類型:File
  • 描述:將咱們須要的類打包進主包,和第 2.11 點的功能相同,區別在於寫法。
  • 使用方法:
debug {
    multiDexKeepFile file('multidex-config.pro')
    ...
}
複製代碼

multidex-config.pro 中的寫法以下

// 將會保留全部的在com.example package的類
-keep class com.example.** { *; }
複製代碼

2.13 name

  • 類型:String
  • 描述:構建類型的名字。
  • 使用方法:
// debug 則會被賦值至 name 屬性,並且 name 是final 類型,沒法在改動。
debug{
    ...
}
複製代碼

2.14 pseudoLocalesEnabled

  • 類型:boolean
  • 描述:這個屬性用於開啓僞語言,用於發現UI中潛在的可本地化問題。
  • 使用方法:

第一步:咱們在配置中開啓該屬性

debug{
    pseudoLocalesEnabled true
}
複製代碼

第二步:安裝咱們的應用 第三步:打開設置 -> 系統 -> 語言和輸入法 -> 語言 -> 添加語言

會在 「添加語言」 頁面中看到以下圖的選項,選擇圖中紅色框的內容,各自的不一樣在圖中也有標明,咱們往下走看看具體不一樣的表現是什麼。

小盆友的測試機是 榮耀8,不一樣機子會有些許不一樣

選擇以後,選擇不一樣的語言會有不一樣效果,如圖所示 (1)左邊爲未開啓時的樣子; (2)中間爲選擇了Pseudo locale(至關於en-XA); (3)右邊爲選擇了Bidirection test locale(至關於en-XB);

2.15 renderscriptDebuggable

  • 類型:boolean
  • 描述:是否能夠對 renderscript 代碼進行調試
  • 使用方法:
debug {
    renderscriptDebuggable true
}
複製代碼

2.16 renderscriptOptimLevel

  • 類型:int
  • 描述:設置渲染腳本等級
  • 使用方法:
debug {
    renderscriptOptimLevel 3
}
複製代碼

2.17 shrinkResources

shrinkResources 官方使用手冊 傳送門

  • 類型:boolean
  • 描述:是否壓縮資源,若是開啓,gradle在編譯時幫咱們把沒有使用的資源給移除。
  • 值得一提:shrinkResources 的開啓須要 minifyEnabled 也爲開啓狀態,不然沒法運行。
  • 使用方法:
debug {
    shrinkResources false
}
複製代碼

開啓後編譯完會看到以下日誌

2.18 signingConfig

  • 類型:SigningConfig

SigningConfig 的可配置參數 傳送門

  • 描述:配置簽名配置。apk包能被安裝是須要被簽名的,咱們直接運行的時候,是使用了系統默認的簽名證書,當咱們要發佈release包時,則須要使用屬於我的或企業的簽名。
  • 使用方法:
buildTypes {
    release {
        signingConfig {
    	    // 不建議將簽名證書的信息寫在這裏,而應該是寫在 properties 文件中,將其引入使用
            config {
                keyAlias keystoreProperties['keyAlias']
                keyPassword keystoreProperties['keyPassword']
                storeFile file(keystoreProperties['storeFile'])
                storePassword keystoreProperties['storePassword']
            }
        }
        ...
    }
}
複製代碼

2.19 testCoverageEnabled

  • 類型:boolean
  • 描述:測試覆蓋率,能夠獲取測試覆蓋率的報告
  • 值得一提:記得將 minifyEnabled 置爲 false,不然報告也會是以混淆後的類名出現。
  • 使用方法:

第一步:在 build.gradle 中開啓 testCoverageEnabled

debug {
    testCoverageEnabled true
}
複製代碼

第二步:鏈接上一臺可用設備,由於咱們執行的測試代碼是要基於設備的,若是不鏈接,測試階段會報以下錯

第三步:在 android studio 的 終端(即 Terminal)中輸入下面這行命令,查看全部可運行任務。

小盆友是 mac 環境,因此 ./gradlew 開頭。windows 的環境則直接使用 gradlew 便可。

./gradlew app:tasks
複製代碼

輸入運行後,能夠看到圖中高亮部分的可運行task。

咱們以駝峯式(即第一個字母加上後面每一個單詞的首字母且以大寫的形式)將其運行,代碼以下

// create + 你的構建類型名(這裏爲debug) + CoverReport 
./gradlew app:cDCR
複製代碼

運行完以後,就是查看測試報告的階段了。咱們進入coverage目錄,具體路徑以下圖所示。

在這裏插入圖片描述
最後用瀏覽器打開 index.html 文件,就能夠看報告啦,以下圖所示,由於小盆友的這個項目沒有寫測試代碼,因此覆蓋率爲0。
在這裏插入圖片描述

2.20 useProguard

  • 類型:boolean
  • 描述:是否開啓老是開啓 proguard
  • 使用方法:
debug {
    useProguard true
}
複製代碼

2.21 versionNameSuffix

  • 類型:String
  • 描述:追加在 versionName 以後
  • 使用方法:
debug {
    // 若是 versionName "1.0.0" ,則最終的版本名爲 1.0.0.test
    versionNameSuffix ".test"
    .....
}
複製代碼

2.22 zipAlignEnabled

  • 類型:boolean
  • 描述:是否開啓zipAlign。會對應用程序進行字節對齊,對齊後會減小了運行應用程序時消耗的內存。
  • 使用方法:
debug {
    zipAlignEnabled true
    .....
}
複製代碼

2.23 matchingFallbacks

  • 類型:List< String >
  • 描述:用於處理 本地依賴library 間 BuildType 的衝突。

matchingFallbacks 還能夠處理 維度風味的 問題,但咱們這裏先不討論,後續的文章會介紹。

  • 使用方法:

一個東西的出現是爲了處理至少一個問題,因此咱們須要先了解下這個問題是怎麼產生的。

如上圖所示,咱們的 主Module(通常是App),存在了三個構建類型,即咱們一開始所提的 「release」、「debug」、「local」 三種。

此時咱們在項目添加了一個 module 名字爲 library,並依賴進咱們的app中。當咱們構建 「release」、「debug」 兩種版本時,都不會有任何問題,由於 library 默認也提供了 「release」、「debug」 兩種構建版本。

可是當咱們使用 「local」 時,便會出問題了,由於此時 gradle 的腳本也會默認選擇 「library」 的 「local」,但 「library」 中並無。會報下面這樣的錯誤

ERROR: Unable to resolve dependency for ':app@local/compileClasspath': Could not resolve project :lib:library.
Show Details
Affected Modules: app
複製代碼

此時就須要幫 「local」 從 「library」 中選擇一個可用的構建類型,則是經過 matchingFallbacks 進行設置。

鋪墊了這麼多,接下來就是怎麼使用了,在 app 的 build.gradle 中添加以下代碼便可。

local{
    matchingFallbacks = ['zinc','release']
    ...
}
複製代碼

值得一提的是,咱們能夠配置多個,gradle在編譯的時候,會按照從頭開始匹配的原則,例如這裏的 「zinc」 會匹配不到,則匹配 「release」,由於 「release」 匹配到了,則會進行使用,中斷後面的匹配。

三、buildTypes 中方法的意義

3.1 buildConfigField(type, name, value)

  • 描述:咱們能夠在 BuildConfig 類中添加值,最終會在 BuildConfig 中添加以下一行代碼。
// 值的注意的是 value 的值是原樣放置,咱們經過使用方法一節來了解
<type> <name> = <value>
複製代碼
  • 使用方法:
debug {
    // 能夠經過 BuildConfig 進行獲取
    buildConfigField('String', 'name', '"zinc"')
    buildConfigField('int', 'age', '26')
    .....
}
複製代碼

最終會生成以下圖的配置,咱們能夠經過下面代碼進行獲取

String name = BuildConfig.name;
int age = BuildConfig.age;
複製代碼

值的一提的是,咱們設置 String 類型的參數時,須要加上 "" 雙引號(如例子中的name屬性)。切記!

3.2 consumerProguardFile(proguardFile)

  • 描述:和上面分享的 2.2 小點的屬性 consumerProguardFiles 是同樣的做用。只是這裏只能設置一個 混淆文件。
  • 使用方法:
debug {
    consumerProguardFile('consumer-rules.pro')
}
複製代碼

3.3 consumerProguardFiles(proguardFiles)

  • 描述:和上面分享的 2.2 小點的屬性 consumerProguardFiles 是同樣的做用,並且也是多個混淆文件。
  • 使用方法:
debug {
    consumerProguardFile('consumer-rules.pro', 'zincPower-rules.pro',.....)
}
複製代碼

3.4 externalNativeBuild(action)

  • 類型:ExternalNativeBuildOptions
  • 描述:這裏咱們設置 ndk 編譯過程的一些參數。分爲 cmake 和 ndkBuild 兩個參數。
  • 使用方法:
debug {
    externalNativeBuild {
        ndkBuild {
            // Passes an optional argument to ndk-build.
            arguments "NDK_MODULE_PATH+=../../third_party/modules"
        }
        // For ndk-build, instead use the ndkBuild block.
        cmake {
             // Passes optional arguments to CMake.
             arguments "-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang"
        
             // Sets a flag to enable format macro constants for the C compiler.
             cFlags "-D__STDC_FORMAT_MACROS"
        
             // Sets optional flags for the C++ compiler.
             cppFlags "-fexceptions", "-frtti"
        
             // Specifies the library and executable targets from your CMake project
             // that Gradle should build.
             targets "libexample-one", "my-executible-demo"
         }
    }
}
複製代碼

cmake 具體參數 傳送門
ndkBuild 具體參數 傳送門

3.5 initWith(that)

  • 描述:會拷貝給定的 buildType(即參數的值)
  • 使用方法:
buildTypes {
    debug{
    }
    local{
    	// 會拷貝 debug 的配置
        initWith debug{
          	// 在這裏進行咱們本身的配置
        }
    }
}
複製代碼

3.6 proguardFile(proguardFile)

  • 描述:添加混淆文件,和 2.9小點 的功能一致,只是傳入的是一個文件,這裏就再也不贅述
  • 使用方法:
debug {
    proguardFile 'proguard-rules.pro'
}
複製代碼

3.7 proguardFiles(files)

  • 描述:添加混淆文件,和 2.9小點 的功能一致,這裏就再也不贅述
  • 使用方法:
debug {
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
複製代碼

3.8 setProguardFiles(proguardFileIterable)

  • 描述:添加混淆文件,和 2.9小點 的功能一致,只是寫法稍微不一樣,這裏就再也不贅述
  • 使用方法:
debug {
    proguardFiles = [getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro']
}
複製代碼

3.9 resValue(type, name, value)

  • 描述:添加 value 資源
  • 使用用法:
debug {
    // 添加至 res/value,經過 R.string.age 獲取
    resValue('string', 'age', '12 years old')
}
複製代碼

4、寫在最後

Gradle 的配置文件看起來好像挺亂,實際上是由於咱們沒有進行總體的梳理。不少配置其實不是沒有用,而是咱們沒有對他有一個總體的瞭解,正所謂 「無知最可怕」

若是喜歡的話請給我一個贊,並關注我吧。文章中若有寫的不妥的地方,請評論區或加我微信與我討論吧,共同進步。

歡迎加我微信,進行更多的交流

若是以爲文章有很大的幫助,快來讚揚一次吧😄
相關文章
相關標籤/搜索