第八章 自定義Android Gradle工程

Android Gradle為我們提供了大量的DSL,我們使用這些DSL定義配置我們的工程以滿足我們項目中不同的需求。這些DSL有很多,在上一章演示Android Gradle工程示例的時候,我們已經(jīng)大概介紹了compileSdkVersion、buildToolsVersion以及defaultConfig等,這一章我們再詳細(xì)介紹一些常用的DSL配置,這些配有有簽名信息、構(gòu)建類型、代碼混淆、zipAlign對齊壓縮等。

8.1 defaultConfig默認(rèn)配置

defaultConfig是android對象中的一個配置塊,負(fù)責(zé)定義所有的默認(rèn)配置,它是一個ProductFlavor,如果一個ProductFlavor沒有被特殊定義配置的話,默認(rèn)就會使用defaultConfig{}塊指定的配置,比如包名、版本號、版本名稱等。

一個基本上的defaultConfig配置如下:

以上示例配置了Android 開發(fā)的基本信息,可以滿足一個基本的Android App開發(fā),下面我們對它的一些配置進(jìn)行一個詳細(xì)的說明。

8.1.1 applicationId

applicationId是ProductFlavor的一個屬性,用于指定生成的App的包名,默認(rèn)情況下是null,這時候在構(gòu)建的時候,會從我們的AndroidManifest.xml文件中讀取,也就是我們在AndroidManifest.xml文件中配置的manifest標(biāo)簽的package屬性值。

8.1.2 minSdkVersion

minSdkVersion是ProductFlavor的一個方法,對應(yīng)的方法原型是

    public void minSdkVersion(int minSdkVersion) {
        this.setMinSdkVersion(minSdkVersion);
    }

它可以指定我們的App最低支持的Android 操作系統(tǒng)版本,其對應(yīng)的值是Android SDK的API LEVEL,根據(jù)這里的方法原型,它接受的值是一個整數(shù),除此之外,它還有以下兩種方法原型定義:

根據(jù)我們前面講的Gradle知識,發(fā)現(xiàn)minSdkVersion也是一個屬性,它也可以接受一個字符串作為它的值,在這里明確一下,這個字符串不是我們SDK API LEVEL的字符串形式,而是Code Name,也就是我們的每個Android SDK或者說是Android OS的代號。就是我們新聞上經(jīng)常見到的什么‘冰激凌三明治’什么的。這里給出一個列表,讓大家一目了然。

8.1.3 targetSdkVersion

這個用于配置我們基于哪個Android SDK開發(fā),它的可選值和minSdkVersion一樣,沒有配置的時候也會從AndroidManifest.xml文件中讀取,參考minSdkVersion的介紹,這里就不多做介紹了。

8.1.4 versionCode

它也是ProductFlavor的一個屬性,用于配置Android App的內(nèi)部版本號,是一個整數(shù)值,通常用于版本的升級。沒有配置的時候從AndroidManifest.xml文件中讀取,建議配置。其方法原型是

public class DefaultProductFlavor extends BaseConfigImpl implements ProductFlavor {
    ...
    public ProductFlavor setVersionCode(Integer versionCode) {
        this.mVersionCode = versionCode;
        return this;
    }

    public Integer getVersionCode() {
        return this.mVersionCode;
    }
    ...
}
8.1.5 versionName

versionName和versionCode類似,也是ProductFlavor一個屬性,用于配置Android App的版本名稱,比如V1.0.0等等,主要顯示用,讓用戶或者市場知道我們的Android App版本,它和versionCode一個是外部用,一個是內(nèi)部使用,一起配合完成Android App的版本控制,其方法原型是

    public ProductFlavor setVersionName(String versionName) {
        this.mVersionName = versionName;
        return this;
    }

    public String getVersionName() {
        return this.mVersionName;
    }
8.1.6 testApplicationId

用于配置測試App的包名,默認(rèn)情況下是applicationId + “.test”,一般情況下默認(rèn)即可,它也是ProductFlavor的一個屬性,方法原型是

    public ProductFlavor setTestApplicationId(String applicationId) {
        this.mTestApplicationId = applicationId;
        return this;
    }

    public String getTestApplicationId() {
        return this.mTestApplicationId;
    }
8.1.7 testInstrumentationRunner

用于配置單元測試時使用的Runner,默認(rèn)使用的是android.test.InstrumentationTestRunner,如果你想使用自己自定義的Runner,修改這個值即可,它也是一個屬性,其方法原型是

    public ProductFlavor setTestInstrumentationRunner(String testInstrumentationRunner) {
        this.mTestInstrumentationRunner = testInstrumentationRunner;
        return this;
    }

    public String getTestInstrumentationRunner() {
        return this.mTestInstrumentationRunner;
    }
8.1.8 signingConfig

