无法从代码中引用生成的资源
Unable to reference generated resource from code
我有一个配置模板文件,其中包含要根据当前构建风格(devDebug
、prodRelease
等)填写的占位符。
我决定创建一个自定义 Gradle 任务并将其注入构建流程,该流程可以正常运行并在主资源文件夹 (main/res/raw
) 中创建正确的配置文件。
我的目标是将生成的配置文件输出到构建文件夹的生成资源中,例如$buildDir/generated/res/myconfig/dev/debug/raw/config.json
。我可以将输出的路径设置为类似的路径并创建文件,但在尝试从代码访问它时我被卡住了。此外,AS 不会将文件夹 myconfig
识别为资源根目录(即使明确标记它)。我在这里想念什么?
这是执行工作的 Gradle 任务(它是 Kotlin):
fun configureMyConfiguration(variant: ApplicationVariant) {
getTasksByName(
"generate${variant.name.capitalize()}Resources",
true
).onEach { task ->
task.dependsOn(
task("${variant.name}ConfigureMyConfiguration") {
group = "MyApp"
description = "Configure my configuration"
doLast {
val configRoot = File("$buildDir/generated/myconfig/${variant.flavorName}/${variant.buildType.name}/res")
val templateFile = "$rootDir/app/config_template.json"
val configFile = File(configRoot, "raw/my_config.json")
val config = File(templateFile).readText()
.replace("${foo}", "bar")
configFile.ensureParentDirsCreated()
configFile.createNewFile()
configFile.writeText(config)
project.android.sourceSets.getByName(variant.name) {
resources.srcDir(configRoot)
}
}
}
)
}
}
配置应用程序变体时调用设置任务的方法:
applicationVariants.all {
outputs.forEach {
configureMyConfiguration(this@all)
}
}
如您所见,文件夹和文件已在构建文件夹中成功创建:
但是我想从代码中引用是行不通的,因为生成的源没有被正确识别和组装。
我尝试将生成的文件夹添加到 gradle 文件的 android
块中的源集中 - 这样文件夹就被标记为资源根目录,但从代码中引用仍然无效。
编辑
因此 resValue
不适用于原始值,因此工作方式是将文件路径注册为 android
的 res
路径
作为@bearlysophisticated 这样做
val configRoot = File("$buildDir/generated/myconfig/${variant.flavorName}/${variant.buildType.name}/res")
// Registering folder as recognized resourced root
variant.registerGeneratedResFolders(files(configRoot))
在任务循环之外进行。之前好多了。
编辑结束
问题是您创建了文件,但从未让 Android 框架为其编制索引。这意味着该文件实际存在,但未添加到具有资源引用的 R.java 文件中。 Gradle 有这样的可能性:
你可以这样做
resValue "raw", "json_name", file
不起作用 - 请参阅上面的 编辑 部分
我不确定这是否适用于原始资源,因为我没有在实际代码中尝试过它 - 但对于字符串和整数它可以完美地工作。
希望对您有所帮助。
在试验 Paul Ost 的回答时,我遇到了一个可行的解决方案。
基本上您需要做的就是调用 variant.registerGeneratedResFolders(files(configRoot))
,它将生成的文件夹注册为资源根目录,以便可以通过 R.
.
访问那里的值
重要的部分是这不应该在任务内部,而是在任务注入和创建发生之前。我不确定为什么。此外,不需要手动添加源根目录,因为它不会影响结果。请参阅下面任务的更正代码。
fun configureMyConfiguration(variant: ApplicationVariant) {
val configRoot = File("$buildDir/generated/myconfig/${variant.flavorName}/${variant.buildType.name}/res")
// Registering folder as recognized resourced root
variant.registerGeneratedResFolders(files(configRoot))
getTasksByName(
"generate${variant.name.capitalize()}Resources",
true
).onEach { task ->
task.dependsOn(
task("${variant.name}ConfigureMyConfiguration") {
group = "MyApp"
description = "Configure my configuration"
doLast {
val templateFile = "$rootDir/app/config_template.json"
val configFile = File(configRoot, "raw/my_config.json")
val config = File(templateFile).readText()
.replace("${foo}", "bar")
configFile.ensureParentDirsCreated()
configFile.createNewFile()
configFile.writeText(config)
}
}
)
}
}
我有一个配置模板文件,其中包含要根据当前构建风格(devDebug
、prodRelease
等)填写的占位符。
我决定创建一个自定义 Gradle 任务并将其注入构建流程,该流程可以正常运行并在主资源文件夹 (main/res/raw
) 中创建正确的配置文件。
我的目标是将生成的配置文件输出到构建文件夹的生成资源中,例如$buildDir/generated/res/myconfig/dev/debug/raw/config.json
。我可以将输出的路径设置为类似的路径并创建文件,但在尝试从代码访问它时我被卡住了。此外,AS 不会将文件夹 myconfig
识别为资源根目录(即使明确标记它)。我在这里想念什么?
这是执行工作的 Gradle 任务(它是 Kotlin):
fun configureMyConfiguration(variant: ApplicationVariant) {
getTasksByName(
"generate${variant.name.capitalize()}Resources",
true
).onEach { task ->
task.dependsOn(
task("${variant.name}ConfigureMyConfiguration") {
group = "MyApp"
description = "Configure my configuration"
doLast {
val configRoot = File("$buildDir/generated/myconfig/${variant.flavorName}/${variant.buildType.name}/res")
val templateFile = "$rootDir/app/config_template.json"
val configFile = File(configRoot, "raw/my_config.json")
val config = File(templateFile).readText()
.replace("${foo}", "bar")
configFile.ensureParentDirsCreated()
configFile.createNewFile()
configFile.writeText(config)
project.android.sourceSets.getByName(variant.name) {
resources.srcDir(configRoot)
}
}
}
)
}
}
配置应用程序变体时调用设置任务的方法:
applicationVariants.all {
outputs.forEach {
configureMyConfiguration(this@all)
}
}
如您所见,文件夹和文件已在构建文件夹中成功创建:
但是我想从代码中引用是行不通的,因为生成的源没有被正确识别和组装。
我尝试将生成的文件夹添加到 gradle 文件的 android
块中的源集中 - 这样文件夹就被标记为资源根目录,但从代码中引用仍然无效。
编辑
因此 resValue
不适用于原始值,因此工作方式是将文件路径注册为 android
res
路径
作为@bearlysophisticated
val configRoot = File("$buildDir/generated/myconfig/${variant.flavorName}/${variant.buildType.name}/res")
// Registering folder as recognized resourced root
variant.registerGeneratedResFolders(files(configRoot))
在任务循环之外进行。之前好多了。
编辑结束
问题是您创建了文件,但从未让 Android 框架为其编制索引。这意味着该文件实际存在,但未添加到具有资源引用的 R.java 文件中。 Gradle 有这样的可能性:
你可以这样做
不起作用 - 请参阅上面的 编辑 部分resValue "raw", "json_name", file
我不确定这是否适用于原始资源,因为我没有在实际代码中尝试过它 - 但对于字符串和整数它可以完美地工作。
希望对您有所帮助。
在试验 Paul Ost 的回答时,我遇到了一个可行的解决方案。
基本上您需要做的就是调用 variant.registerGeneratedResFolders(files(configRoot))
,它将生成的文件夹注册为资源根目录,以便可以通过 R.
.
重要的部分是这不应该在任务内部,而是在任务注入和创建发生之前。我不确定为什么。此外,不需要手动添加源根目录,因为它不会影响结果。请参阅下面任务的更正代码。
fun configureMyConfiguration(variant: ApplicationVariant) {
val configRoot = File("$buildDir/generated/myconfig/${variant.flavorName}/${variant.buildType.name}/res")
// Registering folder as recognized resourced root
variant.registerGeneratedResFolders(files(configRoot))
getTasksByName(
"generate${variant.name.capitalize()}Resources",
true
).onEach { task ->
task.dependsOn(
task("${variant.name}ConfigureMyConfiguration") {
group = "MyApp"
description = "Configure my configuration"
doLast {
val templateFile = "$rootDir/app/config_template.json"
val configFile = File(configRoot, "raw/my_config.json")
val config = File(templateFile).readText()
.replace("${foo}", "bar")
configFile.ensureParentDirsCreated()
configFile.createNewFile()
configFile.writeText(config)
}
}
)
}
}