【问题标题】:Unable to reference generated resource from code无法从代码中引用生成的资源
【发布时间】:2020-03-31 16:12:55
【问题描述】:

我有一个配置模板文件,其中包含要根据当前构建风格(devDebugprodRelease 等)填写的占位符。

我决定创建一个自定义 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)
    }
}

如您所见,文件夹和文件已在 build 文件夹中成功创建:

但是我想从代码中引用不起作用,因为生成的源没有被正确识别和组装。

我尝试将生成的文件夹添加到 gradle 文件的 android 块中的源集中 - 这样该文件夹被标记为资源根目录,但从代码中引用仍然无法正常工作。

【问题讨论】:

    标签: android gradle android-resources android-build gradle-kotlin-dsl


    【解决方案1】:

    编辑

    所以resValue 不适用于原始值,因此工作方式是将文件的路径注册为res android 路径

    就像@bearlysophisticated suggested 那样做

        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 不起作用 - 请参阅上面的编辑部分

    我不确定这是否适用于原始资源,因为我没有在实际代码中尝试过 - 但对于字符串和整数,它可以完美地工作。

    希望对你有帮助。

    【讨论】:

    • 不幸的是,这种方法并不好:resValue 不支持原始文件。尝试执行您建议的操作时出现以下异常:invalid value for type 'raw'. Expected a reference. 我不确定如何将引用设置为值。但是,在实施您的解决方案时,我找到了另一个最终可行的解决方案。谢谢!
    • 酷。干杯队友
    【解决方案2】:

    在尝试 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)
                    }
                }
            )
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-09
      • 2012-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-17
      相关资源
      最近更新 更多