配置默認(rèn)的簽名信息,用對生成的App簽名,它是一個SigningConfig,也是ProductFlavor的一個屬性,可以直接對其進(jìn)行配置,其方法原型是

    public SigningConfig getSigningConfig() {
        return this.mSigningConfig;
    }

    public ProductFlavor setSigningConfig(SigningConfig signingConfig) {
        this.mSigningConfig = signingConfig;
        return this;
    }
8.1.9 proguardFile

用于配置App ProGuard混淆所使用的ProGuard配置文件,它是ProductFlavor的一個方法,接受一個文件作為參數(shù)。其方法原型為

    public void proguardFile(Object proguardFile) {
        this.getProguardFiles().add(this.project.file(proguardFile));
    }

可以看到它可以被調(diào)用多次,調(diào)用一次添加一個,其參數(shù)被project.file方法轉(zhuǎn)換為一個文件對象。其具體使用我們在稍后進(jìn)行介紹。

8.1.10 proguardFiles

這個也是配置ProGuard配置文件,只不過它可以同時接受多個配置文件,因為它的參數(shù)是一個可變類型的參數(shù)。

    public void proguardFiles(Object... files) {
        Object[] var2 = files;
        int var3 = files.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            Object file = var2[var4];
            this.proguardFile(file);
        }
    }

從方法實現(xiàn)我們可以看到,同時可以添加多個ProGuard配置,在實際情況下中可以選擇不同的配置方式。

8.2 配置簽名信息

一個App只有被簽名之后才能被發(fā)布、安裝、使用,簽名是保護(hù)App的方式,標(biāo)記該App的唯一性,如果App被惡意篡改,簽名就不一樣了,就無法升級安裝,一定程度上也保護(hù)了我們的App。

要對App進(jìn)行簽名,你先得有一個簽名證書文件,這個文件被開發(fā)者持有,我們這里假設(shè)你已經(jīng)有生成的證書,不對證書的生成進(jìn)行介紹了。
一般我們的App有debug和release兩種模式(下面會將構(gòu)建類型),在我們開發(fā)調(diào)試的時候使用的是debug模式,發(fā)布的時候使用release模式;我們可以針對這兩種模式采用不同的簽名方式,一般debug模式的時候,Android SDK已經(jīng)為我們提供了一個默認(rèn)的debug簽名證書,我們可以直接使用,但是發(fā)布的時候,release模式構(gòu)建時,我們要配置使用自己生成的簽名證書。

對于簽名信息的配置,Android Gradle為我們提供了非常簡便的方式,讓我們可以非常容易的配置一個簽名信息以供調(diào)用。

Android Gradle為我們提供了signingConfigs{}配置塊便于我們生成多個簽名配置信息。signingConfigs是android的一個方法,它接受一個域?qū)ο笞鳛槠鋮?shù),前面我們講過的,其類型是NamedDomainObjectContainer<SigningConfig>,這樣我們在signingConfigs{}塊中定義的都是一個SigningConfig。一個SigningConfig就是一個簽名配置,其可配置的元素如下:

  • storeFile 簽名證書文件
  • storePassword 簽名證書文件的密碼
  • storeType 簽名證書的類型
  • keyAlias 簽名證書中密鑰別名
  • keyPassword 簽名證書中該密鑰的密碼

例子中我們定義配置了一個名為release的簽名配置,除此之外,我們還可以配置多個不同的簽名前置,比如我們添加一個debug的配置。

默認(rèn)情況下,debug模式的簽名已經(jīng)被配置好了,使用的就是Android SDK自動生成的debug證書,它一般位于$HOME/.android/debug.keystore,其Key和密碼都是已知的,一般情況下我們不需要單獨配置debug模式的簽名信息。

現(xiàn)在我們配置好了兩個簽名信息,但是他們還沒有被使用,現(xiàn)在只是生成了兩個SigningConfig的實例,一個變量名為release,一個為debug,如果要使用他們我們只需引用他們即可,比如在8.1.8節(jié)中我們講配置默認(rèn)的簽名信息,現(xiàn)在我們就可以引用debug的配置信息使用。

可以看到我們在defaultConfig中對簽名配置的應(yīng)用這里的signingConfigs是android對象實例的一個屬性,對應(yīng)是getSigningConfigs(),debug就是我們上面創(chuàng)建的簽名配置名稱。

除了上面的默認(rèn)簽名配置之外,我們也可以對構(gòu)建的類型分別配置簽名信息,比如我上面說的debug模式配置debug的簽名信息,release默認(rèn)配置release的簽名信息。

如果你還有其他類型,想為其配置單獨的簽名,也可以這么做,比如付費版的VIP,單獨進(jìn)行簽名配置、特別的渠道包單獨配置等等。

8.3 構(gòu)建的應(yīng)用類型

