目录
多渠道的写法
针对多渠道引用不同的包
There was a failure while populating the build operation queue: Could not stat file E:\xxxx\xxxx\xxxx\app\src\UAT\libsUAT\xxx-provider(?)-xx.aar
最近升级了Gradle8.3之后,从Groovy 迁移到 Kotlin,很多写法都有发生改变。
其他的不细说了,针对这篇文章的主题,多渠道写法 以及 不同渠道如何导入不同的包 来讲。
日常单一渠道的话,一般会用这种方式去区分环境。在8.0以下的写法是:
productFlavors {
DEV {
dimension 'XXXXX'
applicationIdSuffix '.dev'
buildConfigField "String", "DOMAIN", '"https://XXXXX/"'
buildConfigField "String", "XXXX_RETURN_URL", '"scheme://host"'
buildConfigField "String", "XXXX_RETURN_URL", '"scheme://host"'
buildConfigField "String", "XXXX_RETURN_URL", '"scheme://host"'
buildConfigField "Long", "BUILD_DATE", "${buildDate}L"
manifestPlaceholders = [
app_name : "(DEV)XXXX",
DEEP_LINK_HOST : "DOMAINXXXXX",
]
}
UAT {}
PROD {}
}
但在8.0以上,写法要改成
productFlavors {
create("DEV").apply {
this.dimension = "xxxxx"
this.applicationIdSuffix = ".dev"
this.buildConfigField("String", "DOMAIN", "\"https://XXXXXX/\"")
this.buildConfigField("String", "XXXX_RETURN_URL", "\"scheme://host\"")
this.buildConfigField("String", "XXXX_RETURN_URL", "\"scheme://host\"")
this.buildConfigField("String", "XXXX_RETURN_URL", "\"scheme://host\"")
this.buildConfigField("Long", "BUILD_DATE", "${buildDate}L")
this.manifestPlaceholders.apply {
this["app_name"] to "(DEV)XXXXX"
this["DEEP_LINK_HOST"] to "DOMAINXXXX"
}
}
create("UAT").apply {}
create("PROD").apply {}
}
这个可能不是每个人都需要,我是遇到是这个问题。
背景:台湾的支付平台SDK,UAT跟PROD给了两个SDK,同时导入会引发重复包的错误,不然就需要在开发阶段,放置UAT的SDK,等上线的时候记得替换PROD的SDK,这样存在一定的风险,可能会忘记替换等等原因。我希望做成当切换渠道(环境)的时候,自动切换到不同的SDK。
正常引用SDK,我们是使用下面这两种方式
dependencies {
implementation(files("XXXX"))
implementation(fileTree(mapOf("dir" to "../XXXX/libs", "include" to listOf("*.jar","*.aar"))))
}
我没在Gradle8.0以下针对不同渠道引用不同的SDK,没办法给出8.0以下的写法,我将8.0以上的写法直接贴出来
// 对于特定的flavor,使用特定的dependencies
val libsProdPath = "src/PROD/libsPROD/XXXXX.aar"
val libsUATPath = "src/UAT/libsUAT/XXXXX.aar"
configurations {
"PRODImplementation" {
extendsFrom(configurations.implementation.get())
}
"UATImplementation" {
extendsFrom(configurations.implementation.get())
}
}
dependencies {
// implementation(fileTree(mapOf("dir" to "../XXXXX/libs", "include" to listOf("*.jar","*.aar"))))
"PRODImplementation"(files(libsProdPath))
"UATImplementation"(files(libsUATPath))
}
这样在build的时候,就能根据不同的渠道(环境)去拿到对应的路径下的SDK文件了。
我需要加载多个SDK,所以改成了
// 对于特定的flavor,使用特定的dependencies
val libsProdPath = listOf(
"src/PROD/libsPROD/XXXXX.aar",
"src/PROD/libsPROD/XXXXX.aar",
"src/PROD/libsPROD/XXXXX.aar"
)
val libsUATPath = listOf(
"src/UAT/libsUAT/XXXXX.aar",
"src/UAT/libsUAT/XXXXX.aar",
"src/UAT/libsUAT/XXXXX.aar"
)
configurations {
"PRODImplementation" {
extendsFrom(configurations.implementation.get())
}
"UATImplementation" {
extendsFrom(configurations.implementation.get())
}
}
dependencies {
// implementation(fileTree(mapOf("dir" to "../XXXXX/libs", "include" to listOf("*.jar","*.aar"))))
"PRODImplementation"(files(libsProdPath))
"UATImplementation"(files(libsUATPath))
}
后面又觉得把版本号写固定在路径下并不方便,于是把版本号抽出来,由于我其他的libs的版本号都写在libs.versions.toml下统一管理,于是也很自然而然的去这个文件下添加了
[versions]
xxxxxVersion = "x.y.z"
但当我回来build.gradle.kts修改为如下之后
// 对于特定的flavor,使用特定的dependencies
val libsProdPath = listOf(
"src/PROD/libsPROD/XXX-${libs.versions.xxxxxVersion}-XX.aar",
"src/PROD/libsPROD/XXX-${libs.versions.xxxxxVersion}-XX.aar",
"src/PROD/libsPROD/XXX-${libs.versions.xxxxxVersion}-XX.aar"
)
val libsUATPath = listOf(
"src/UAT/libsUAT/XXX-${libs.versions.xxxxxVersion}-XX.aar",
"src/UAT/libsUAT/XXX-${libs.versions.xxxxxVersion}-XX.aar",
"src/UAT/libsUAT/XXX-${libs.versions.xxxxxVersion}-XX.aar"
)
configurations {
"PRODImplementation" {
extendsFrom(configurations.implementation.get())
}
"UATImplementation" {
extendsFrom(configurations.implementation.get())
}
}
dependencies {
// implementation(fileTree(mapOf("dir" to "../XXXXX/libs", "include" to listOf("*.jar","*.aar"))))
"PRODImplementation"(files(libsProdPath))
"UATImplementation"(files(libsUATPath))
}
出现了问题,Sync的时候提示错误:
找不到文件?为什么找不到,因为版本号没有被正确的加载,变成了provider(?)。
猜测是因为Gradle在执行阶段的时候引用了没有被正确解析的变量,最后通过provider来延迟加载版本号,以确保在配置阶段能够正确加载到版本号。
于是,最终代码如下:
val xxxxxVersionProvider: Provider = providers.provider { libs.versions.xxxxxVersion.get() }
// 对于特定的flavor,使用特定的dependencies
val libsProdPath = listOf(
"src/PROD/libsPROD/XXX-${xxxxxVersionProvider.get()}-XX.aar",
"src/PROD/libsPROD/XXX-${xxxxxVersionProvider.get()}-XX.aar",
"src/PROD/libsPROD/XXX-${xxxxxVersionProvider.get()}-XX.aar"
)
val libsUATPath = listOf(
"src/UAT/libsUAT/XXX-${xxxxxVersionProvider.get()}-XX.aar",
"src/UAT/libsUAT/XXX-${xxxxxVersionProvider.get()}-XX.aar",
"src/UAT/libsUAT/XXX-${xxxxxVersionProvider.get()}-XX.aar"
)
configurations {
"PRODImplementation" {
extendsFrom(configurations.implementation.get())
}
"UATImplementation" {
extendsFrom(configurations.implementation.get())
}
}
dependencies {
// implementation(fileTree(mapOf("dir" to "../XXXXX/libs", "include" to listOf("*.jar","*.aar"))))
"PRODImplementation"(files(libsProdPath))
"UATImplementation"(files(libsUATPath))
}
这样就能完美根据Build Variants中选择的Active Build Variant,build.gradle.kts自动去找到相对应的SDK了。
代码中所有实际项目相关的内容,都用【xxxxx】隐去,相应的路径、文件名,大家便根据各自实际情况修改了,有问题可以留言。
本文终。