主頁 > 移動端開發 > Android Gradle 常用配置

Android Gradle 常用配置

2020-09-22 19:21:53 移動端開發

Android Gradle 提供了大量的 DSL 給我們,以方便我們根據自己的需求定義相應的配置,

在這里記錄一些常用的配置,以方便使用的時候查詢,老話說 好記性不如爛筆頭,

關于 Android 專案的配置幾乎全部在 android{} 里了,我這里記錄的也全是 android 擴展里的配置,

最上面的兩個配置

//編譯的SDK 版本
compileSdkVersion 29
//構建工具版本
buildToolsVersion "29.0.2"

defaultConfig 默認配置

defaultConfig{} 是一個配置塊,負責定義所有的默認配置,

如果一個變體沒有定義自己的配置,就會默認使用 defaultConfig{} 里的配置,

例如 應用 ID ,版本號,版本名等,

//默認配置
defaultConfig {
    //應用程式ID,創建時的包名,可以更改,
    applicationId "com.skymxc.example"
    //最小支持的SDK 版本
    minSdkVersion 19
    //目標 SDK 版本
    targetSdkVersion 29
    //應用版本代碼,一般用于控制APP的升級,
    versionCode 1
    //應用版本名稱,用戶可以看到,
    versionName "1.0"

    //配置單元測驗使用的 runner
    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

如果是 library 專案,是沒有 applicatoinId 的,但是有一個 consumerProguardFiles 配置

defaultConfig {
    minSdkVersion 19
    targetSdkVersion 29
    versionCode 1
    versionName "1.0"

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    //配置庫自己的 混淆規則,打包時會被打包進 AAR 包里,在 使用這個庫的專案里會自動應用庫里的混淆規則,
    consumerProguardFiles 'consumer-rules.pro'
}

構建型別

構建型別是 Gradle 在構建和打包 APK 時使用的某些配置,通常是為開發生命周期的不同階段做配置,

例如 debug 構建型別 是在開發除錯階段使用的,Gradle 會使用 除錯密鑰庫為其簽名;
release 構建型別是正式發布打包階段使用的,會縮減 APK,對 APK 進行混淆處理并使用特定的加密密鑰庫,

Android studio 在創建專案時就會自動創建兩個構建型別:debug 和 release ,

雖然沒有把 debug 顯示在配置腳本上,但會有 debuggable true 配置它,

//構建型別
buildTypes {
    //發布型別
    release {
        //是否啟用混淆
        minifyEnabled false
        //proguard 規則檔案;
        //getDefaultProguardFile 是 Android 擴展的一個方法,可以獲取你的 Android SDK 目錄下默認的 proguard 組態檔,
        //在 android-sdk/tools/proguard/目錄下,檔案名就是傳入的 proguard-android-optimize.txt
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}

如果你有其他別的配置要在 debug 構建型別上配置,直接定義即可,

例如 我想讓 除錯版和發布版本都能在一個手機上安裝,就可以為 debug 構建型別 增加一個配置,更改它的應用ID

//構建型別
buildTypes {
    //正式發布階段使用
    release {
        //是否啟用混淆
        minifyEnabled false
        //proguard 規則檔案;
        //getDefaultProguardFile 是 Android 擴展的一個方法,可以獲取你的 Android SDK 目錄下默認的 proguard 組態檔,
        //在 android-sdk/tools/proguard/目錄下,檔案名就是傳入的 proguard-android-optimize.txt
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
    //除錯階段使用
    debug {
        applicationIdSuffix ".debug"
    }
}

如果你有其他需求是這兩個型別不能滿足的,也可以添加一個構建型別,自定義其中的配置,

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

        debug {
            applicationIdSuffix ".debug"
            debuggable true
        }

        staging {
            initWith debug
            manifestPlaceholders = [hostName:"internal.example.com"]
            applicationIdSuffix ".debugStaging"
        }
    }

關于構建型別可以使用的配置,我把常用的在這里列一下,方便以后查閱

  • applicationIdSuffix 基于默認 applicationId 追加后綴,(注意也要符合 applicationId 的定義規則) 接受 String 型別的值,
  • debuggable 是否生成一個可調式的 APK,接受 Boolean 型別的值,
  • jniDebuggable 是否生成一個可供除錯 Jni(C/C++) 代碼的 APK,接受 Boolean 型別的值,
  • minifyEnabled 是否進行代碼縮減、啟用 Proguard 混淆,接受 Boolean 型別的值,
  • proguardFiles 配置 Proguard 使用的規則檔案,可以接受多個檔案,
  • shrinkResources 是否清理未使用的資源,默認是 false ,
  • signingConfig 配置使用的簽名

更多更詳細的屬性和方法查看檔案吧,傳送門

產品變種

產品變種可以理解為應用的不同版本,例如,農村版和非農版,

可以自定義變種以使用不同的代碼和資源,同時共享和重復利用所有應用版本共用的部分,

產品變種是配置出來的,默認是沒有的,有需要則需要自己配置,

產品變種的配置和構建型別的差不多,

  1. 首先要添加一個產品維度,可以理解為一個分組,所有的變種都必須指定一個維度
//變種維度
flavorDimensions "domicile"
  1. 添加變種
//變種維度
flavorDimensions "domicile"
//產品變種
productFlavors{
    //農村 變種
    countryside {
        //指定所屬維度
        dimension "domicile"
        versionNameSuffix '-countryside'
    }
    //城市 變種
    city {
        dimension "domicile"
        versionNameSuffix '-city'
    }
}

defaultConfig{} 中的配置在變種里都可以用,他們兩個都是屬于 ProductFlavor 類

比如,想給不同變種設定不同的版本就可以像上面那樣設定,

如果沒有在變種中配置任何自定義屬性,將使用 defaultConfig 中的配置,

在添加產品變種并同步后, Gradle 就會生成很多任務,基本上都是基于 構建型別+產品變種的方式生成的,

比如 assembleCity、assembleRelease 、assembleCityRelease 等,

assemble 開頭的負責生成 APK,比如 assembleCity 運行之后就會生成 City 變種的 release 和 debug 包;

assembleRelease 運行之后就會生成所有變種的的 release 包;

而 assembleCityRelease 運行后只會生成 city 的 release 包,

除了 assemble 系列,還有 compile系列,install系列等等,可以通過命令 gradle tasks 查看,

除了生成任務之外,每個產品變種和構建型別還可以有自己的 源集、依賴,

這就意味著可以為每個變種和構建型別定義他們自己的資源、代碼以及依賴的第三方庫,

關于怎么為構建型別,產品變種定義自己的資源、代碼和依賴下面和變體一起看,

產品變種也是多渠道構建的基礎,通常多渠道構建就是配置多個變種,

構建變體

構建變體是 Gradle 使用一組特定規則將構建型別和產品變種中配置的設定、代碼和資源組合在一起的結果,

它是構建型別和產品變種的交叉產物,也是 Gradle 用來構建應用的配置,

例如,“city” 產品變種可以定義不同的功能和設備要求(如自定義源代碼、資源和最低 API 級別),而 “debug” 構建型別則會應用不同的構建和打包設定(如除錯選項和簽名密鑰),

生成的構建變體是應用的“cityDebug”版本,它由“city”產品變種、“debug”構建型別和 main/ 源代碼集中包含的配置和資源組合而成,

你無法直接創建和更改變體,只能通過更改構建型別和產品變種的方式創建和配置變體,

在腳本中添加產品變種后,點擊 “Sync Now” ,

同步完成后,Gradle 會根據構建型別和產品變種自動創建構建變體,并按照 <product-flavor><Build-Type> 為其命名,

例如,如果創建了“countryside”和“city”產品變種,并保留了默認的“debug”和“release”構建型別,則 Gradle 會創建以下構建變體:

  • cityDebug
  • cityRelease
  • countrysideDebug
  • countrysideRelease

變體同步出來之后,你可以任意選擇要構建運行的變體,只需要在 Android studio 的 Build Variant 視窗選擇即可:
buildVariants

源代碼集

想知道怎么為構建變體配置特定資源,就需要先了解源代碼集的概念,

源代碼集俗稱源集,是 Android studio 按照邏輯關系將每個模塊的源代碼和資源進行的分組,

模塊的 main 源集包含所有構建變體共用的代碼和資源,

其他的源集都是可選的,在添加構建型別,產品變種或者配置構建變體后,Android studio 并不會自動的創建對應的源集,

我們可根據實際需求自行創建:

  • src/main/
    此源代碼集包含所有構建變體共用的代碼和資源,

  • src/buildType/
    創建此源代碼集可加入特定構建型別專用的代碼和資源,

  • src/productFlavor/
    創建此源代碼集可加入特定產品變種專用的代碼和資源,
    注意:如果配置構建以組合多個產品變種,則可以為變種維度之間的每個產品變種組合創建源代碼集目錄:src/productFlavor1ProductFlavor2/

  • src/productFlavorBuildType/
    創建此源代碼集可加入特定構建變體專用的代碼和資源,

例如,如果要生成 “cityDebug” 版本,Android Gradle 需要合并來自以下源集的代碼、資源和配置:

  • src/cityDebug (構建變體源集)
  • src/debug (構建型別源集)
  • src/city (產品變種源集)
  • src/main (主源集)

如果不同源集包含同一資源的不同版本,Gradle 將按照以下優先順序決定使用哪一個(左側源集替換右側源集的檔案和設定)

構建變體 > 構建型別 > 產品變種 > 主源代碼集 > 庫依賴項

這樣一來,Gradle 在你構建某個變體時就會專門使用對應的源集,同時重復利用與應用的其他版本共用的 Activity、應用邏輯和資源,

在合并多個清單時,Gradle 會使用相同的優先順序,這樣每個構建變體都能在最終清單中定義不同的組件或權限,

前面說到為構建型別,產品變種和構建變體創建自己專用的代碼和資源就是通過創建各自的源集實作的,

例如,要為 debug 構建型別創建源集,只需要在 src目錄下創建一個 debug 目錄就好了,

其目錄結構也和 main 源集一樣就好,java 代碼 放在 java 目錄里,資源檔案檔案放在 res 目錄里,
debugSourceSet

為產品變種和構建變體創建源集都是一樣的,根據名稱創建在 src 下創建對應的目錄即可,
目錄里對資源和代碼的組織和 main 源集一樣即可,
buildVariant-sourceSet

Android Gradle 提供了一個任務 :sourceSets .

這個任務的輸出展示了如何組織每個構建型別、產品變種和構建變體的檔案,
sourceSet

當然這些都不是說定死了, 只不過約定俗成的都這么用,如果你偏偏不想這么用,非想特立獨行的改變源集的組織方式也是可以的,自行查閱吧,關鍵詞: “更改默認源代碼集配置”

單獨配置資源和代碼整完了,接著看怎么單獨配置依賴,使用第三方庫,

在關鍵字 implementation 前邊加上源集的名稱就可以了,我們創建一個應用模塊時就能看到這樣的例子

// main 源集的依賴
implementation 'androidx.constraintlayout:constraintlayout:1.1.3’
//test 源集的依賴
testImplementation 'junit:junit:4.12’
//androidTest 源集的依賴
androidTestImplementation 'androidx.test.ext:junit:1.1.1'

為 debug 構建型別添加依賴

debugImplementation project(":library")

為 city 構建變種添加依賴

cityImplementation project(":library")

為 cityDebug 構建變體添加依賴

cityDebugImplementation project(":library")

配置簽名資訊

APP 只有在簽名之后才能被發布,安裝,使用,簽名是保護 APP 的一種方式,標記該 APP 的唯一性,

如果簽名被惡意篡改,簽名就不一樣了,就無法安裝升級了,一定程度上也保護了我們的 APP,

要對 APP 簽名 就需要一個簽名證書檔案,這個檔案怎么創建下面會有,

一般情況下我們有兩種構建型別,debug 和 release ,對應的是開發生命周期中的兩個階段,通常也是只給發布型別的 APP 配置簽名資訊,

開發除錯時,Android studio 已經為我們提供了一個默認的 debug 簽名證書,可以直接使用,無需單獨配置,一般位于 $HOME/.android/debug.keystore ;密碼為 android ,

Android Gradle 提供了 signingConfigs{} 以便我們配置簽名資訊,只需要將簽名資訊添加在這個代碼塊里就可以了,

//簽名密鑰庫配置

signingConfigs {
    //配置一個簽名資訊,名稱為 release 
    release {
        storeFile file("myreleasekey.keystore")
        storePassword "password"
        keyAlias "MyReleaseKey"
        keyPassword "password"
    }
}

signingConfigs{} 代碼塊里配置實際是屬于 SigningConfig 型別的,一個SigningConfig 就是一個簽名配置,可以添加多個簽名資訊,

其中 release 就是簽名配置的名字,代碼塊里就是對當前簽名的配置,

其中常用的配置屬性如下

  • storeFile 簽名證書檔案
  • storePassword 簽名證書檔案密碼
  • keyAlias 密鑰別名
  • keyPassword 密鑰密碼

更詳細的配置看這里 SigningConfig

一個簽名證書里可以有多個 密鑰,每個密鑰 都有自己的密碼,

Android studio 目前是提供了圖形視窗供我們使用的,在視窗里填好資訊就自動配置腳本,
配置簽名資訊

配置完成 簽名后,就可以直接在構建型別或者產品變種的配置中參考了

//城市 變種
city {
    dimension "domicile"
    versionNameSuffix '-city'
    signingConfig signingConfigs.city
}

創建簽名證書

1.在上方工具條的 build 選單里選擇 Generate Signed Builde /APK
創建簽名證書

  1. 選擇 APK,點擊 next
    創建簽名證書

  2. 選擇 Create New… 進入創建視窗

創建簽名證書

  1. 然后就是創建簽名證書檔案,選擇存盤路徑,設定密碼,創建密鑰,設定密鑰密碼,有效期默認就好,其他的資訊視自己情況配置,填寫完成后,點擊 OK 就可以了,

創建簽名證書

5.在創建完簽名證書后,會自動賦值到之前的視窗,到這里簽名證書檔案就創建完成了,如果不繼續生成 APK 就可以關閉了,

創建簽名證書

壓縮 APK

在配置了 minifyEnabled true 之后系統默認就會啟用 R8 代碼壓縮,優化,混淆功能,

混淆規則是配置在 proguard-rules.pro 檔案里,可通過 proguardFiles 配置更改,

//發布型別
release {
    //是否啟用混淆
    minifyEnabled false
    //proguard 規則檔案;
    //getDefaultProguardFile 是 Android 擴展的一個方法,可以獲取你的 Android SDK 目錄下默認的 proguard 組態檔,
    //在 android-sdk/tools/proguard/目錄下,檔案名就是傳入的 proguard-android-optimize.txt
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}

檔案里默認是沒有任何規則的,需要自行配置,

Android Gradle 在 3.4.0 以及之后的版本已經默認不使用 Proguard 了,改成 R8 編譯器了,

目前 R8 編譯器是 支持所有現有的 Proguard 規則檔案,所以即使現在不使用 Proguard 了,仍然不需要做什么改變,

關于 Proguard 的規則我在另一篇文章里詳細的解釋了一下 Proguard 常用規則

R8 編譯器幾乎和 Proguard 編譯程序差不多,在編譯時會處理以下任務

  • 代碼縮減(即搖樹優化):從代碼中檢測沒有使用到的類、欄位、方法和屬性然后進行安全的移除,這里如果你用到了反射并沒有直接參考就需要配置保留入口點了,
  • 資源縮減:移除不使用的資源,包括依賴的庫中的資源,如果你有動態參考的資源就需要配置哪些資源不能被清除
  • 混淆處理:縮短或者重命名類和成員的名稱,從而減小 DEX 檔案的大小,
  • 優化:檢查并重寫代碼,進一步縮小 DEX 的大小,例如,如果 R8 檢測到 if/else 陳述句中的 else {} 分之沒有采用過,就會把 else {} 移除

在設定了 minifyEnabled true 之后,R8 會從多個地方讀取 Proguard 規則檔案,這里把 R8 使用的檔案來源列一下,了解一下編譯器都是從哪里讀取組態檔,

來源 位置 說明
Android studio <module-dir>/proguard-rules.pro 在使用 IDE 創建新模塊時,IDE 會在該模塊的根目錄創建 proguard-rules.pro 檔案默認是沒有任何規則的,需要自行配置,
Android Gradle 插件 由 Android Gradle 插件在編譯時生成 Android Gradle 插件會生成 proguard-android-optimize.txt(其中包含了對大多數 Android 專案都有用的規則),并啟用 @Keep* 注釋,
默認情況下,使用 Android Studio 創建新模塊時,模塊級 build.gradle 檔案會配置此檔案,
庫依賴項 AAR 庫:<library-dir>/proguard.txt
JAR 庫:<library-dir>/META-INF/proguard/
如果某個 AAR 庫是使用它自己的 ProGuard 規則檔案發布的,并且將該 AAR 庫作為編譯時依賴項納入到專案中,那么 R8 在編譯專案時會自動應用其規則,(library 專案里的 consumerProguardFiles 配置)

如果 AAR 庫需要某些保留規則才能正常運行,那么使用該庫隨附的規則檔案將非常有用,
也就是說,庫開發者已經為你配置好了規則,不過,請注意,由于 ProGuard 規則是累加的,因此 AAR 庫依賴項包含的某些規則無法移除,并且可能會影響對應用其他部分的編譯,
例如,如果某個庫包含停用代碼優化功能的規則,該規則會針對整個專案停用優化功能,
Android 資源打包工具 2 (AAPT2) 使用 minifyEnabled true 構建專案后:<module-dir>/build/intermediates/proguard-rules/debug/aapt_rules.txt AAPT2 會根據對應用清單中的類、布局及其他應用資源的參考,生成保留規則,
例如,AAPT2 會為您在應用清單中注冊為入口點的每個 Activity 添加一個保留規則,
自定義組態檔 默認情況下,當使用 Android Studio 創建新模塊時,IDE 會創建 <module-dir>/proguard-rules.pro,以便添加自己的規則, 我們可以添加自定義的配置,R8編譯器在編譯時會應用這些配置

在配置了 minifyEnabled true 之后, R8 會將來自上述所有可用來源的組態檔組合到一起,

如果需要查看 R8 在構建專案時應用的所有規則的完整報告,可以將以下代碼加入到模塊的 proguard-rules.pro 檔案中
路徑和名字可以隨意更改

-printconfiguration ~/tmp/full-r8-config.txt

自動清理未使用的資源

在配置 minifyEnabled true 后 R8 編譯器會將代碼進行優化縮級訓淆,那么資源呢,如何優化呢?

答案是通過配置 shrinkResources 屬性

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

通過 shrinkResources true 配置 資源縮減,可將沒有使用到的資源自動移除,

配置資源縮減的前提是配置了代碼縮減,資源縮減只有在與代碼縮減配合才能發揮作用,

在代碼縮減器移除掉所有不使用代碼后,資源縮減器便可以確定哪些資源沒有被參考,從而安全的移除,

通常我們在實際開發中會有一些資源是未被直接參考的,存在動態參考或者反射參考的可能,這時就需要配置一些規則,告訴資源縮減器規則內的資源不能被移除,

這就和配置 Proguard 規則保留入口點的道理一樣,

配置要保留的資源

如果需要自定義保留或者舍棄特定資源,需要在專案中創建一個包含 <resources> 標記的 XML 檔案,

可以在 tools:keep 屬性中指定要保留的資源,在 tools:discard 屬性中指定要舍棄的資源,

這兩個屬性都接受以逗號分隔的資源名稱串列,也可以使用 * 作為通配符,

例如

<resources
    xmlns:tools="http://schemas.android.com/tools"
    tools:keep="@mipmap/more,@mipmap/saw"
    tools:discard="@mipmap/*_2"
    tools:shrinkMode="strict">
<!--保留 more saw檔案-->
<!--    舍棄 share_2 檔案-->
<!--    嚴格模式-->
</resources>

通常將檔案保存在 /res/raw/keeps.xml ,Android Gradle 不會將其打包進 APK,除非你在代碼中使用了 R.raw.keeps

上面的三個屬性都是可選項,其中 shrinkMode 是配置自動清理資源的模式,有兩個可選項

  • strict 嚴格模式
  • safe 安全模式,默認值

默認值的情況下,對于代碼中動態參考資源,資源縮級訓自行模糊判斷一些資源,當作已使用資源,

例如,下面這個代碼,就會把 img_ 為前綴的資源都算已參考資源,

String name = String.format("img_%1d", angle + 1);

res = getResources().getIdentifier(name, "drawable", getPackageName());

如果設定了 strict 模式,就必須手動保留了,例如這樣

<resources
    xmlns:tools="http://schemas.android.com/tools"
    tools:keep="@drawable/img_*"
    tools:shrinkMode="strict">
</resources>

配置生成的 APK 名稱

//    配置 APK 名稱
android.applicationVariants.all { variant ->
     variant.outputs.all {
        outputFileName = "Example_${variant.flavorName}_${variant.versionCode}_${variant.versionName}.apk"
     }
}

動態配置 AndroidManifest 檔案

動態配置 AndroidManifest 檔案就是在構建程序中,動態修改 AndroidManifest 檔案中的一些內容,

其本質是將構建變數注入到清單檔案中,

在清單檔案中是可以使用 占位符 的,格式是 ${variable} ,

例如常用的渠道編號

<!-- 渠道商編號 -->
<meta-data
    android:name="BaiduMobAd_CHANNEL"
    android:value="https://www.cnblogs.com/skymxc/archive/2020/09/12/${CHANNEL_NAME}" />

定義好占位符之后在 build.gradle 腳本里就可以通過 ProductFlavor 的 manifestPlaceholders 屬性進行配置,它接受 Map 型別的引數,

//默認配置,它是一個 ProductFlavor
defaultConfig {
   ······
    manifestPlaceholders = [
            CHANNEL_NAME:"default"
    ]
}

實際開發中通常是在產品變種配置渠道,方便日后運營統計查看

//變種維度
 flavorDimensions "channel"

 //產品變種
 productFlavors{

//        為了實踐動態配置 AndroidManifest 檔案
     huawei {
         dimension "channel"
         manifestPlaceholders = [
                 "CHANNEL_NAME":"華為"
         ]
     }
     mi {
         dimension "channel"
         manifestPlaceholders = [
                 CHANNEL_NAME:"小米"
         ]
     }
}

默認情況下是有一個 ${applicationId} 占位符的,它會提供程式的應用ID,

例如

<intent-filter ... >
    <action android:name="${applicationId}.TRANSMOGRIFY" />
    ...
</intent-filter>

自定義 BuildConfig

對于 BuildConfig 這個類,應該都很熟悉,這是一個由 構建工具生成的類,
BuildConfig

其中有一個 DEBUG 欄位是我們常用的,用于標記是否在開發除錯階段,通常可以用作是否開啟日志的開關,剩下的幾個欄位也都很熟悉,都是 build.gradle 中的配置,

除了構建工具自動生成的欄位,也可以通過 ProductFlavor.buildConfigField(String type, String name, String value) 方法自定義 BuildConfig 的欄位,

  • 第一個引數是 要生成的欄位的型別
  • 第二個引數是 要生成的欄位的名字
  • 第三個引數是 要生成的欄位的常量值,如果是 String 型別型別的要帶上引號,

例如,在 腳本里定義一個欄位后

defaultConfig {

    buildConfigField "String" "WEBURL" "\"https://github.com/skymxc\""

}

Sync now 之后就會在 BuildConfig 類中看到對應的欄位了
自定義BuildConfig

這個配置在構建型別和產品變種里都是可以配置的,利用這個特性,就可以針對不同的構建型別,不同的產品變種配置不同的欄位,

例如,分別配置開發和生產環境

defaultConfig {
    buildConfigField "String" "WEBURL" "\"https://github.com/skymxc\""
}

//構建型別
buildTypes {
    //發布型別
    release {
      ·······
        buildConfigField "String","WEBURL","\"https://www.cnblogs.com/skymxc/\""
    }
}

也可以針對不同變種配置

//產品變種
productFlavors{

    //農村 變種
    countryside {
        dimension "domicile"
        buildConfigField "int","type","2"
    }
    
    //城市 變種
    city {
        dimension "domicile"
        buildConfigField "int","type","1"
    }

}

Java 編譯選項

Android Gradle 提供了一個 compileOptions{} 對 Java 編譯進行配置

//Java 編譯選項配置
compileOptions {
    // Java 源代碼的編碼
    encoding = 'utf-8'
    //Java 源代碼編譯級別
    sourceCompatibility JavaVersion.VERSION_1_8
    //生成的 Java 位元組碼版本
    targetCompatibility JavaVersion.VERSION_1_8
}

常用的配置有三個

  • encoding Java源代碼的編碼
  • sourceCompatibility Java 源代碼編譯級別
  • targetCompatibility 生成的 Java 位元組碼版本

關于 64 K 限制

在打包 APK 檔案時,Java 源代碼被打包成了一個 DEX 檔案,這個檔案就是優化過的、Dalvik 虛擬機可執行的檔案,

Dalvik 虛擬機在執行 DEX 檔案的時候,它使用了 short 這個型別來索引 DEX 檔案中的方法,這就意味著單個 DEX 檔案最多只能是 65535 個,當方法數超過這個數量就會出現編譯錯誤,

因為 1024 * 64 = 65535 也稱 64K 限制,

解決辦法就是生成多個 DEX 檔案,讓單個 DEX 檔案內的方法數不超過 64K .

在 Android 5.0 及之后的版本使用 ART 了運行時,本身支持從 APK 中加載多個 DEX 檔案,

ART 在應用安裝時執行預編譯,掃描 class[N].dex 檔案,并將他們合成一個 .oat 檔案,以供 Android 設備執行,

因此,如果你的 minSdkVersion 是 21 或者更高的版本,默認就會啟用 MultiDex ,在打包時構建工具會自動生成多個 DEX 檔案,

如果 miniSdkVersion 在 20或者更低,就需要在 build.gradle 腳本添加配置 multiDexEnabled true 啟用 MultiDex,并添加 MultiDex 支持庫,

android {

    defaultConfig {
        ...
        minSdkVersion 15
        targetSdkVersion 28
        multiDexEnabled true
    }
    ...

}
dependencies {
  implementation 'com.android.support:multidex:1.0.3’
}

如果使用了 androidx ,則使用以下依賴

def multidex_version = "2.0.1"
implementation 'androidx.multidex:multidex:$multidex_version'

添加完依賴庫之后,還需要替換 Application 類

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <application
            android:name="android.support.multidex.MultiDexApplication" >
        ...
    </application>
</manifest>

如果你有自己的 Application 類,只需繼承 MultiDexApplication 即可

public class MyApplication extends MultiDexApplication { ... }

如果你不能繼承此類,也可在自己的 Application 類的 attachBaseContext() 方法里呼叫 MultiDex.install(this) 以啟用 MultiDex

public class MyApplication extends SomeOtherApplication {

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

注意:在 MultiDex.install() 完成之前,不要通過反射或 JNI 執行 MultiDex.install() 或其他任何代碼,MultiDex 跟蹤功能不會追蹤這些呼叫,從而導致出現 ClassNotFoundException,或因 DEX 檔案之間的類磁區錯誤而導致驗證錯誤,

關于更多 64K 限制的檔案可以看這里:啟用 MultiDex

學習資料

  • 《Android Gradle 權威指南》
  • Android Studio 用戶指南
  • Android Plugin DSL Reference

End

最后把 Android Gradle 的 DSL 查詢地址留一下Android Plugin DSL Reference 方便大家隨用隨查,

我把這些配置和注釋都放在了 GitHub 上的一個倉庫里,需要時查閱即可 AndroidGradleExample

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/106806.html

標籤:其他

上一篇:開發一個漸進式Web應用程式(PWA)前都需要了解什么?

下一篇:Android連載32-實作登錄密碼存盤功能

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more