文章來源:Google
已知問題:如果您現(xiàn)在有一個使用 alpha 版 Android 插件 3.0.0(例如 3.0.0-alpha9
)的 Android Studio 項目,則在您遷移到 Android 插件 3.0.0-beta4
和同步您的項目時罩润,可能會遇到以下錯誤: Gradle project refresh failed
怀酷。
從菜單欄中選擇 Build > Clean Project 可以解決此問題 - 您需要為每個項目僅執(zhí)行一次此操作驶忌。 然后荠列,您可以點擊菜單欄中的 Sync Project 蜓肆,將您的項目文件與 Gradle 同步坦仍。
如果您想要將您的項目遷移至 Android 插件 3.0.0-beta4
或更高版本湿颅,請閱讀本頁面,了解如何應用插件和特定版本的 Gradle床蜘,并根據(jù)一些突破性更改調整您的項目辙培。
更新 Gradle 版本
新 Android 插件要求 Gradle 版本 4.1-rc-1 或更高版本蔑水。 如果您正在使用 Android Studio 3.0 Beta 1 或更高版本打開現(xiàn)有項目,請按照提示操作扬蕊,將現(xiàn)有項目自動更新到兼容版本的 Gradle搀别。
要手動更新 Gradle,請更新 gradle-wrapper.properties 中的網址尾抑,如下所示:
distributionUrl=\
https\://services.gradle.org/distributions/gradle-4.1-rc-1-all.zip
應用插件
如果您正在使用 Android Studio 3.0 Beta 1 或更高版本打開現(xiàn)有項目歇父,請按照提示操作,將您的項目自動更新到最新版本的 Android 插件再愈。 要手動更新您的項目庶骄,請包含 Maven 存儲區(qū)并在您的項目級 build.gradle 文件中更改插件版本,如下所示:
buildscript {
repositories {
...
// You need to add the following repository to download the
// new plugin.
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0-beta4'
}
}
使用風味維度進行變體感知依賴項管理
插件 3.0.0 包含一項新的依賴項機制践磅,這種機制可以在消費庫時自動匹配變體单刁。 也就是說,應用的 debug
變體將自動消費庫的 debug
變體府适,等等羔飞。 這種機制也適用于使用風味的情況 - 應用的 redDebug
變體將消費庫的 redDebug
變體。 要使這種機制發(fā)揮作用檐春,插件現(xiàn)在要求屬于給定風味維度的所有風味 - 即使您僅準備使用一個維度逻淌,也是如此。 否則疟暖,您將遇到以下構建錯誤:
Error:All flavors must now belong to a named flavor dimension.
The flavor 'flavor_name' is not assigned to a flavor dimension.
要解決此錯誤卡儒,請將每個風味分配至一個給定維度,如下面的示例中所示俐巴。 由于依賴項匹配現(xiàn)在由插件處理骨望,您應當謹慎地為風味維度命名。 例如欣舵,如果您的所有應用和庫模塊均使用 foo 維度擎鸠,您對插件可以匹配的風味的控制力較弱。
// Specifies a flavor dimension.
flavorDimensions "color"
productFlavors {
red {
// Assigns this product flavor to the 'color' flavor dimension.
// This step is optional if you are using only one dimension.
dimension "color"
...
}
blue {
dimension "color"
...
}
}
解決與依賴項匹配相關的構建錯誤
Android 插件會嘗試將您的應用的每一個變體與庫中的相同變體匹配缘圈。 因此劣光,在您構建“freeDebug”版本的應用時,插件會嘗試將其與“freeDebug”版本的本地庫依賴項匹配糟把。
不過绢涡,假設您的應用配置一個名稱為“staging”的構建類型,但其庫依賴項之一沒有進行相應配置遣疯。 在插件嘗試創(chuàng)建您的“staging”版本的應用時雄可,它將無法了解庫要使用哪一個版本,您將看到一條類似于如下的錯誤消息:
Error:Failed to resolve: Could not resolve project :mylibrary.
Required by:
project :app
Android 插件 3.0.0-beta4 及更高版本包含一些 DSL 元素,這些 DSL 元素有助于控制插件應如何解決應用與依賴項之間無法實現(xiàn)直接變體匹配的情況滞项。 下表可以幫助您確定應使用哪個 DSL 屬性來解決與變體感知依賴項匹配相關的特定構建錯誤狭归。
您的應用包含庫依賴項不包含的構建類型夭坪。
例如文判,您的應用包含“staging”構建類型,但依賴項僅包含“調試”和“發(fā)布”構建類型室梅。
請注意戏仓,如果庫依賴項包含您的應用不包含的構建類型,這不會引發(fā)問題亡鼠。 這是因為插件在任何時候都不會從依賴項請求該構建類型赏殃。
解決方法:
使用 matchingFallbacks 為給定構建類型指定替代匹配,如下所示:// In the app's build.gradle file. android { buildTypes { debug {} release {} staging { // Specifies a sorted list of fallback build types that the // plugin should try to use when a dependency does not include a // "staging" build type. You may specify as many fallbacks as you // like, and the plugin selects the first build type that's // available in the dependency. matchingFallbacks = ['debug', 'qa', 'release'] } } }
對于應用及其庫依賴項中均存在的給定風味維度间涵,您的應用包含庫不包含的風味仁热。
例如,您的應用及其庫依賴項都包含“級別”風味維度勾哩。 不過抗蠢,應用中的“級別”維度包含“免費”和“付費”風味,但依賴項僅包含相同維度的“演示”和“付費”風味思劳。
請注意迅矛,對于應用及其庫依賴項中均存在的給定風味維度,如果庫包含應用不包含的產品風味潜叛,這不會引發(fā)問題秽褒。 這是因為插件在任何時候都不會從依賴項請求該風味。
解決方法:
使用 matchingFallbacks 為應用的“免費”產品風味指定替代匹配威兜,如下所示:// In the app's build.gradle file. android { defaultConfig{ // Do not configure matchingFallbacks in the defaultConfig block. // Instead, you must specify fallbacks for a given product flavor in the // productFlavors block, as shown below. } flavorDimensions 'tier' productFlavors { paid { dimension 'tier' // Because the dependency already includes a "paid" flavor in its // "tier" dimension, you don't need to provide a list of fallbacks // for the "paid" flavor. } free { dimension 'tier' // Specifies a sorted list of fallback flavors that the plugin // should try to use when a dependency's matching dimension does // not include a "free" flavor. You may specify as many // fallbacks as you like, and the plugin selects the first flavor // that's available in the dependency's "tier" dimension. matchingFallbacks = ['demo', 'trial'] } } }
庫依賴項包含應用不包含的風味維度销斟。
例如,庫依賴項包含“minApi”維度的風味椒舵, 但您的應用包含僅適用于“級別”維度的風味票堵。 因此,當您想要構建“freeDebug”版本的應用時逮栅,插件不知道使用“minApi23Debug”還是“minApi18Debug” 版本的依賴項悴势。
請注意,如果應用包含庫依賴項不包含的風味維度措伐,這不會引發(fā)問題特纤。 這是因為插件僅會匹配依賴項中存在的維度的風味。 例如侥加,如果依賴項不包含 ABI 的維度捧存,您的“freeX86Debug”版本的應用將直接使用“freeDebug” 版本的依賴項。
解決方法:
在defaultConfig
代碼塊中使用missingDimensionStrategy
指定插件應從每個缺失維度中選擇的默認風味,如下面的示例所示昔穴。 您也可以替換在productFlavors
代碼塊中的選擇镰官,讓每一個風味都可以為缺失維度指定一個不同的匹配策略。// In the app's build.gradle file. android { defaultConfig{ // Specifies a sorted list of flavors that the plugin should try to use from // a given dimension. The following tells the plugin that, when encountering // a dependency that includes a "minApi" dimension, it should select the // "minApi18" flavor. You can include additional flavor names to provide a // sorted list of fallbacks for the dimension. missingDimensionStrategy 'minApi', 'minApi18', 'minApi23' // You should specify a missingDimensionStrategy property for each // dimension that exists in a local dependency but not in your app. missingDimensionStrategy 'abi', 'x86', 'arm64' } flavorDimensions 'tier' productFlavors { free { dimension 'tier' // You can override the default selection at the product flavor // level by configuring another missingDimensionStrategy property // for the "minApi" dimension. missingDimensionStrategy 'minApi', 'minApi23', 'minApi18' } paid {} } }
遷移本地模塊的依賴項配置
如果您已正確配置您的風味維度以充分利用變體感知依賴項解析吗货,則不再需要為本地模塊依賴項使用變體特定的配置泳唠,例如 redDebugImplementation
- 插件將為您執(zhí)行這項操作。使用變體特定的配置是可選項宙搬,并且不會破壞您的構建笨腥。
不過,針對本地模塊依賴項的特定變體(例如使用 configuration: 'debug'
)會導致以下構建錯誤:
Error:Could not resolve all dependencies for configuration
':app:prodDebugCompileClasspath'.
Project :app declares a dependency from configuration 'compile'
to configuration 'debug' which is not declared in the descriptor
for project :foo.
您應當按如下方式配置您的依賴項:
dependencies {
// This is the old method and no longer works for local
// library modules:
// debugCompile project(path: ':foo', configuration: 'debug')
// releaseCompile project(path: ':foo', configuration: 'release')
// Instead, simply use the following to take advantage of
// variant-aware dependency resolution. You can learn more about
// the 'implementation' configuration in the section about
// new dependency configurations.
implementation project(':foo')
// You can, however, keep using variant-specific configurations when
// targeting external dependencies. The following line adds 'app-magic'
// as a dependency to only the 'debug' version of your module.
debugImplementation 'com.example.android:app-magic:12.3'
}
配置 Wear 應用依賴項
為了支持嵌入式 Wear 應用的變體感知依賴項解析勇垛,插件 3.0.0 在解析之前會將所有關系圖組合起來脖母,與其他依賴項的處理方式類似。 在之前版本的插件中闲孤,<component>WearApp
依賴關系圖單獨解析谆级。 因此,您可以執(zhí)行與下面類似的操作讼积,藍色變體將使用 :wear2
肥照,所有其他變體將使用 :wear1
:
dependencies {
// This is the old way of configuring Wear App dependencies.
wearApp project(':wear1')
blueWearApp project(':wear2')
}
上面的配置不再適用于新插件。 不過币砂,如果您的穿戴式設備模塊與您的主應用配置相同的風味建峭,那么您不需要使用 <flavor>WearApp
配置。 只需指定 wearApp
配置决摧,主應用的每一個變體都將消費 wearable
中的匹配變體:
dependencies {
// If the main app and wearable modules have the same flavors,
// the following configuration uses automatic dependency matching.
wearApp project(':wearable')
}
如果您想要按應用風味指定不同的 Wear 應用模塊亿蒸,您仍可以按以下方式使用 <flavor>WearApp
配置(不過,您無法將其與 wearApp
配置組合):
dependencies {
redWearApp project(':wear1')
greenWearApp project(':wear1')
blueWearApp project(':wear2')
}
使用新依賴項配置
Gradle 3.4 引入了新的 Java 庫插件配置掌桩,允許您控制到編譯和運行時類路徑的發(fā)布(適用于模塊間依賴項)边锁。 Android 插件 3.0.0 正在遷移到這些新依賴項配置。 要遷移您的項目波岛,只需更新您的依賴項以使用新配置茅坛,而非已棄用配置,如下表中所列则拷。
新配置 | 已棄用配置 | 行為 |
---|---|---|
implementation | compile | 依賴項在編譯時對模塊可用贡蓖,并且僅在運行時對模塊的消費者可用。 對于大型多項目構建煌茬,使用 implementation 而不是 api/compile 可以顯著縮短構建時間斥铺,因為它可以減少構建系統(tǒng)需要重新編譯的項目量。 大多數(shù)應用和測試模塊都應使用此配置坛善。 |
api | compile | 依賴項在編譯時對模塊可用晾蜘,并且在編譯時和運行時還對模塊的消費者可用邻眷。 此配置的行為類似于 compile(現(xiàn)在已棄用),一般情況下剔交,您應當僅在庫模塊中使用它肆饶。 應用模塊應使用 implementation,除非您想要將其 API 公開給單獨的測試模塊岖常。 |
compileOnly | provided | 依賴項僅在編譯時對模塊可用驯镊,并且在編譯或運行時對其消費者不可用。 此配置的行為類似于 provided(現(xiàn)在已棄用)腥椒。 |
runtimeOnly | apk | 依賴項僅在運行時對模塊及其消費者可用阿宅。 此配置的行為類似于 apk(現(xiàn)在已棄用)候衍。 |
就像當前穩(wěn)定版本的 Android 插件一樣笼蛛,上面的配置對風味或構建類型特定的依賴項可用。 例如蛉鹿,您可以使用 api
讓依賴項對所有變體可用滨砍,也可以使用 redApi
讓其僅對模塊的 red
變體可用。
注:compile妖异、provided 和 apk 目前仍然可用惋戏。 不過党觅,它們將在下一個主要版本的 Android 插件中消失撕攒。
發(fā)布依賴項
以下配置將保持庫的傳遞依賴項供其消費者消費:
<variant>ApiElements
<variant>RuntimeElements
每個變體都曾有一個名稱為 <variant>
的配置深胳。 由于庫現(xiàn)在可以使用上一部分中介紹的 implementation
和 api
配置控制消費者可以看到的編譯信息蛇耀,現(xiàn)在有兩種配置畦浓,一種用于消費者的編譯遮婶,一種用于運行時书蚪。
要詳細了解不同配置之間的關系谢肾,請轉到 Java 庫插件配置蟀俊。
遷移自定義依賴項解析策略
插件使用以下配置解析變體的所有依賴項:
<variant>CompileClasspath(_<variant>Compile 不再奏效)
<variant>RuntimeClasspath(_<variant>Apk 不再奏效)
如果您仍在使用舊配置钦铺,將會遇到一個類似于如下的構建錯誤:
Error:Configuration with old name _debugCompile found.
Use new name debugCompileClasspath instead.
在已解析配置上設置解析策略的插件或構建文件需要改成新的名稱。 由于延遲依賴項解析肢预,現(xiàn)在可以在使用變體 API 時設置解析策略矛洞,如下面的示例中所示。 (Android 插件現(xiàn)在包含用于訪問變體配置對象的 getter 函數(shù)烫映。)
// Previously, you had to apply a custom resolution strategy during the
// configuration phase, rather than in the execution phase. That's
// because, by the time the variant was created and the Variant API was
// called, the dependencies were already resolved. This no longer works, and
// you should use this method only while using an older version of the plugin.
// configurations {
// _debugCompile
// _debugApk
// }
// ...
//
// configurations._debugCompile.resolutionStrategy {
// ...
// }
//
// configurations.all {
// resolutionStrategy {
// ...
// }
// }
// Because the new build model delays dependency resolution, you should
// query and modify the resolution strategy using the Variant API.
android {
applicationVariants.all { variant ->
variant.getCompileConfiguration().resolutionStrategy {
...
}
variant.runtimeConfiguration.resolutionStrategy {
...
}
variant.getAnnotationProcessorConfiguration().resolutionStrategy {
...
}
}
}
注: 新插件目前使用舊名稱查找配置沼本,如果發(fā)現(xiàn)這些配置,將失敗锭沟。 否則抽兆,它會靜默忽略自定義解析策略。 我們可能會根據(jù)反饋對這一點進行更改冈钦,不過我們想要尋找一種方式來簡化遷移郊丛。
使用注解處理器依賴項配置
在之前版本的 Android Plugin for Gradle 中李请,編譯類路徑中的依賴項將自動添加到處理器類路徑中。 也就是說厉熟,您可以向編譯類路徑中添加一個注解處理器导盅,它將按預期工作。 不過揍瑟,由于向處理器添加了大量不需要的依賴項白翻,這會對性能造成顯著影響。
使用新插件時绢片,必須使用 annotationProcessor 依賴項配置將注解處理器添加到處理器類路徑中滤馍,如下所示:
dependencies {
...
annotationProcessor 'com.google.dagger:dagger-compiler:<version-number>'
}
如果 JAR 文件包含以下文件,插件會將依賴項假設為注解處理器:META-INF/services/javax.annotation.processing.Processor底循。如果插件在編譯類路徑中檢測到注解處理器巢株,您的構建將失敗,并且您將看到一條錯誤消息熙涤,其中列出了編譯類路徑中的每一個注解處理器阁苞。 要修復錯誤,只需更改這些依賴項的配置以使用 annotationProcessor祠挫。 如果依賴項包含也需要位于編譯類路徑中的組件那槽,請再次聲明該依賴項并使用 compile 依賴項配置。
android-apt 插件用戶: 此行為變更目前不影響 android-apt 插件等舔。 不過骚灸,插件將不會與未來版本的 Android Plugin for Gradle 兼容。
停用錯誤檢查
如果編譯類路徑中的依賴項包含您不需要的注解處理器慌植,您可以將以下代碼添加到 build.gradle 文件中甚牲,停用錯誤檢查。 請記住涤浇,您添加到編譯類路徑中的注解處理器仍不會添加到處理器類路徑中鳖藕。
android {
...
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
includeCompileClasspath false
}
}
}
}
如果您在遷移到新依賴項解析策略時遇到問題,可以設置 includeCompileClasspath true
只锭,將行為恢復為 Android 插件 2.3 的行為著恩。 不過,不建議將行為恢復為版本 2.3蜻展,未來更新中將移除恢復選項喉誊。 為了幫助我們提升與您正在使用的依賴項的兼容性,請提交錯誤纵顾。
使用單獨的測試模塊
使用插件 3.0.0 時伍茄,單獨的測試模塊現(xiàn)在具備變體感知功能(請參見上面的部分)。也就是說施逾,不再需要指定 targetVariant敷矫。
測試模塊中的每個變體都將嘗試測試目標項目中的匹配變體例获。 默認情況下,測試模塊僅包含一個 debug 變體曹仗,但您也可以創(chuàng)建新的構建類型和新風味來創(chuàng)建新的變體以匹配測試的應用項目榨汤。 將為每一個變體創(chuàng)建一個 connectedCheck 任務。
要讓 Test 項目僅測試不同的構建類型怎茫,而不測試“調試”構建類型收壕,請使用 VariantFilter 在測試項目中停用 debug 變體,如下所示:
android {
variantFilter { variant ->
if (variant.buildType.name.equals('debug') {
variant.setIgnore(true);
}
}
}
如果您希望測試模塊僅針對應用的特定風味變體轨蛤,則可以使用 flavorSelection
屬性針對您想要測試的風味蜜宪。 這樣也可以讓測試模塊不必為自己配置這些風味。
庫中的本地 JAR
之前祥山,庫模塊以非標準方式處理本地 JAR 上的依賴項圃验,并將其打包到 AAR 中。 即使在多項目構建中枪蘑,AAR 的消費者也能通過打包版本看到這些 JAR 文件损谦。
Android 插件 3.0.0 及更高版本使用新的 Gradle API 以允許消費項目岖免,從而將本地 JAR 視為常規(guī)傳遞依賴項岳颇,與基于 Maven 坐標的依賴項類似。 要適應新的 Gradle API颅湘,插件必須更改其處理本地 JAR 文件方式的多個方面话侧。
項目間發(fā)布
庫模塊不再處理本地 JAR。 旨在加快增量構建的速度闯参,這些增量構建由庫模塊代碼更改引起瞻鹏。
庫模塊上的變換現(xiàn)在可以僅影響 PROJECT 范圍。 應用使用 PROJECT_LOCAL_DEPS 的變換將失敗鹿寨,因為此范圍現(xiàn)在已棄用新博。
對于其本地 JAR 屬于 EXTERNAL 流的應用模塊,PROJECT_LOCAL_DEPS 和 SUB_PROJECT_LOCAL_DEPS 流現(xiàn)在始終為空脚草。
為本地庫模塊啟用 ProGuard 不再影響庫的代碼赫悄。 您應在最終應用模塊上改為運行 ProGuard。
之前馏慨,必須在庫模塊中解決庫模塊與其本地 JAR 依賴項之間的 Java 資源沖突埂淮。 由于本地 JAR 不再通過庫模塊處理,必須在消費該庫的應用中解決沖突写隶。
發(fā)布到 Maven 存儲區(qū)
發(fā)布到 Maven 存儲區(qū)方面沒有任何變化倔撞。 本地 JAR 已綁定,它們的非類資源合并到 AAR 的主 JAR 文件中慕趴。 如果模塊啟用 ProGuard痪蝇,則所有 JAR 都將合并到主 JAR 文件中
API 變更
Android 插件 3.0.0 引入了一些移除特定功能的 API 變更鄙陡,可能會破壞您現(xiàn)有的構建。 后期版本的插件可能會引入新的公共 API 來取代破壞的功能躏啰。
變體輸出
使用 Variant API 操作變體輸出在新插件中已不再受支持柔吼。 不過,這種方式仍然適用于簡單任務丙唧,例如在構建時更改 APK 名稱愈魏,如下所示:
// If you use each() to iterate through the variant objects,
// you need to start using all(). That's because each() iterates
// through only the objects that already exist during configuration time—
// but those object don't exist at configuration time with the new model.
// However, all() adapts to the new model by picking up object as they are
// added during execution.
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "${variant.name}-${variant.versionName}.apk"
}
}
不過,涉及訪問 outputFile 對象的更復雜任務不再奏效想际。 這是因為配置階段期間不再創(chuàng)建變體特定的任務培漏。 這就讓插件無法提前了解其全部輸出,不過胡本,這會加快配置速度牌柄。
manifestOutputFile
processManifest.manifestOutputFile() 函數(shù)不再可用,如果您嘗試調用該函數(shù)侧甫,您將遇到以下錯誤:
A problem occurred configuring project ':myapp'.
Could not get unknown property 'manifestOutputFile' for task ':myapp:processDebugManifest'
of type com.android.build.gradle.tasks.ProcessManifest.
您可以調用 processManifest.manifestOutputDirectory() 來返回包含所有已生成 manifest 的目錄的路徑珊佣,而不是調用 manifestOutputFile() 來獲取每個變體的 manifest 文件。 然后披粟,您可以找到某個 manifest 并向其應用您的邏輯咒锻。 下面的示例可以在 manifest 中動態(tài)更改版本代碼:
android.applicationVariants.all { variant ->
variant.outputs.all { output ->
output.processManifest.doLast {
// Stores the path to the maifest.
String manifestPath = "$manifestOutputDirectory/AndroidManifest.xml"
// Stores the contents of the manifest.
def manifestContent = file(manifestPath).getText()
// Changes the version code in the stored text.
manifestContent = manifestContent.replace('android:versionCode="1"',
String.format('android:versionCode="%s"', generatedCode))
// Overwrites the manifest with the new text.
file(manifestPath).write(manifestContent)
}
}
}