Gradle是什么?
Android Studio 基于 Gradle 構(gòu)建系統(tǒng),并通過 Android Gradle 插件提供更多面向 Android 的功能
Gradle 和 Android 插件獨立于 Android Studio 運行。這意味著,您可以在 Android Studio 內(nèi)、使用計算機上的命令行工具或在未安裝 Android Studio 的計算機(例如持續(xù)性集成服務(wù)器)上構(gòu)建 Android 應(yīng)用。如果您不使用 Android Studio,可以學(xué)習(xí)如何從命令行構(gòu)建和運行您的應(yīng)用。無論您是從命令行、在遠(yuǎn)程計算機上還是使用 Android Studio 構(gòu)建項目,構(gòu)建的輸出都相同。
Gradle與Android項目相關(guān)的文件
Gradle 設(shè)置文件 —— settings.gradle

頂級構(gòu)建文件 —— build.gradle

模塊級構(gòu)建文件 —— build.gradle
模塊級 build.gradle 文件位于每個 <project>/<module>/ 目錄
apply plugin: 'com.android.application'
/**
* android {}塊配置所有Android特定的構(gòu)建選項
*/
android {
/**
* compileSdkVersion指定Gradle應(yīng)該使用的Android API級別
* 編譯您的應(yīng)用程序。 這意味著您的應(yīng)用可以使用的API等于
* 或低于這個API。
*
* buildToolsVersion指定SDK構(gòu)建工具的版本,命令行
* 以及Gradle用來構(gòu)建應(yīng)用程序的編譯器。 你需要
* 使用SDK管理器下載構(gòu)建工具。
*/
compileSdkVersion 25
buildToolsVersion "25.0.0"
/**
* defaultConfig {}塊封裝了所有構(gòu)建variants的默認(rèn)設(shè)置,
* 并可以覆蓋AndroidManifest.xml中的某些屬性例如包名、
* minSdkVersion 、versionCode扥
*/
defaultConfig {
/**
* applicationId唯一,等同于AndroidManifest.xml文件中的package屬性。
*/
applicationId 'com.example.myapp'
// 最小API版本
minSdkVersion 15
// 項目測試運行的版本
targetSdkVersion 25
// 版本號
versionCode 1
// 在app中顯示的版本名稱
versionName "1.0"
}
/**
* buildTypes {}塊可以配置多個構(gòu)建類型。
* 默認(rèn)情況下,構(gòu)建系統(tǒng)定義了兩種構(gòu)建類型:debug和release。
*/
buildTypes {
/**
* 默認(rèn)情況下,Android Studio會配置發(fā)布版本類型以啟用縮減
* 代碼,使用minifyEnabled,并指定Proguard設(shè)置文件。
*/
release {
minifyEnabled true // 啟用縮減代碼
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
/**
* productFlavors {}塊是您可以配置不同定制的產(chǎn)品,例如免費和付費
*/
productFlavors {
free {
applicationId 'com.example.myapp.free'
}
paid {
applicationId 'com.example.myapp.paid'
}
}
/**
* split {}塊中配置不同的APK版本,用于分包
*/
splits {
// Screen density split settings
density {
// 啟用或禁用密度分割機制
enable false
// 不包含以下密度
exclude "ldpi", "tvdpi", "xxxhdpi", "400dpi", "560dpi"
}
}
}
/**
* dependencies {}塊指定模塊需要添加的依賴
*/
dependencies {
compile project(":lib")
compile 'com.android.support:appcompat-v7:25.1.0'
compile fileTree(dir: 'libs', include: ['*.jar'])
}
gradle.properties
您可以在其中配置項目范圍 Gradle 設(shè)置,例如 Gradle 后臺進程的最大堆大小。如需了解詳細(xì)信息,請參閱構(gòu)建環(huán)境。
local.properties
為構(gòu)建系統(tǒng)配置本地環(huán)境屬性,例如 SDK 安裝路徑。由于該文件的內(nèi)容由 Android Studio 自動生成并且專用于本地開發(fā)者環(huán)境,因此您不應(yīng)手動修改該文件,或?qū)⑵浼{入版本控制
注:由于 Gradle 和 Android 插件獨立于 Android Studio 運行,您需要單獨更新構(gòu)建工具。請閱讀版本說明,了解如何更新 Gradle 和 Android 插件。
Gradle可以做什么?
- 自定義、配置和擴展構(gòu)建流程。
- 使用相同的項目和模塊為您的應(yīng)用創(chuàng)建多個具有不同功能的 APK。
- 在不同源代碼集中重復(fù)使用代碼和資源。
Gradle如何構(gòu)建APK?

如圖所示,典型 Android 應(yīng)用模塊的構(gòu)建流程通常依循下列步驟:
- 編譯器將您的源代碼轉(zhuǎn)換成 DEX(Dalvik Executable) 文件(其中包括運行在 Android 設(shè)備上的字節(jié)碼),將所有其他內(nèi)容轉(zhuǎn)換成已編譯資源。
- APK 打包器將 DEX 文件和已編譯資源合并成單個 APK。不過,必須先簽名,才能將應(yīng)用安裝并部署到 Android 設(shè)備上。
- APK 打包器使用調(diào)試或發(fā)布密鑰簽名:
- 如果您構(gòu)建的是調(diào)試版本的應(yīng)用(即專用于測試和分析的應(yīng)用),打包器會使用調(diào)試密鑰庫簽名。Android Studio 自動使用調(diào)試密鑰配置新項目。
- 如果您構(gòu)建的是打算向外發(fā)布的發(fā)布版本應(yīng)用,打包器會使用發(fā)布密鑰簽名。要創(chuàng)建發(fā)布密鑰,請閱讀在 Android Studio 中簽名。
- 在生成最終 APK 之前,打包器會使用 zipalign 工具對應(yīng)用進行優(yōu)化,減少其在設(shè)備上運行時的內(nèi)存占用。
構(gòu)建流程結(jié)束時,您將獲得可用來進行部署、測試的調(diào)試 APK,或者可用來發(fā)布給外部用戶的發(fā)布 APK。
如何配置不同構(gòu)建類型?
您必須至少定義一個構(gòu)建類型才能構(gòu)建應(yīng)用——Android Studio 默認(rèn)情況下會創(chuàng)建調(diào)試和發(fā)布構(gòu)建類型。盡管調(diào)試構(gòu)建類型不會出現(xiàn)在構(gòu)建配置文件中,Android Studio 會將其配置為 debuggable true
。要開始為應(yīng)用自定義打包設(shè)置,請學(xué)習(xí)如何配置構(gòu)建類型。
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
applicationIdSuffix ".amy"
versionNameSuffix ".amy"
}
/**
* The 'initWith' property allows you to copy configurations from other build types,
* so you don't have to configure one from the beginning. You can then configure
* just the settings you want to change. The following line initializes
* 'jnidebug' using the debug build type, and changes only the
* applicationIdSuffix and versionNameSuffix settings.
*/
jnidebug {
// This copies the debuggable attribute and debug signing configurations.
initWith debug
applicationIdSuffix ".jnidebug"
jniDebuggable true
}
}
我們現(xiàn)在設(shè)置了debug構(gòu)建類型的applicationIdSuffix屬性和versionNameSuffix屬性,那么如何驗證app的debug版本的包名和版本名改變了呢?
這里我們就需要用到aapt(Android Asset Packaging Tool)了,我們可以在..\sdk\build-tools[sdk version(例如我的電腦里面是23.0.2)]目錄下找到該工具,然后將之前打包的app-debug.apk文件復(fù)制到該目錄下,然后在命令行中使用如下命令:
D:\Users\Administrator\AppData\Local\Android\sdk\build-tools\23.0.2>aapt dump ba
dging app-debug.apk
可以得到以下輸出:
package: name='mylibrary.zero.com.customview.jmy'
versionCode='1'
versionName='1
.0.jmy'
platformBuildVersionName=''
sdkVersion:'17'
targetSdkVersion:'24'
從上面的輸出可以看到package和versionName的后綴都多了 .jmy
如需詳細(xì)了解對于構(gòu)建類型可以配置的所有屬性,請閱讀構(gòu)建類型 DSL 參考
如何發(fā)布不同版本的應(yīng)用?
productFlavors代表您可以發(fā)布給用戶的不同應(yīng)用版本,例如免費和付費的應(yīng)用版本。您可以將productFlavors自定義為使用不同的代碼和資源,同時對所有應(yīng)用版本共有的部分加以共享和重復(fù)利用。productFlavors是可選項,并且您必須手動創(chuàng)建。要開始創(chuàng)建不同的應(yīng)用版本,請學(xué)習(xí)如何配置productFlavors。
defaultConfig實際上屬于 ProductFlavor 類。這意味著,您可以在 defaultConfig {}代碼塊中提供所有ProductFlavor的基本配置,例如 applicationId
。
注:您仍需在清單文件中使用 package 屬性指定程序包名稱。這樣,您可以使用 applicationId為每個productFlavors分配一個唯一的 ID,這樣就可以在不更改您的源代碼的情況下打包和分發(fā)。
注:要利用 Google Play 中的多 APK 支持分發(fā)您的應(yīng)用,請為所有Variant分配相同的 applicationId值并為每個Variant分配一個不同的 versionCode。要在 Google Play 中以獨立應(yīng)用的形式分發(fā)應(yīng)用的不同Variant,您需要為每個Variant分配一個不同的 applicationId。
manifestPlaceholders
如果您需要將變量插入到您的build.gradle文件中定義的AndroidManifest.xml文件中,則可以使用manifestPlaceholders屬性。
build.gradle:
android {
defaultConfig {
manifestPlaceholders = [hostName:"www.example.com"]
}
...
}
manifest :
<intent-filter ... >
<data android:scheme="http" android:host="${hostName}" ... />
...
</intent-filter>
默認(rèn)情況下,構(gòu)建工具還會在$ {applicationId}占位符中提供應(yīng)用程序的應(yīng)用程序ID。例如,如果您的build.gradle文件如下所示:
android {
defaultConfig {
applicationId "com.example.myapp"
}
productFlavors {
free {
applicationIdSuffix ".free"
}
pro {
applicationIdSuffix ".pro"
}
}
}
manifest:
<intent-filter ... >
<action android:name="${applicationId}.TRANSMOGRIFY" />
...
</intent-filter>
當(dāng)你構(gòu)建“free”product flavor時,manifest結(jié)果如下:
<intent-filter ... >
<action android:name="com.example.myapp.free.TRANSMOGRIFY" />
...
</intent-filter>
如果想發(fā)布不同版本例如debug、release、demo等,那么組織項目文件?
默認(rèn)的app模塊的build.gradle文件如下:
...
android {
compileSdkVersion 24
buildToolsVersion "24.0.2"
defaultConfig {
applicationId "mylibrary.zero.com.customview"
minSdkVersion 17
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 Plugin for Gradle 提供了一項有用的 Gradle 任務(wù),可向您展示如何針對每種構(gòu)建類型、產(chǎn)品風(fēng)味和構(gòu)建變體組織您的文件:
- 點擊 IDE 窗口右側(cè)的 Gradle
- 導(dǎo)航至 MyApplication > Tasks > android 并雙擊 sourceSets
- 要查看報告,請單擊 IDE 窗口底部的 Gradle Console
用上面的代碼執(zhí)行Gradle任務(wù)后得到的報告如下:
------------------------------------------------------------
Project :app
------------------------------------------------------------
androidTest
-----------
Compile configuration: androidTestCompile
build.gradle name: android.sourceSets.androidTest
Java sources: [app\src\androidTest\java]
Manifest file: app\src\androidTest\AndroidManifest.xml
Android resources: [app\src\androidTest\res]
Assets: [app\src\androidTest\assets]
AIDL sources: [app\src\androidTest\aidl]
RenderScript sources: [app\src\androidTest\rs]
JNI sources: [app\src\androidTest\jni]
JNI libraries: [app\src\androidTest\jniLibs]
Java-style resources: [app\src\androidTest\resources]
debug
-----
......
main
----
......
release
-------
......
test
----
Compile configuration: testCompile
build.gradle name: android.sourceSets.test
Java sources: [app\src\test\java]
Java-style resources: [app\src\test\resources]
testDebug
---------
......
testRelease
-----------
......
而當(dāng)我們增加構(gòu)建類型、productFlavors或構(gòu)建vriant,則會增加對應(yīng)的輸出,例如我們添加productFlavors:
...
android {
...
productFlavors{
demo{
applicationId "mylibrary.zero.com.customview.demo"
versionName "1.0.demo"
}
}
}
...
執(zhí)行Gradle任務(wù)后則增加了和demo對應(yīng)的報告:
androidTestDemo
---------------
Compile configuration: androidTestDemoCompile
build.gradle name: android.sourceSets.androidTestDemo
Java sources: [app\src\androidTestDemo\java]
Manifest file: app\src\androidTestDemo\AndroidManifest.xml
Android resources: [app\src\androidTestDemo\res]
Assets: [app\src\androidTestDemo\assets]
AIDL sources: [app\src\androidTestDemo\aidl]
RenderScript sources: [app\src\androidTestDemo\rs]
JNI sources: [app\src\androidTestDemo\jni]
JNI libraries: [app\src\androidTestDemo\jniLibs]
Java-style resources: [app\src\androidTestDemo\resources]
demo
----
......
demoDebug
---------
......
demoRelease
-----------
......
testDemo
--------
Compile configuration: testDemoCompile
build.gradle name: android.sourceSets.testDemo
Java sources: [app\src\testDemo\java]
Java-style resources: [app\src\testDemo\resources]
testDemoDebug
-------------
......
testDemoRelease
---------------
......
根據(jù)報告,知道項目文件應(yīng)該如何組織,那么如何創(chuàng)建文件呢?
- 在該** Project 窗格中,右鍵點擊 src 目錄并選擇 New > XML > Values XML File **。
- 為 XML 文件輸入名稱或保留默認(rèn)名稱。
- 從** Target Source Set 旁邊的下拉菜單中,選擇 debug**。
- 點擊** Finish**。

打包時,Gradle要如何構(gòu)建呢?
Gradle查找目錄的優(yōu)先級順序
- src/demoDebug/ (構(gòu)建variant源集)
- src/debug/ (構(gòu)建類型源集)
- src/demo/ (productFlavors源集)
- src/main/ (主源集)
- library (依賴庫)
Gradle構(gòu)建規(guī)則
Java 類合并
集中編譯 java/ 目錄中的所有源代碼以生成單一的輸出
注:對于給定的構(gòu)建變體,如果找到兩個或兩個以上定義同一 Java 類的源集目錄,Gradle 就會引發(fā)一個構(gòu)建錯誤。例如,在構(gòu)建調(diào)試 APK 時,您不能同時定義 src/debug/Utility.java and src/main/Utility.java。這是因為 Gradle 會在構(gòu)建過程中檢查這兩個目錄并引發(fā)“duplicate class”錯誤。如果您需要針對不同的構(gòu)建類型構(gòu)建不同版本的 Utility.java,您可以讓每個構(gòu)建類型定義自己的文件版本,而不將其包含在 main/ 源集中。
清單文件合并
合并工具通過基于每個清單文件的優(yōu)先級順序地合并它們將所有清單文件組合成一個文件,如圖:

清單文件合并規(guī)則:
- <manifest>元素中的屬性從不會合并在一起 - 只使用來自最高優(yōu)先級清單的屬性。
- <uses-feature>和<uses-library>元素中的android:required屬性使用OR合并,因此如果存在沖突,則應(yīng)用“true”,并且始終包括一個清單所需的功能部件或庫。
- <uses-sdk>元素中的屬性始終使用優(yōu)先級更高的清單中的值,但以下情況除外:
- 當(dāng)優(yōu)先級較低的清單具有更高的
minSdkVersion值時,會發(fā)生錯誤,除非您應(yīng)用 overrideLibrary
合并規(guī)則。
main的清單文件如下定義時,其他清單文件定義的minSdkVersion比main中的還低時就不會報錯:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app"
xmlns:tools="http://schemas.android.com/tools">
<uses-sdk android:targetSdkVersion="22" android:minSdkVersion="2"
tools:overrideLibrary="com.example.lib1, com.example.lib2"/>
...
- 當(dāng)優(yōu)先級較低的清單的
targetSdkVersion值較低時,合并工具使用來自較高優(yōu)先級清單的值,但它還會添加必要的系統(tǒng)權(quán)限,以確保導(dǎo)入的庫繼續(xù)正常工作(對于其中較高的Android版本已經(jīng)增加了許可限制)。有關(guān)此行為的詳細(xì)信息,請參閱 implicit system permissions。
- <intent-filter>元素永遠(yuǎn)不會在清單之間匹配。每個都被視為唯一,并添加到合并清單中的公共父元素。
- 對于屬性之間的所有其他沖突,您將收到錯誤,并且必須通過在更高優(yōu)先級的清單文件中添加特殊屬性來指示合并工具如何解決它(請參閱merge rule markers)
| Element | Merge policy | Match key |
|---|---|---|
| <action> | Merge | android:name attribute |
| <activity> | Merge | android:name attribute |
| <application> | Merge | There is only one per <manifest> |
| <category> | Merge | android:name attribute |
| <data> | Merge | There is only one per <intent-filter> |
| <grant-uri-permission> | Merge | There is only one per <provider> |
| <instrumentation> | Merge | android:name attribute |
| <intent-filter> | Keep | No matching; several declarations within the parent element are allowed |
| <manifest> | Merge children only | There is only one per file |
| <meta-data> | Merge | android:name attribute |
| <path-permission> | Merge | There is only one per <provider> |
| <permission-group> | Merge | android:name attribute |
| <permission> | Merge | android:name attribute |
| <permission-tree> | Merge | android:name attribute |
| <provider> | Merge | android:name attribute |
| <receiver> | Merge | android:name attribute |
| <screen> | Merge | android:screenSize attribute |
| <service> | Merge | android:name attribute |
| <supports-gl-texture> | Merge | android:name attribute |
| <supports-screen> | Merge | There is only one per <manifest> |
| <uses-configuration> | Merge | There is only one per <manifest> |
| <uses-feature> | Merge | android:name attribute (if not present, then the android:glEsVersion attribute) |
| <uses-library> | Merge | android:name attribute |
| <uses-permission> | Merge | android:name attribute |
| <uses-sdk> | Merge | There is only one per <manifest> |
| Custom elements | Merge | No matching; these are unknown to the merger tool so they are always included in the merged manifest |
標(biāo)記合并規(guī)則
node
- tools:node="merge",默認(rèn)行為
低優(yōu)先級manifest:
<activity android:name=”com.example.ActivityOne”
android:windowSoftInputMode=”stateUnchanged”>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
高優(yōu)先級manifest:
<activity android:name=”com.example.ActivityOne”
android:screenOrientation=”portrait”
tools:node="merge”>
</activity>
合并后的manifest:
<activity android:name=”com.example.ActivityOne”
android:screenOrientation=”portrait”
android:windowSoftInputMode=”stateUnchanged”>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
- tools:node="merge-only-attributes"
低優(yōu)先級manifest:
<activity android:name=”com.example.ActivityOne”
android:windowSoftInputMode=”stateUnchanged”>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<data android:type="image/*" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
高優(yōu)先級manifest:
<activity android:name=”com.example.ActivityOne”
android:screenOrientation=”portrait”
tools:node="merge-only-attributes”>
</activity>
合并后的manifest:
<activity android:name=”com.example.ActivityOne”
android:screenOrientation=”portrait”
android:windowSoftInputMode=”stateUnchanged”>
</activity>
- tools:node="remove"
低優(yōu)先級manifest:
<activity-alias android:name=”com.example.alias”>
<meta-data android:name=”cow”
android:value=”@string/moo”/>
<meta-data android:name=”duck”
android:value=”@string/quack”/>
</activity-alias>
高優(yōu)先級manifest:
<activity-alias android:name=”com.example.alias”>
<meta-data android:name=”cow”
tools:node=”remove”/>
</activity-alias>
合并后的manifest:
<activity-alias android:name=”com.example.alias”>
<meta-data android:name=”duck”
android:value=”@string/quack”/>
</activity-alias>
- tools:node="removeAll"
低優(yōu)先級manifest:
<activity-alias android:name=”com.example.alias”>
<meta-data android:name=”cow”
android:value=”@string/moo”/>
<meta-data android:name=”duck”
android:value=”@string/quack”/>
</activity-alias>
高優(yōu)先級manifest:
<activity-alias android:name=”com.example.alias”>
<meta-data tools:node=”removeAll”/>
</activity-alias>
合并后的manifest:
<activity-alias android:name=”com.example.alias”>
</activity-alias>
- tools:node="replace"
低優(yōu)先級manifest:
<activity-alias android:name=”com.example.alias”>
<meta-data android:name=”cow”
android:value=”@string/moo”/>
<meta-data android:name=”duck”
android:value=”@string/quack”/>
</activity-alias>
高優(yōu)先級manifest:
<activity-alias android:name=”com.example.alias”
tools:node=”replace”>
<meta-data android:name=”fox”
android:value=”@string/dingeringeding”/>
</activity-alias>
合并后的manifest:
<activity-alias android:name=”com.example.alias”>
<meta-data android:name=”fox”
android:value=”@string/dingeringeding”/>
</activity-alias>
- tools:node="strict",如果優(yōu)先級較低的清單只是包含一個額外的屬性,都會構(gòu)建失?。ǘJ(rèn)行為將額外的屬性添加到合并的清單中)。
低優(yōu)先級manifest:
<activity android:name=”com.example.ActivityOne”
android:windowSoftInputMode=”stateUnchanged”>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
高優(yōu)先級manifest:
<activity android:name=”com.example.ActivityOne”
android:screenOrientation=”portrait”
tools:node="strict”>
</activity>
合并后的manifest:報錯
Attribute
- tools:remove="attr, ..."
低優(yōu)先級manifest:
<activity android:name=”com.example.ActivityOne”
android:windowSoftInputMode=”stateUnchanged”>
高優(yōu)先級manifest:
<activity android:name=”com.example.ActivityOne”
android:screenOrientation=”portrait”
tools:remove=”android:windowSoftInputMode”>
合并后的manifest:
<activity android:name=”com.example.ActivityOne”
android:screenOrientation=”portrait”>
- tools:replace="attr, ..."
低優(yōu)先級manifest:
<activity android:name=”com.example.ActivityOne”
android:theme=”@oldtheme”
android:exported=”false”
android:windowSoftInputMode=”stateUnchanged”>
高優(yōu)先級manifest:
<activity android:name=”com.example.ActivityOne”
android:theme=”@newtheme”
android:exported=”true”
android:screenOrientation=”portrait”
tools:replace=”android:theme,android:exported”>
合并后的manifest:
<activity android:name=”com.example.ActivityOne”
android:theme=”@newtheme”
android:exported=”true”
android:screenOrientation=”portrait”
android:windowSoftInputMode=”stateUnchanged”>
- tools:strict="attr, ...",當(dāng)優(yōu)先級較低的清單中的這些屬性在較高優(yōu)先級清單中不完全匹配時,則構(gòu)建失敗。
低優(yōu)先級manifest:
<activity android:name=”com.example.ActivityOne”
android:screenOrientation=”landscape”>
</activity>
高優(yōu)先級manifest:
<activity android:name=”com.example.ActivityOne”
android:screenOrientation=”portrait”
tools:strict="android:screenOrientation”>
</activity>
合并后的manifest:報錯
tools:selector
將合并規(guī)則標(biāo)記僅應(yīng)用于特定導(dǎo)入的庫。
<permission android:name="permissionOne"
tools:node="remove"
tools:selector="com.example.lib1">
如何查看清單文件合并沖突?

如果您想查看合并的完整日志,您可以在模塊的build / outputs / logs /目錄中找到名為manifest-merger-buildVariant-report.txt的日志文件
values合并
例如存在兩個 strings.xml 文件,將按照上述列表中的相同順序指定優(yōu)先級。也就是說,在構(gòu)建類型源集中的文件中定義的值將會替換產(chǎn)品風(fēng)味中同一文件中定義的值,依此類推。
res和asset合并
如果兩個或兩個以上的源集中定義有同名資源,將按照上述列表中的相同順序指定優(yōu)先級。
庫模塊依賴項合并
Gradle 會為隨庫模塊依賴項包含的資源和清單分配最低的優(yōu)先級
如何添加依賴?
直接依賴項分類
模塊依賴項
// Dependency on the "mylibrary" module from this project
compile project(":mylibrary")
遠(yuǎn)程依賴項
// Remote binary dependency
compile 'com.android.support:appcompat-v7:25.1.0'
本地依賴項
// Local binary dependency
compile fileTree(dir: 'libs', include: ['*.jar'])
如何生成依賴項樹?
demoDebug
\--- com.android.support:appcompat-v7:24.2.1
+--- com.android.support:support-v4:24.2.1
| +--- com.android.support:support-compat:24.2.1
| | \--- LOCAL: internal_impl-24.2.1.jar
| +--- com.android.support:support-media-compat:24.2.1
| | +--- LOCAL: internal_impl-24.2.1.jar
| | \--- com.android.support:support-compat:24.2.1
| | \--- LOCAL: internal_impl-24.2.1.jar
| +--- com.android.support:support-core-utils:24.2.1
| | +--- LOCAL: internal_impl-24.2.1.jar
| | \--- com.android.support:support-compat:24.2.1
| | \--- LOCAL: internal_impl-24.2.1.jar
| +--- com.android.support:support-core-ui:24.2.1
| | +--- LOCAL: internal_impl-24.2.1.jar
| | \--- com.android.support:support-compat:24.2.1
| | \--- LOCAL: internal_impl-24.2.1.jar
| \--- com.android.support:support-fragment:24.2.1
| +--- LOCAL: internal_impl-24.2.1.jar
| +--- com.android.support:support-compat:24.2.1
| | \--- LOCAL: internal_impl-24.2.1.jar
| +--- com.android.support:support-media-compat:24.2.1
| | +--- LOCAL: internal_impl-24.2.1.jar
| | \--- com.android.support:support-compat:24.2.1
| | \--- LOCAL: internal_impl-24.2.1.jar
| +--- com.android.support:support-core-ui:24.2.1
| | +--- LOCAL: internal_impl-24.2.1.jar
| | \--- com.android.support:support-compat:24.2.1
| | \--- LOCAL: internal_impl-24.2.1.jar
| \--- com.android.support:support-core-utils:24.2.1
| +--- LOCAL: internal_impl-24.2.1.jar
| \--- com.android.support:support-compat:24.2.1
| \--- LOCAL: internal_impl-24.2.1.jar
+--- com.android.support:support-vector-drawable:24.2.1
| \--- com.android.support:support-compat:24.2.1
| \--- LOCAL: internal_impl-24.2.1.jar
\--- com.android.support:animated-vector-drawable:24.2.1
\--- com.android.support:support-vector-drawable:24.2.1
\--- com.android.support:support-compat:24.2.1
\--- LOCAL: internal_impl-24.2.1.jar
demoDebugAndroidTest
\--- com.android.support.test.espresso:espresso-core:2.2.2
+--- com.android.support.test:rules:0.5
| \--- com.android.support.test:runner:0.5
| \--- com.android.support.test:exposed-instrumentation-api-publish:0.5
+--- com.android.support.test:runner:0.5
| \--- com.android.support.test:exposed-instrumentation-api-publish:0.5
\--- com.android.support.test.espresso:espresso-idling-resource:2.2.2
demoDebugUnitTest
No dependencies
demoRelease
......
demoReleaseUnitTest
No dependencies
- 點擊 IDE 窗口右側(cè)的 Gradle
- 導(dǎo)航至 MyApplication > Tasks > android 并雙擊 androidDependencies。
- 要查看報告,請單擊 IDE 窗口底部的 Gradle Console
如需了解在 Gradle 中管理依賴項的詳細(xì)信息,請參閱《Gradle 用戶指南》中的依賴項管理基礎(chǔ)知識
如何配置依賴項?
compile
Gradle 將此配置的依賴項添加到類路徑和應(yīng)用的 APK。這是默認(rèn)配置。
apk
指定 Gradle 需要將其與應(yīng)用的 APK 一起打包的運行時依賴項。您可以將此配置與 JAR 二進制依賴項一起使用,而不能與其他庫模塊依賴項或 AAR 二進制依賴項一起使用。
provided
指定 Gradle 不與應(yīng)用的 APK 一起打包的編譯時依賴項。如果運行時無需此依賴項,這將有助于縮減 APK 的大小。您可以將此配置與 JAR 二進制依賴項一起使用,而不能與其他庫模塊依賴項或 AAR 二進制依賴項一起使用。
如何使用Gradle簽名打包?
- 創(chuàng)建密鑰
- 創(chuàng)建私鑰
- 將簽名配置添加到模塊級 build.gradle 文件中:
...
android {
...
defaultConfig {...}
signingConfigs {
release {
storeFile file("myreleasekey.keystore")
storePassword "password"
keyAlias "MyReleaseKey"
keyPassword "password"
}
}
buildTypes {
release {
...
signingConfig signingConfigs.release
}
}
}
注:將發(fā)布密鑰和密鑰庫的密碼放在構(gòu)建文件中并不安全。作為替代方案,您可以將此構(gòu)建文件配置為通過環(huán)境變量獲取這些密碼,或讓構(gòu)建流程提示您輸入這些密碼。
如何以安全地方式獲取密碼?
過環(huán)境變量獲取這些密碼
storePassword System.getenv("KSTOREPWD")
keyPassword System.getenv("KEYPWD")
從命令行調(diào)用此構(gòu)建時提示您輸入這些密碼
storePassword System.console().readLine("\nKeystore password: ")
keyPassword System.console().readLine("\nKey password: ")