你該知道的Gradle配置知識總結(jié)
前言
本文主要介紹了關(guān)于Gradle配置的相關(guān)知識,分享出來供大家參考學(xué)習(xí),下面話不多說了,來一起看看詳細(xì)的介紹吧。
參考鏈接:https://developer.android.com/studio/build/index.html
本片文章的內(nèi)容全部參考自上面的鏈接,其中有些內(nèi)容是直接翻譯的,有些內(nèi)容是結(jié)合自己的經(jīng)驗(yàn)總結(jié)的,可能有理解錯誤的地方,非常希望大家能指正出來,在交流中進(jìn)步。
Gradle 編譯過程

編譯流程圖
上圖展示了一個典型的 App 編譯過程,主要分為以幾步:
- 編譯器將源代碼(包括依賴庫)轉(zhuǎn)化為 DEX 文件,編譯資源文件(res 以及 assets 文件下的資源)。
- APK Packager 整合所有的 DEX 文件和編譯過的資源文件,并且對 APK 進(jìn)行簽名。
- 簽名文件必須使用 Debug 版或者 Release 版,使用 Debug Keystore 生成的 app 被用來測試和分析,使用 Release Keystore 生成的 app 可以進(jìn)行發(fā)布供其他用戶使用。
- 在生成最終的 APK 之前,APK Packager 會使用 zipalign 工具優(yōu)化整個 app ,以便 app 在使用的過程中更加節(jié)省內(nèi)存。
自定義編譯配置
Android Studio 的 gradle 插件方便我們在以下幾個方面配置我們的編譯選項(xiàng):
Build Types - 編譯類型
編譯類型,包括我們最熟悉的 release 和 debug 兩種類型,我們可以根據(jù)這兩種類型定義出更多的類型。配置對應(yīng)的 build.gradle 文件在 moudle 下,需要添加新的或者修改 Build Type ,只需要在 android{ ... }里面操作。
一個示例如下:
android {
...
defaultConfig {...}
buildTypes {
release {
//開啟混淆
minifyEnabled true
//混淆規(guī)則文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
//apk的后綴
applicationIdSuffix ".debug"
}
//debug的一個擴(kuò)展
jnidebug {
// 復(fù)制debug的屬性和簽名配置
initWith debug
applicationIdSuffix ".jnidebug"
//開啟Jni調(diào)試
jniDebuggable true
}
}
}
其中 initWith 可以方便我們繼承其他的配置,只需要添加需要的部分。
Product Flavors - 構(gòu)建不同版本
配置 apk 的版本信息,可以為每一個版本指定不同的 applicationId 和版本名稱。關(guān)于 applicationId ,可以把它也理解為包名,不過和 Manifest 文件中的包名作用不同,它是用來給應(yīng)用商店和設(shè)備區(qū)分不同的 app ,而 Manifest 中的 pakage 屬性用來在源代碼中引用 R 類和其他類。即同一份代碼 applicationId 可以讓它變成不同的 app 。
示例配置如下:
android {
...
defaultConfig {...}
buildTypes {...}
productFlavors {
demo {
applicationId "com.example.myapp.demo"
versionName "1.0-demo"
}
full {
applicationId "com.example.myapp.full"
versionName "1.0-full"
}
}
}
通過上面的配置之后,如果 buildTypes 里面配置了兩個編譯類型,假如是 debug 和 release ,將會產(chǎn)生四個 apk 文件,每一種 buildType 都會和每種 flavor 進(jìn)行組合拼接,進(jìn)而產(chǎn)生不同的變種版本(Build Variant),上面對應(yīng)的四個不同的變種版本分別是:demoDebug、demoRelease、fullDebug、fullRelease。
Mutiple Manifest Files - 合并多個清單文件
配置多個 Manifest 文件。經(jīng)常會在項(xiàng)目中依賴其他項(xiàng)目,這個時候就會有多個 Manifest 文件,那在編譯的時候該如何處理呢?這個時候需要進(jìn)行合并,而且還必須有一套相應(yīng)的合并規(guī)則解決和避免合并沖突。對于不同的 Manifest 文件中同一個屬性的不同值,在合并的時候還需要優(yōu)先級來進(jìn)行判斷,用高優(yōu)先級的去覆蓋低優(yōu)先級的。
關(guān)于優(yōu)先級定義如下:
- 最高優(yōu)先級:buildType 的設(shè)置
- 次高優(yōu)先級:productFlavor 的設(shè)置
- 中等優(yōu)先級:在 src/main 目錄下的 Manifest 文件
- 最低優(yōu)先級:各種依賴和第三方庫的設(shè)置
合并規(guī)則:概括來說是這樣:
- 合并之前,先將每個 module 里面的 buildType 內(nèi)容寫到 Manifest 里面去,比如你在 buildType 里面的 minSdkVersion 和targetSdkVersion 以及 versionCode 和 VersionName 等等(此時合并后的 Manifest 文件可以在 app/intermediates/manifests/* 目錄下查看)。
- 對于同一個屬性,當(dāng)高優(yōu)先級和低優(yōu)先級都為非默認(rèn)值時,如果可以匹配,那直接合并,不能匹配,就會產(chǎn)生沖突(這種是針對兩個不同的 module 來說),下面會專門給出例子。
- 不管高優(yōu)先級還是低優(yōu)先級,如果其中一個沒有設(shè)置該屬性或者設(shè)置為默認(rèn)的屬性值,而另外一個設(shè)置了非默認(rèn)的屬性值,則合并的結(jié)果就是非默認(rèn)的屬性值,在項(xiàng)目編譯后,可以查看 Manifest 的合并記錄,該文件目錄為:app/intermediates/outputs/logs/manifest*.txt。
示例:現(xiàn)在給出一些例子說明上述規(guī)則,我的主 module 名為 app ,新建一個依賴的 module 叫 uisdk ,現(xiàn)在分別給出兩個 module 的 build.gradle 文件:
app/build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "24.0.0"
defaultConfig {
applicationId "com.example.rth.study"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
demo {
minSdkVersion 7
applicationId "com.rth.app"
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.0.0'
compile project(':uisdk')
}
uisdk/build.gradle
apply plugin: 'com.android.library'
android {
compileSdkVersion 24
buildToolsVersion "24.0.0"
defaultConfig {
minSdkVersion 8
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.0.0'
}
在 app/build.gradle 里面,defaultConfig 的 minSdkVersion 為15,但我在變種版本(productFlavors 里的 demo)里設(shè)置的 minSdkVersion 為7,最終 app 的 Manifest 的 minSdkVersion 就為7,再看 uisdk 里面的 build.gradle ,minSdkVersion 為8,就是說 app 這個 module 和 uisdk 這個 module library 在同一個屬性上使用了不同的非默認(rèn)值,而且 library 的 Manifest 屬于最低優(yōu)先級,它設(shè)置的值又比優(yōu)先級比它高的值還要高,就會出錯,出錯信息的描述也很清晰:
Error:Execution failed for task ':app:processDemoDebugManifest'. Manifest merger failed : uses-sdk:minSdkVersion 7 cannot be smaller than version 8 declared in library ... Suggestion: use tools:overrideLibrary="com.example.uisdk" to force usage
根據(jù)錯誤信息,我們有兩種方式解決這個問題:
- 把 app 里面的值調(diào)高,或者把 uisdk 里面的值調(diào)低。
- 就像上面建議的那樣,使用 overrideLibrary 這個標(biāo)簽。該標(biāo)簽的作用在名字上已經(jīng)體現(xiàn)出來了,就是直接覆蓋 library 里面的設(shè)置,現(xiàn)在我們在 app/src/main/Manifest 里面加上這么一句:
<uses-sdk tools:overrideLibrary="com.example.uisdk"/>
就能編譯通過了,這適用于比較特殊的情況,就是在依賴庫里可能要適用一些新特性,這些特性在 app 的 minSdkVersion 下不能使用,而且 app 的 minSdkVersion 已經(jīng)不能更改了。
標(biāo)記選擇器(Marker Selectors) :選擇器的功能可以讓一些屬性在某些 libary 里面無效,比如就拿上面的例子來說,我想讓 uisdk 只處理 ui 上的東西,不想讓他具有網(wǎng)絡(luò)訪問的功能,那么我可以這么設(shè)置:
<uses-permission android:name="android.permission.INTERNET" tools:node="remove" tools:selector="com.example.uisdk" />
其中 tools:node 標(biāo)簽表示刪除該權(quán)限,tools:selector 標(biāo)簽選擇在哪個依賴庫里執(zhí)行 tools:node 表示的動作。
可以看出這些配置還是挺靈活的。
Configure dependencies - 配置依賴
這個應(yīng)該是最熟悉的了,項(xiàng)目中經(jīng)常要依賴第三方庫,一個典型了例子如下:
android {...}
...
dependencies {
//將本地 module library 編譯到項(xiàng)目中
compile project(":mylibrary")
//編譯遠(yuǎn)程依賴
compile 'com.android.support:appcompat-v7:23.4.0'
//編譯本地 jar 包
compile fileTree(dir: 'libs', include: ['*.jar'])
}
上面主要用到的方式是 compile ,gradle 支持6種編譯方式:
- compile:對所有 buildType 以及 flavors 進(jìn)行編譯并打包到 apk 。
- provided:和 compile 相似,但只在編譯時使用,幾只參與編譯,不打包到最終 apk 。
- apk:只會打包到 apk 中,不參與編譯,所以不能在項(xiàng)目代碼中使用相應(yīng)庫中的方法。
- test compile:相比于 compile ,僅僅針對單元測試的代碼編譯打包。
- debug compile:僅針對 debug 模式編譯打包。
- release compile:僅針對 release 模式編譯打包。
另外在進(jìn)行 sdk 開發(fā)時,一般為了減小 sdk 體積,一些依賴庫會用 provided 的方式,同時需要注意的是,對于遠(yuǎn)程依賴,compile 和 provided 的效果一樣,都不會打包到 jar 包或者 arr 包中,但對于本地的 jar 包或者 arr 包的依賴,compile 和 provided 就有區(qū)別了。
Configure Sigining - 配置簽名
在用 gradle 配置 release 版本的簽名信息時,需要下面三個步驟:
- 生成一個 keystore ,一個二進(jìn)制文件保存一些私鑰,這個必須好好保存。
- 生成一個私鑰,用于開發(fā)者或者公司與這個 app 建立對應(yīng)關(guān)系。
- 將生成的信息配置到 moudle 層的 build.gradle 里。
示例如下:
android {
...
defaultConfig {...}
signingConfigs {
release {
storeFile file("myreleasekey.keystore")
storePassword "password"
keyAlias "MyReleaseKey"
keyPassword "password"
}
}
buildTypes {
release {
...
signingConfig signingConfigs.release
}
}
}
上面的配置中直接顯示了一些敏感信息,比如各種密碼,一種更加安全的方式是通過環(huán)境變量的方式獲?。?br />
storePassword System.getenv("KSTOREWD");
keyPassword System.getenv("KEYPWD");
或者如果使用命令行的方式編譯,還可以讓用戶在命令行輸入密碼:
storePassword System.console().readLine("\nKeystore password: ")
keyPassword System.console().readLine("\nKey password: ")
暫時就總結(jié)到這么多了,再次說明,如果發(fā)現(xiàn)理解錯的地方歡迎指正!??!
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
- Android Studio手動配置Gradle的方法
- android studio 3.0 gradle 打包腳本配置詳解
- 詳解關(guān)于Android Studio中安裝和gradle的一些坑
- 詳解Androidstudio3.0 關(guān)于Gradle報錯的問題(小結(jié))
- 詳解如何使用Android Studio開發(fā)Gradle插件
- Android如何在Gradle中更改APK文件名詳解
- Android gradle打包并自動上傳的方法
- AndroidStudio Gradle基于友盟的多渠道打包方法
- AndroidStudio Gradle第三依賴統(tǒng)一管理的實(shí)現(xiàn)方法
- Android 出現(xiàn)問題 Gradle
- AndroidStudio更新出現(xiàn)Refreshing ''xxx'' Gradle Project狀態(tài)解決辦法
- Android studio利用gradle打jar包并混淆的方法詳解
- Android 自定義gradle property詳解及實(shí)例代碼
- Android Studio 3.0 gradle提示版本太老
相關(guān)文章
Android App中實(shí)現(xiàn)圖片異步加載的實(shí)例分享
這篇文章主要介紹了Android App中實(shí)現(xiàn)圖片異步加載的實(shí)例分享,這樣GridView在加載大量圖片時便可以延時分布顯示,需要的朋友可以參考下2016-04-04
Android TagCloudView云標(biāo)簽的使用方法
這篇文章主要為大家詳細(xì)介紹了Android TagCloudView云標(biāo)簽的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-05-05
基于Android實(shí)現(xiàn)個性彩色好看的二維碼
二維碼在我們?nèi)粘I钪袩o處不在,今天小編通過本教程給大家介紹基于Android實(shí)現(xiàn)個性彩色好看的二維碼,需要的朋友參考下吧2016-02-02
Android防止按鈕過快點(diǎn)擊造成多次事件的解決方法
這篇文章主要介紹了Android防止按鈕過快點(diǎn)擊造成多次事件的解決方法的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-07-07
強(qiáng)制Android應(yīng)用使用某個Locale的方法
這篇文章主要介紹了強(qiáng)制Android應(yīng)用使用某個Locale的方法,涉及Android基于Locale進(jìn)行語言設(shè)置的相關(guān)技巧,需要的朋友可以參考下2015-10-10
Android實(shí)現(xiàn)單選與多選對話框的代碼
這篇文章主要介紹了Android實(shí)現(xiàn)單選與多選對話框的代碼,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-01-01