關(guān)于構(gòu)建類型,前面的章節(jié)我們已經(jīng)用到了一些,在Android Gradle工程中,Android Gradle已經(jīng)幫我們內(nèi)置了debug和release兩個構(gòu)建類型,他們兩種模式的只要差別在于能否在設(shè)備上調(diào)試以及簽名不一樣,其他代碼和文件資源都是一樣的,一般情況下也夠用了。

如果想增加新的構(gòu)建類型,在buildTypes{}代碼塊中繼續(xù)添加元素就好了。buildTypes和signingConfigs一樣,也是android的一個方法,接受的參數(shù)也是一個域?qū)ο驨amedDomainObjectContainer<BuildType>,添加的每一個都是BuildType類型,所以你可以使用BuildType提供的方法和屬性對現(xiàn)有的BuildType配置,這里列舉一些常用的配置。

8.3.1 applicationIdSuffix

applicationIdSuffix是BuildType的一個屬性,用于配置基于默認(rèn)applicationId的后綴,比如默認(rèn)defaultConfig中配置的applicationId為org.flysnow.app.example82,我們在debug的BuildType中指定applicationIdSuffix為.debug,那么構(gòu)建生成的debug apk的包名就是org.flysnow.app.example82.debug。其方法原型為

    public BaseConfigImpl setApplicationIdSuffix(String applicationIdSuffix) {
        this.mApplicationIdSuffix = applicationIdSuffix;
        return this;
    }
8.3.2 debuggable

debuggable也是BuildType的一個屬性,用于配置是否生成一個可供調(diào)試的Apk。其值可以為true或者false。其方法原型為

    public BuildType setDebuggable(boolean debuggable) {
        this.mDebuggable = debuggable;
        return this;
    }
8.3.3 jniDebuggable

jniDebuggable和debuggable類似,也是BuildType的一個屬性,用于配置是否生成一個可供調(diào)試Jni(C/C++)代碼的Apk。接受boolean類型的值

8.3.4 minifyEnabled

也是BuildType的一個屬性,用于配置該BuildType是否啟用Proguard混淆,接受一個boolean類型的值

8.3.5 multiDexEnabled

也是BuildType的一個屬性,用于配置該BuildType是否啟用自動拆分多個Dex的功能,一般用于代碼太多,超過了65535個方法的時候,進(jìn)行的拆分為多個Dex的處理,后面會詳細(xì)講使用。接受一個boolean類型的值

8.3.6 proguardFile

是BuildType的一個方法,用于配置Proguard混淆使用的配置文件,和前面講的defaultConfig中的proguardFile一樣

8.3.7 proguardFiles

是BuildType的一個方法,用于配置Proguard混淆使用的配置文件,該方法可以同時配置多個Proguard配置文件

8.3.8 shrinkResources

是BuildType的一個屬性,用于配置是否自動清理未使用的資源,默認(rèn)為false.
這是一個非常有用的功能,我們在后面的章節(jié)會詳細(xì)介紹。

8.3.9 signingConfig

配置該BuildType使用的簽名配置,前面已經(jīng)講過,可以參考8.2章節(jié)溫習(xí)一遍。

每一個BuildType都會生成一個SourceSet,默認(rèn)位置為src/<buildtypename>/,根據(jù)我們以前講的知識,一個SourceSet包含源代碼、資源文件等信息,在Android中就包含了我們的java源代碼,res資源文件以及AndroidManiftest文件等,所以針對不同的BuildType,我們可以單獨的為其指定Java源代碼,res資源等,只要把他們放到src/<buildtypename>/下相應(yīng)的位置即可,在構(gòu)建的時候,Android Gradle會優(yōu)先使用他們代替我們main下的相關(guān)文件。

另外需要注意,因為我們的每個BuildType都會生成一個SourceSet,所以新增的BuildType名字一個要注意,不能是main和androidTest,因為他們兩個已經(jīng)被系統(tǒng)占用,同事每個BuildType之間名稱不能相同。

除了會生成對應(yīng)的SourceSet外,每一個BuildType還會生成相應(yīng)的assemble<BuildTypeName>任務(wù),比如我們常用的assembleRelease和assembleDebug就是Android Gradle自動生成的兩個Task任務(wù),他們是release和debug這兩個BuildType自動創(chuàng)建生成的。執(zhí)行相應(yīng)的assemble<BuildTypeName>任務(wù),就能生成對應(yīng)BuildType的所有Apk。

8.4 使用混淆

代碼混淆是一個非常有用的功能,它不僅可能優(yōu)化我們的代碼,讓我們的Apk包變得更小,還可以混淆我們原來的代碼,讓反編譯的人不容易看明白我們業(yè)務(wù)邏輯,很難分析。一般情況下我們發(fā)布到市場的版本一定是要混淆的,也就是我們的release模式編譯的版本,但是我們自己調(diào)試的版本不用混淆,因為混淆后就無法斷點跟蹤調(diào)試了,也就是我們的debug模式。

