在共用套件或其他一些套件以資料庫為相依項目時,如果相依對象是不同且互不相容的共用套件版本,便會發生相依項目問題。Gradle 可減輕 Android 開發人員的工作負擔,只需在 build.gradle 中加入相依項目,所需的資料庫就會無縫地納入組建當中。但是,當兩個相依項目的相依對象是同一資料庫的不同版本時,會發生什麼情況?
如果兩個相依項目屬於相同配置,即同為應用程式配置,Gradle 能夠自動解析相依關係。例如,Android 版 Audience Network SDK 的相依項目為 「exoplayer」資料庫。如果需要加入不同版本的「exoplayer」資料庫,Gradle 將選擇納入最高的版本。但是如果兩個相依項目屬於不同配置,即分別屬應用程式和測試配置,Gradle 便會擲回錯誤。我們將於下文講解不同的衝突和解決方案。
確保您在開始操作前,已經先行參閱 Audience Network 新手指南及 Android 新手指南。
請參考以下範例。以下程式碼的兩個相依項目均採用相同的配置,並在資料庫「org.hamcrest:hamcrest-core」中有內部相依項目。由於兩個相依項目在內部使用同一個資料庫的不同版本,系統會在組建中納入較高的版本。Gradle 同步的輸出內容將清楚列明,其在最終組建中將 hamcrest 資料庫版本由 1.1 版自動升級至 1.3 版。
// Depends on version 1.3 of org.hamcrest:hamcrest-core androidTestImplementation 'junit:junit:4.12' // Depends on version 1.1 of org.hamcrest:hamcrest-core androidTestImplementation 'org.mockito:mockito-core:1.10.19'
如果兩個相依項目屬於不同配置,即分別屬應用程式和測試配置,Gradle 便會擲回錯誤。請參考下列程式碼片段。第一個相依項目屬於應用程式配置,而第二個相依項目則屬於測試配置。因此,當建立專案時,系統將失敗並出現異常情況。
進行儀器測試時,主 APK 和測試 APK 將共用相同的類別路徑。如果主 APK 和測試 APK 使用相同的資料庫(例如 Guava),但版本不同,Gradle 將無法建立專案。如果 Gradle 未有發現這一點,您的應用程式在測試時和正常運行時的表現會有所不同,包括在其中一個情況下當機。
// Depends on version 1.3 of org.hamcrest:hamcrest-core implementation 'junit:junit:4.12' // Depends on version 1.1 of org.hamcrest:hamcrest-core androidTestImplementation 'org.mockito:mockito-core:1.10.19'
這是最簡單的方法,但僅限於各相依項目屬於相同配置的情況。例如,您的模組明確地以 ExoPlayer 的特定版本為相依項目。然而,Audience Network SDK 已納入 ExoPlayer 的另一版本。系統預設會將最高版本納入組建中。在以下的程式碼片段中,Gradle 同步的輸出內容將清楚列明,其在最終組建中將 ExoPlayer 資料庫版本由 r2.4.2 版自動升級至 2.7.3 版。
implementation 'com.google.android.exoplayer:exoplayer-core:2.7.3' implementation 'com.google.android.exoplayer:exoplayer-dash:2.7.3' ... // audience-network-sdk depends on exoplayer-core:r2.4.2 and exoplayer-dash:r2.4.2 implementation 'com.facebook.android:audience-network-sdk:4.28.1'
在大多數情況下,開發人員或會想控制最終組建中所包含的資料庫版本。您可配置 build.gradle 以做到這一點。例如,如果開發人員想以較低版本的 ExoPlayer r2.4.0,而非 Audience Network SDK 中的 r2.4.2,則您可以在宣告「audience-network-sdk」相依項目時排除此模組。排除標籤也適用於各相依項目屬於不同配置的情況。
在實際專案中,許多相依項目會採用同一資料庫的不同版本。在這種情況下,您需要為每個相依項目分別提供排除標籤,以便納入該資料庫的預期版本。
情景 1:各相依項目屬於同一配置implementation 'com.google.android.exoplayer:exoplayer-core:r2.4.0' implementation 'com.google.android.exoplayer:exoplayer-dash:r2.4.0' ... // audience-network-sdk depends on exoplayer-core:r2.4.2 and exoplayer-dash:r2.4.2 implementation ('com.facebook.android:audience-network-sdk:4.28.1') { exclude group: 'com.google.android.exoplayer', module:'exoplayer-core' exclude group: 'com.google.android.exoplayer', module:'exoplayer-dash' }情景 2:各相依項目屬於不同配置
// Depends on version 1.3 of org.hamcrest:hamcrest-core implementation 'junit:junit:4.12' // Depends on version 1.1 of org.hamcrest:hamcrest-core androidTestImplementation ('org.mockito:mockito-core:1.10.19'){ exclude group: 'org.hamcrest', module:'hamcrest-core' }
當屬於不同配置的相依項目發生衝突時,這是較簡潔的解決方法。在這種情況下,我們需要明確指出在為任何一種配置而設的最終組建中,我們希望納入哪個資料庫版本。
這是能夠解決衝突的更簡潔方法,但缺點是在更新 junit 和 mockito 等實際相依項目的同時,開發人員也需要更新出現衝突的資料庫。
// Depends on version 1.3 of org.hamcrest:hamcrest-core implementation 'junit:junit:4.12' // Depends on version 1.1 of org.hamcrest:hamcrest-core androidTestImplementation 'org.mockito:mockito-core:1.10.19' // Explictly mention that include version 1.3 of org.hamcrest:hamcrest-core androidTestCompile 'org.hamcrest:hamcrest-core:1.3'
這是解決衝突的另一種方法,也就是不針對單一配置來宣告,而是強制為所有配置執行此解決方案。在以下範例中,您可以將自己的「resolutionStrategy」加入模組層級的 build.gradle,以便其強制納入套件的指定版本,不論各相依項目的配置是相同還是不同亦然。
使用此方法時請格外小心。在第一個範例中,如果 audience-network-sdk 已更新,而且這些資料庫已更新 exoplayer-core 和 exoplayer-dash 資料庫的版本,則我們仍然會強制使用早期版本。雖然這種情況也適合採用第二種解決方案,但是在此方法中,我們會為所有配置強制設定相依項目版本,而不只是針對單一配置。
情景 1:各相依項目屬於同一配置android { configurations.all { resolutionStrategy.force 'com.google.android.exoplayer:exoplayer-core:r2.4.0' resolutionStrategy.force 'com.google.android.exoplayer:exoplayer-dash:r2.4.0' } }情景 2:各相依項目屬於不同配置
android { configurations.all { resolutionStrategy.force 'org.hamcrest:hamcrest-core:1.1' } }
提交應用程式以供審查。
一旦我們從您的應用程式或網站接收到廣告的要求,我們就會檢視要求並確保其符合 Audience Network 政策與 Facebook 社群守則。深入瞭解我們的審查程序。