Android Gradle使用技巧-gradle使用詳細(xì)介紹
Android Gradle使用詳解(一)--設(shè)置applicationId
利用 Android Studio 中的 Gradle 構(gòu)建系統(tǒng),您可以輕松地將外部二進(jìn)制文件或其他庫(kù)模塊作為依賴項(xiàng)添加到您的 build 中。這些依賴項(xiàng)可位于您的計(jì)算機(jī)上或遠(yuǎn)程代碼庫(kù)中,并且它們聲明的所有傳遞依賴項(xiàng)也會(huì)自動(dòng)包含在內(nèi)。
注意:指定依賴項(xiàng)時(shí),不應(yīng)使用動(dòng)態(tài)版本號(hào),如 'com.android.tools.build:gradle:3.+'。使用此功能可能會(huì)導(dǎo)致意外的版本更新和難以解析版本差異。
一、依賴項(xiàng)類型
如需向您的項(xiàng)目添加依賴項(xiàng),請(qǐng)?jiān)?build.gradle 文件的 dependencies 代碼塊中指定依賴項(xiàng)配置,如 implementation。
例如,應(yīng)用模塊的以下 build.gradle 文件包含三種不同類型的依賴項(xiàng):
apply plugin: 'com.android.application'
android { ... }
dependencies {
// 對(duì)本地庫(kù)模塊的依賴
implementation project(":mylibrary")
//或者
implementation project(path: ":mylibrary")
// 對(duì)本地二進(jìn)制文件的依賴
implementation fileTree(dir: 'libs', include: ['*.jar'])
// 對(duì)遠(yuǎn)程二進(jìn)制文件的依賴
implementation 'com.example.android:app-magic:12.3'
}
其中每種依賴項(xiàng)配置都請(qǐng)求不同種類的庫(kù)依賴項(xiàng),如下所示:
1、本地庫(kù)模塊依賴項(xiàng)
implementation project(':mylibrary')
這聲明了對(duì)一個(gè)名為“mylibrary”(此名稱必須與在您的 settings.gradle 文件中使用 include: 定義的庫(kù)名稱相符)的 Android 庫(kù)模塊的依賴關(guān)系。在構(gòu)建您的應(yīng)用時(shí),構(gòu)建系統(tǒng)會(huì)編譯該庫(kù)模塊,并將生成的編譯內(nèi)容打包到 APK 中。
2、本地二進(jìn)制文件依賴項(xiàng)
implementation fileTree(dir: 'libs', include: ['*.jar'])
Gradle 聲明了對(duì)項(xiàng)目的 module_name/libs/ 目錄中 JAR 文件的依賴關(guān)系(因?yàn)?Gradle 會(huì)讀取 build.gradle 文件的相對(duì)路徑)。
或者,您也可以按如下方式指定各個(gè)文件:
implementation files('libs/foo.jar', 'libs/bar.jar')
3、遠(yuǎn)程二進(jìn)制文件依賴項(xiàng)
implementation 'com.example.android:app-magic:12.3'
這實(shí)際上是以下代碼的簡(jiǎn)寫(xiě)形式:
implementation group: 'com.example.android', name: 'app-magic', version: '12.3'
這聲明了對(duì)“com.example.android”命名空間組內(nèi)的 12.3 版“app-magic”庫(kù)的依賴關(guān)系。
注意:此類遠(yuǎn)程依賴項(xiàng)要求您聲明適當(dāng)?shù)倪h(yuǎn)程代碼庫(kù),Gradle 應(yīng)在其中查找相應(yīng)的庫(kù)。如果本地不存在相應(yīng)的庫(kù),則當(dāng) build 需要它時(shí)(例如,當(dāng)您點(diǎn)擊 Sync Project with Gradle Files 圖標(biāo)或運(yùn)行 build 時(shí)),Gradle 會(huì)從遠(yuǎn)程站點(diǎn)提取它。
二、依賴項(xiàng)配置
在 dependencies 代碼塊內(nèi),您可以從多種不同的依賴項(xiàng)配置中選擇其一(如上面所示的 implementation)來(lái)聲明庫(kù)依賴項(xiàng)。每種依賴項(xiàng)配置都向 Gradle 提供了有關(guān)如何使用該依賴項(xiàng)的不同說(shuō)明。下表介紹了您可以對(duì) Android 項(xiàng)目中的依賴項(xiàng)使用的各種配置。此表還將這些配置與自 Android Gradle 插件 3.0.0 起棄用的配置進(jìn)行了比較
| 新配置 | 已棄用配置 | 行為 |
|---|---|---|
| implementation | compile | Gradle 會(huì)將依賴項(xiàng)添加到編譯類路徑,并將依賴項(xiàng)打包到構(gòu)建輸出。不過(guò),當(dāng)您的模塊配置 implementation 依賴項(xiàng)時(shí),會(huì)讓 Gradle 了解您不希望該模塊在編譯時(shí)將該依賴項(xiàng)泄露給其他模塊。也就是說(shuō),其他模塊只有在運(yùn)行時(shí)才能使用該依賴項(xiàng)。 注意:使用此依賴項(xiàng)配置代替 api 或 compile(已棄用)可以顯著縮短構(gòu)建時(shí)間,因?yàn)檫@樣可以減少構(gòu)建系統(tǒng)需要重新編譯的模塊數(shù)。例如,如果 implementation 依賴項(xiàng)更改了其 API,Gradle 只會(huì)重新編譯該依賴項(xiàng)以及直接依賴于它的模塊。大多數(shù)應(yīng)用和測(cè)試模塊都應(yīng)使用此配置。 |
| api | compile | Gradle 會(huì)將依賴項(xiàng)添加到編譯類路徑和構(gòu)建輸出。當(dāng)一個(gè)模塊包含 api 依賴項(xiàng)時(shí),會(huì)讓 Gradle 了解該模塊要以傳遞方式將該依賴項(xiàng)導(dǎo)出到其他模塊,以便這些模塊在運(yùn)行時(shí)和編譯時(shí)都可以使用該依賴項(xiàng)。 注意:此配置的行為類似于 compile(現(xiàn)已棄用),但使用它時(shí)應(yīng)格外小心,只能對(duì)您需要以傳遞方式導(dǎo)出到其他上游消費(fèi)者的依賴項(xiàng)使用它。這是因?yàn)椋绻?api 依賴項(xiàng)更改了其外部 API,Gradle 會(huì)在編譯時(shí)重新編譯所有有權(quán)訪問(wèn)該依賴項(xiàng)的模塊。因此,擁有大量的 api 依賴項(xiàng)會(huì)顯著增加構(gòu)建時(shí)間。除非要將依賴項(xiàng)的 API 公開(kāi)給單獨(dú)的模塊,否則庫(kù)模塊應(yīng)改用 implementation 依賴項(xiàng)。 |
| compileOnly | provided | Gradle 只會(huì)將依賴項(xiàng)添加到編譯類路徑(也就是說(shuō),不會(huì)將其添加到構(gòu)建輸出)。如果您創(chuàng)建 Android 模塊時(shí)在編譯期間需要相應(yīng)依賴項(xiàng),但它在運(yùn)行時(shí)可有可無(wú),此配置會(huì)很有用。如果您使用此配置,那么您的庫(kù)模塊必須包含一個(gè)運(yùn)行時(shí)條件,用于檢查是否提供了相應(yīng)依賴項(xiàng),然后適當(dāng)?shù)馗淖冊(cè)撃K的行為,以使該模塊在未提供相應(yīng)依賴項(xiàng)的情況下仍可正常運(yùn)行。這樣做不會(huì)添加不重要的瞬時(shí)依賴項(xiàng),因而有助于減小最終 APK 的大小。注意:您不能將 compileOnly 配置與 AAR 依賴項(xiàng)配合使用。 |
| runtimeOnly | apk | Gradle 只會(huì)將依賴項(xiàng)添加到構(gòu)建輸出,以便在運(yùn)行時(shí)使用。也就是說(shuō),不會(huì)將其添加到編譯類路徑。 |
| annotationProcessor | compile | 如需添加對(duì)作為注釋處理器的庫(kù)的依賴關(guān)系,您必須使用 annotationProcessor 配置將其添加到注釋處理器類路徑。這是因?yàn)椋褂么伺渲每梢詫⒕幾g類路徑與注釋處理器類路徑分開(kāi),從而提高構(gòu)建性能。如果 Gradle 在編譯類路徑上找到注釋處理器,則會(huì)禁用避免編譯功能,這樣會(huì)對(duì)構(gòu)建時(shí)間產(chǎn)生負(fù)面影響(Gradle 5.0 及更高版本會(huì)忽略在編譯類路徑上找到的注釋處理器)。如果 JAR 文件包含以下文件,則 Android Gradle 插件會(huì)假定依賴項(xiàng)是注釋處理器:META-INF/services/javax.annotation.processing.Processor。如果插件檢測(cè)到編譯類路徑上包含注釋處理器,則會(huì)生成構(gòu)建錯(cuò)誤。 |
| lintChecks | 使用此配置可以添加您希望 Gradle 在構(gòu)建項(xiàng)目時(shí)執(zhí)行的 lint 檢查.注意:使用 Android Gradle 插件 3.4.0 及更高版本時(shí),此依賴項(xiàng)配置不再將 lint 檢查打包在 Android 庫(kù)項(xiàng)目中。如需將 lint 檢查依賴項(xiàng)包含在 AAR 庫(kù)中,請(qǐng)使用下面介紹的 lintPublish 配置。 | |
| lintPublish | 在 Android 庫(kù)項(xiàng)目中使用此配置可以添加您希望 Gradle 編譯成 lint.jar 文件并打包在 AAR 中的 lint 檢查。這會(huì)使得使用 AAR 的項(xiàng)目也應(yīng)用這些 lint 檢查。如果您之前使用 lintChecks 依賴項(xiàng)配置將 lint 檢查包含在已發(fā)布的 AAR 中,則需要遷移這些依賴項(xiàng)以改用 lintPublish 配置。 |
1.為構(gòu)建變體添加依賴
以上配置會(huì)將依賴項(xiàng)應(yīng)用于所有構(gòu)建變體。如果您只想為特定的構(gòu)建變體源代碼集或測(cè)試源代碼集聲明依賴項(xiàng),則必須將配置名稱的首字母大寫(xiě),并在其前面加上構(gòu)建變體或測(cè)試源代碼集的名稱作為前綴。
例如,如需只向“free”產(chǎn)品變種添加 implementation 依賴項(xiàng)(使用遠(yuǎn)程二進(jìn)制文件依賴項(xiàng)),請(qǐng)使用如下所示的代碼:
dependencies {
freeImplementation 'com.google.firebase:firebase-ads:9.8.0'
}
不過(guò),如果您想為將產(chǎn)品變種和構(gòu)建類型組合在一起的變體添加依賴項(xiàng),就必須在 configurations 代碼塊中初始化配置名稱。以下示例向“freeDebug”構(gòu)建變體添加了 runtimeOnly 依賴項(xiàng)(使用本地二進(jìn)制文件依賴項(xiàng)):
configurations {
// 為freeDebugRuntimeOnly依賴項(xiàng)初始化一個(gè)占位符配置。
freeDebugRuntimeOnly {}
}
dependencies {
freeDebugRuntimeOnly fileTree(dir: 'libs', include: ['*.jar'])
}
如需為本地測(cè)試和插樁測(cè)試添加 implementation 依賴項(xiàng),請(qǐng)使用如下所示的代碼:
dependencies {
// 僅為本地測(cè)試添加遠(yuǎn)程二進(jìn)制依賴項(xiàng)。
testImplementation 'junit:junit:4.12'
// 僅為已檢測(cè)的測(cè)試APK添加遠(yuǎn)程二進(jìn)制依賴項(xiàng)。
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
不過(guò),某些配置在這種情況下沒(méi)有意義。例如,因?yàn)槠渌K不能依賴于 androidTest,所以如果您使用 androidTestApi 配置,會(huì)收到以下警告:
WARNING: Configuration 'androidTestApi' is obsolete and has been replaced with
'androidTestImplementation'.
2.使用變體感知型依賴項(xiàng)管理機(jī)制
Android 插件 3.0.0 及更高版本包含一種新的依賴項(xiàng)機(jī)制,該機(jī)制可在使用庫(kù)時(shí)自動(dòng)匹配變體。這意味著,應(yīng)用的 debug 變體會(huì)自動(dòng)使用庫(kù)的 debug 變體,依此類推。在使用變種時(shí),這種機(jī)制也同樣適用 - 應(yīng)用的 freeDebug 變體將使用庫(kù)的 freeDebug 變體。
Android 插件 3.0.0 及更高版本包含一種新的依賴項(xiàng)機(jī)制,該機(jī)制可在使用庫(kù)時(shí)自動(dòng)匹配變體。這意味著,應(yīng)用的 debug 變體會(huì)自動(dòng)使用庫(kù)的 debug 變體,依此類推。在使用變種時(shí),這種機(jī)制也同樣適用 - 應(yīng)用的 freeDebug 變體將使用庫(kù)的 freeDebug 變體。
為了讓插件準(zhǔn)確匹配變體,您需要在無(wú)法進(jìn)行直接匹配的情況下提供匹配回退機(jī)制。不妨假設(shè)您的應(yīng)用配置了一個(gè)名為“staging”的構(gòu)建類型,但該應(yīng)用的一個(gè)庫(kù)依賴項(xiàng)沒(méi)有進(jìn)行相應(yīng)配置。當(dāng)插件嘗試構(gòu)建“staging”版本的應(yīng)用時(shí),它不知道要使用哪個(gè)版本的庫(kù),因此您將看到一條與以下內(nèi)容類似的錯(cuò)誤消息:
Error:Failed to resolve: Could not resolve project :mylibrary.Required by: project :app
3.解決與變體匹配相關(guān)的構(gòu)建錯(cuò)誤
- 編譯錯(cuò)誤原因:您的應(yīng)用包含庫(kù)依賴項(xiàng)不包含的構(gòu)建類型
例如,您的應(yīng)用包含“staging”版本類型,但依賴項(xiàng)僅包含“debug”和“release”版本類型。
解決方案:使用 matchingFallbacks 為給定的構(gòu)建類型指定替代匹配,如下所示:android { buildTypes { debug {} release {} staging { //指定后備的構(gòu)建類型的排序列表,當(dāng)依賴項(xiàng)不包含“ staging”構(gòu)建類型。您可以指定一個(gè),然后插件選擇第一個(gè)可用的構(gòu)建類型添在依賴項(xiàng)。 matchingFallbacks = ['debug', 'qa', 'release'] } }
}
```
- 編譯錯(cuò)誤原因:對(duì)于應(yīng)用及其庫(kù)依賴項(xiàng)中均存在的給定變種維度,您的應(yīng)用包含庫(kù)不包含的變種。
例如,您的應(yīng)用及其庫(kù)依賴項(xiàng)都包含“tier”變種維度。不過(guò),應(yīng)用中的“tier”維度包含“free”和“paid”變種,但依賴項(xiàng)中的同一維度僅包含“demo”和“paid”變種。
解決方案:使用 matchingFallbacks 為應(yīng)用的“free”產(chǎn)品變種指定替代匹配,如下所示:android { defaultConfig{ // 不要在defaultConfig塊中配置matchFallbacks。相反,您必須在productFlavors塊中添加他; } flavorDimensions 'tier' productFlavors { paid { dimension 'tier' // 因?yàn)橐蕾図?xiàng)已在其依賴項(xiàng)中包含“付費(fèi)”的形式“層級(jí)”維度,您無(wú)需提供后備列表代表“付費(fèi)”變體。 } free { dimension 'tier' matchingFallbacks = ['demo', 'trial'] } }
}
```
- 編譯錯(cuò)誤原因:庫(kù)依賴項(xiàng)包含您的應(yīng)用不包含的變種維度
例如,庫(kù)依賴項(xiàng)包含“minApi”維度的變種,但您的應(yīng)用僅包含“tier”維度的變種。因此,當(dāng)您要構(gòu)建“freeDebug”版本的應(yīng)用時(shí),插件不知道是使用“minApi23Debug”還是“minApi18Debug”版本的依賴項(xiàng)。
解決方案:在 defaultConfig 代碼塊中使用 missingDimensionStrategy 指定插件應(yīng)從每個(gè)缺失維度中選擇的默認(rèn)變種,如以下示例所示。您也可以替換在 productFlavors 代碼塊中的選擇,讓每一個(gè)變種都可以為缺失維度指定一個(gè)不同的匹配策略。android { defaultConfig{ // 指定插件應(yīng)嘗試從中使用的變體的排序列表給定的尺寸下面告訴插件,當(dāng)遇到包含“ minApi”維的依賴項(xiàng),應(yīng)選擇“ minApi18”變體。您可以包括其他變體名稱以提供對(duì)維度的后備列表進(jìn)行排序。 missingDimensionStrategy 'minApi', 'minApi18', 'minApi23' // 您應(yīng)該為每個(gè)屬性指定一個(gè)missingDimensionStrategy屬性存在于本地依賴項(xiàng)中但不存在于您的應(yīng)用程序中。 missingDimensionStrategy 'abi', 'x86', 'arm64' } flavorDimensions 'tier' productFlavors { free { dimension 'tier' // 您可以覆蓋產(chǎn)品變體的默認(rèn)選擇通過(guò)配置另一個(gè)missingDimensionStrategy屬性進(jìn)行級(jí)別用于“ minApi”維度。 missingDimensionStrategy 'minApi', 'minApi23', 'minApi18' } paid {} }
}
```
4.排除傳遞依賴項(xiàng)
隨著應(yīng)用的范圍不斷擴(kuò)大,它可能會(huì)包含許多依賴項(xiàng),包括直接依賴項(xiàng)和傳遞依賴項(xiàng)(應(yīng)用中導(dǎo)入的庫(kù)所依賴的庫(kù))。如需排除不再需要的傳遞依賴項(xiàng),您可以使用 exclude 關(guān)鍵字,如下所示:
dependencies {
implementation('some-library') {
exclude group: 'com.example.imgtools', module: 'native'
}
}
三、遠(yuǎn)程代碼庫(kù)
當(dāng)您的依賴項(xiàng)不是本地庫(kù)或文件樹(shù)時(shí),Gradle 會(huì)在 build.gradle 文件的 repositories 代碼塊中指定的所有在線代碼庫(kù)中查找相關(guān)文件。各個(gè)代碼庫(kù)的列出順序決定了 Gradle 在這些代碼庫(kù)中搜索各個(gè)項(xiàng)目依賴項(xiàng)的順序。例如,如果從代碼庫(kù) A 和 B 均可獲得某個(gè)依賴項(xiàng),而您先列出了代碼庫(kù) A,則 Gradle 會(huì)從代碼庫(kù) A 下載該依賴項(xiàng)。
默認(rèn)情況下,新的 Android Studio 項(xiàng)目會(huì)將 Google 的 Maven 代碼庫(kù)和 JCenter 指定為項(xiàng)目的頂級(jí) build.gradle 文件中的代碼庫(kù)位置,如下所示:
allprojects {
repositories {
google()
jcenter()
}
}
如果您要從 Maven 中央代碼庫(kù)獲取某些內(nèi)容,則添加 mavenCentral();對(duì)于本地代碼庫(kù),則使用 mavenLocal():
allprojects {
repositories {
google()
jcenter()
mavenCentral()
mavenLocal()
}
}
或者,您也可以按如下方式聲明特定的 Maven 或 Ivy 代碼庫(kù):
allprojects {
repositories {
maven {
url "https://repo.example.com/maven2"
}
maven {
url "file://local/repo/"
}
ivy {
url "https://repo.example.com/ivy"
}
}
}
四、依賴項(xiàng)順序
依賴項(xiàng)的列出順序指明了每個(gè)庫(kù)的優(yōu)先級(jí):第一個(gè)庫(kù)的優(yōu)先級(jí)高于第二個(gè),第二個(gè)庫(kù)的優(yōu)先級(jí)高于第三個(gè),依此類推。在合并資源或?qū)⑶鍐卧貜膸?kù)中合并到應(yīng)用中時(shí),此順序很重要。
例如,如果您的項(xiàng)目聲明以下內(nèi)容:
- 依賴 LIB_A 和 LIB_B(按此順序)
- LIB_A 依賴于 LIB_C 和 LIB_D(按此順序)
- LIB_B 也依賴于 LIB_C
那么,扁平型依賴項(xiàng)順序?qū)⑷缦滤荆?/li>
- LIB_A
- LIB_D
- LIB_B
- LIB_C
這可以確保 LIB_A 和 LIB_B 都可以替換 LIB_C;并且 LIB_D 的優(yōu)先級(jí)仍高于 LIB_B,因?yàn)?LIB_A(依賴前者)的優(yōu)先級(jí)高于 LIB_B。
五、查看模塊依賴項(xiàng)
一些直接依賴項(xiàng)可能具有自己的依賴項(xiàng)。此類依賴項(xiàng)稱為“傳遞依賴項(xiàng)”。Gradle 將會(huì)自動(dòng)為您收集并添加這些傳遞依賴項(xiàng),無(wú)需您手動(dòng)逐一加以聲明。Android Plugin for Gradle 提供了一項(xiàng)任務(wù),用來(lái)列出 Gradle 為給定模塊解析的依賴項(xiàng)。
對(duì)于每個(gè)模塊,報(bào)告還會(huì)根據(jù)構(gòu)建變體、測(cè)試源代碼集和類路徑對(duì)依賴項(xiàng)進(jìn)行分組。下面是一個(gè)應(yīng)用模塊的依賴項(xiàng)示例報(bào)告,其中按該模塊的調(diào)試構(gòu)建變體的運(yùn)行時(shí)類路徑和該模塊的插樁測(cè)試源代碼集的編譯類路徑對(duì)依賴項(xiàng)進(jìn)行了分組。
如需運(yùn)行該任務(wù),請(qǐng)按以下步驟操作:
- 依次選擇 View > Tool Windows > Gradle(或點(diǎn)擊工具窗口欄中的 Gradle 圖標(biāo))。
- 依次展開(kāi) AppName > Tasks > android,然后雙擊 androidDependencies。Gradle 執(zhí)行該任務(wù)后,系統(tǒng)應(yīng)該會(huì)打開(kāi) Run 窗口以顯示輸出。
顯示如下:
debugRuntimeClasspath - Dependencies for runtime/packaging
+--- :mylibrary (variant: debug)
+--- com.google.android.material:material:1.0.0@aar
+--- androidx.appcompat:appcompat:1.0.2@aar
+--- androidx.constraintlayout:constraintlayout:1.1.3@aar
+--- androidx.fragment:fragment:1.0.0@aar
+--- androidx.vectordrawable:vectordrawable-animated:1.0.0@aar
+--- androidx.recyclerview:recyclerview:1.0.0@aar
+--- androidx.legacy:legacy-support-core-ui:1.0.0@aar
...
debugAndroidTest
debugAndroidTestCompileClasspath - Dependencies for compilation
+--- androidx.test.ext:junit:1.1.0@aar
+--- androidx.test.espresso:espresso-core:3.1.1@aar
+--- androidx.test:runner:1.1.1@aar
+--- junit:junit:4.12@jar
...
六、修復(fù)依賴項(xiàng)解析錯(cuò)誤
當(dāng)您向應(yīng)用項(xiàng)目添加多個(gè)依賴項(xiàng)時(shí),這些直接和傳遞依賴項(xiàng)可能會(huì)相互沖突。Android Gradle 插件會(huì)嘗試妥善解決這些沖突,但有些沖突可能會(huì)導(dǎo)致編譯時(shí)或運(yùn)行時(shí)錯(cuò)誤。
為幫助您調(diào)查是哪些依賴項(xiàng)導(dǎo)致了錯(cuò)誤,請(qǐng)如上檢查您的應(yīng)用的依賴項(xiàng)樹(shù),從中查找多次出現(xiàn)的依賴項(xiàng)或版本沖突的依賴項(xiàng)。
如果無(wú)法輕松識(shí)別重復(fù)的依賴項(xiàng),請(qǐng)嘗試使用 Android Studio 的界面搜索包含重復(fù)類的依賴項(xiàng),具體操作步驟如下:
- 從菜單欄中依次選擇 Navigate > Class。
- 在彈出式搜索對(duì)話框中,確保已勾選 Include non-project items 旁邊的框。
- 輸入出現(xiàn)在構(gòu)建錯(cuò)誤中的類的名稱。
- 檢查結(jié)果以查找包含該類的依賴項(xiàng)。
下面幾部分介紹您可能會(huì)遇到的不同類型的依賴項(xiàng)解析錯(cuò)誤及其修復(fù)方法。
1.修復(fù)重復(fù)類錯(cuò)誤
如果某個(gè)類多次出現(xiàn)在運(yùn)行時(shí)類路徑上,您會(huì)收到一條與以下內(nèi)容類似的錯(cuò)誤:
Program type already present com.example.MyClass
此錯(cuò)誤通常是下列其中一種情況所致:
-
二進(jìn)制文件依賴項(xiàng)包含一個(gè)庫(kù),該庫(kù)也作為直接依賴項(xiàng)包含在您的應(yīng)用中。例如,您的應(yīng)用聲明直接依賴于庫(kù) A 和庫(kù) B,但庫(kù) A 已在其二進(jìn)制文件中包含庫(kù) B。
- 如需解決此問(wèn)題,請(qǐng)取消將庫(kù) B 作為直接依賴項(xiàng)。
-
您的應(yīng)用的本地二進(jìn)制文件依賴項(xiàng)和遠(yuǎn)程二進(jìn)制文件依賴項(xiàng)是同一個(gè)庫(kù)。
- 如需解決此問(wèn)題,請(qǐng)移除其中一個(gè)二進(jìn)制文件依賴項(xiàng)。
2.解決類路徑之間的沖突
當(dāng) Gradle 解析編譯類路徑時(shí),會(huì)先解析運(yùn)行時(shí)類路徑,然后使用所得結(jié)果確定應(yīng)添加到編譯類路徑的依賴項(xiàng)版本。換句話說(shuō),運(yùn)行時(shí)類路徑?jīng)Q定了下游類路徑上完全相同的依賴項(xiàng)所需的版本號(hào)。
應(yīng)用的運(yùn)行時(shí)類路徑還決定了 Gradle 需要對(duì)應(yīng)用的測(cè)試 APK 的運(yùn)行時(shí)類路徑中的匹配依賴項(xiàng)使用的版本號(hào)。圖 1 說(shuō)明了類路徑的層次結(jié)構(gòu)。

例如,當(dāng)應(yīng)用使用 implementation 依賴項(xiàng)配置加入某個(gè)依賴項(xiàng)的一個(gè)版本,而庫(kù)模塊使用 runtimeOnly 配置加入該依賴項(xiàng)的另一個(gè)版本時(shí),就可能會(huì)發(fā)生多個(gè)類路徑中出現(xiàn)同一依賴項(xiàng)的不同版本的沖突。
在解析對(duì)運(yùn)行時(shí)和編譯時(shí)類路徑的依賴關(guān)系時(shí),Android Gradle 插件 3.3.0 及更高版本會(huì)嘗試自動(dòng)解決某些下游版本沖突。例如,如果運(yùn)行時(shí)類路徑包含庫(kù) A 版本 2.0,而編譯類路徑包含庫(kù) A 版本 1.0,則插件會(huì)自動(dòng)將對(duì)編譯類路徑的依賴關(guān)系更新為庫(kù) A 版本 2.0,以避免錯(cuò)誤。
不過(guò),如果運(yùn)行時(shí)類路徑包含庫(kù) A 版本 1.0,而編譯類路徑包含庫(kù) A 版本 2.0,插件不會(huì)將對(duì)編譯類路徑的依賴關(guān)系降級(jí)為庫(kù) A 版本 1.0,您仍會(huì)收到一條與以下內(nèi)容類似的錯(cuò)誤:
Conflict with dependency 'com.example.library:some-lib:2.0' in project 'my-library'.
Resolved versions for runtime classpath (1.0) and compile classpath (2.0) differ.
如需解決此問(wèn)題,請(qǐng)執(zhí)行以下某項(xiàng)操作:
- 將所需版本的依賴項(xiàng)作為 api 依賴項(xiàng)添加到庫(kù)模塊。也就是說(shuō),只有庫(kù)模塊聲明相應(yīng)依賴項(xiàng),但應(yīng)用模塊也能以傳遞方式訪問(wèn)其 API。
- 或者,您也可以同時(shí)在兩個(gè)模塊中聲明相應(yīng)依賴項(xiàng),但應(yīng)確保每個(gè)模塊使用的版本相同。不妨考慮配置項(xiàng)目全局屬性,以確保每個(gè)依賴項(xiàng)的版本在整個(gè)項(xiàng)目中保持一致。