要啟用混淆,我們把BuildType的屬性minifyEnabled的值設(shè)置為true即可。

現(xiàn)在我們啟用了混淆,但是Android Gradle還不知道按何種規(guī)則進(jìn)行混淆,不知道要保留哪些類不混淆,要做到這些就需要我們的Proguard配置文件了,現(xiàn)在我們?yōu)槲覀兊幕煜付ㄅ渲梦募?/p>

根據(jù)我們8.3小結(jié)講的知識,指定Proguard配置文件我們可以使用proguardFile方法,也可以使用proguardFiles方法,這個根據(jù)情況而定,看你是想指定一個還是想同時指定多個。

這里我們注意到,使用了一個getDefaultProguardFile方法,該方法是android實例的一個方法,全限定寫法可以這樣android.getDefaultProguardFile,它的作用是獲取我們Android SDK安裝目錄中,Android為我們提供的默認(rèn)Proguard混淆配置文件,路徑是Android SDK安裝目錄下的tools/proguard文件夾中,我們看下該方法的原型

從實現(xiàn)中看,我們只需傳遞一個文件名給這個方法,他就會返回tools/proguard目錄下的該文件的絕對路徑。

Android SDK默認(rèn)為我們提供了兩個Proguard配置文件,他們分別是proguard-android.txt和proguard-android-optimize.txt,一個是沒有優(yōu)化的,一個是優(yōu)化的,你可以根據(jù)情況自己選擇,當(dāng)然你也可以都不用,全部自己定義,自己定義的時候可以參考Proguard官方網(wǎng)站文檔,查看相關(guān)配置說明,網(wǎng)址為 http://proguard.sourceforge.net/ 。

除了在BuildType中啟用混淆和配置混淆外,我們也可以在defaultConfig中啟用和配置,還記得我們前面在8.1章節(jié)講的吧,因為這個是默認(rèn)配置,一般用的比較少。

我們還可以針對個別渠道,啟用和配置Proguard混淆,多渠道包是通過productFlavors配置的,productFlavors是一個NamedDomainObjectContainer<ProductFlavor>域?qū)ο?,其配置的渠道本質(zhì)上就是一個ProductFlavor,和defaultConfig是一樣的,所以每個渠道也可以單獨的啟用和配置Proguard混淆。

8.5 啟用zipalign優(yōu)化

zipalign是Android為我們提供的一個整理優(yōu)化Apk文件的工具,它能提供系統(tǒng)和應(yīng)用的運(yùn)行效率,更快的讀寫Apk中的資源,降低內(nèi)存的使用,所以對于我們要發(fā)布的App,在發(fā)布之前一定要使用zipalign進(jìn)行優(yōu)化

Android Gradle為我們提供了開啟zipalign優(yōu)化更簡便的方式,我們只需要配置開啟即可,剩下的操作,比如調(diào)用SDK目錄下的zipalign工具進(jìn)行處理等,Android Gradle會幫我們搞定。要為我們的release模式開啟zipalign優(yōu)化的話,只需進(jìn)行如下配置即可。

zipAlignEnabled是BuildType的一個屬性,接受一個boolean類型的值.

8.6 小結(jié)

這一章對我們Android Gradle常用的DSL做了詳細(xì)的講解說明,并且盡可能對常用的屬性方法配置也進(jìn)行了詳細(xì)的說明,同時配有每個屬性和方法的源代碼實現(xiàn),讓大家對這些配置有個更深的認(rèn)識。大家可以靈活的使用這些DSL對自己的項目進(jìn)行自定義構(gòu)建,以滿足自己的項目需求。


本文屬自學(xué)歷程, 僅供參考
詳情請支持原書 Android Gradle權(quán)威指南

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,716評論 25 709
  • 這一章主要針對項目中可以用到的一些實用功能來介紹Android Gradle,比如如何隱藏我們的證書文件,降低風(fēng)險...
    acc8226閱讀 7,960評論 3 25
  • 1.介紹 如果你正在查閱build.gradle文件的所有可選項,請點擊這里進(jìn)行查閱:DSL參考 1.1新構(gòu)建系統(tǒng)...
    Chuckiefan閱讀 12,355評論 8 72
  • 轉(zhuǎn)載注明出處:http://www.itdecent.cn/p/5255b100930e 0. 前言 完全由個人翻...
    王三的貓阿德閱讀 2,730評論 0 4
  • 20170301,睡得很晚,起的很早。 5點,迷離楞登中調(diào)動全身的細(xì)胞離開充滿魔力的床,靜坐4分18秒,蹦下床,伸...
    皮爾巴拉流浪者閱讀 347評論 0 0

友情鏈接更多精彩內(nèi)容