Невозможно сослаться на сгенерированный ресурс из кода - PullRequest
1 голос
/ 31 марта 2020

У меня есть файл шаблона конфигурации, который должен заполнять заполнители на основе текущего варианта сборки (devDebug, prodRelease, et c.).

Я решил создать и внедрить пользовательскую задачу Gradle в поток сборки, который правильно запускается и создает правильный файл конфигурации в папку основных ресурсов (main/res/raw).

Моя цель - вывести сгенерированный файл конфигурации в сгенерированные ресурсы папки сборки. Например, $buildDir/generated/res/myconfig/dev/debug/raw/config.json. Я могу установить путь для вывода, чтобы он был похож, и файл был создан, но я застрял при попытке доступа к нему из кода. Также AS не распознает папку myconfig как ресурсы root (даже если она явно помечена). Что мне здесь не хватает?

Вот задача 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)
    }
}

Как видите, папки и файлы успешно создаются в папке сборки:

generated resources

Однако ссылки из кода не работают, я предположим, потому что сгенерированные источники не распознаются и собраны должным образом.

enter image description here

Я попытался добавить сгенерированную папку к исходным наборам в блоке android файла Gradle - таким образом папка была помечена как ресурс root, но ссылки из кода все еще не работают.

Ответы [ 2 ]

1 голос
/ 08 апреля 2020

Редактировать

Таким образом, resValue не работает с необработанными значениями, поэтому рабочий путь заключается в регистрации пути вашего файла как res path для android

Как @bearlysophisticated предложил сделать это так

    val configRoot = File("$buildDir/generated/myconfig/${variant.flavorName}/${variant.buildType.name}/res")

    // Registering folder as recognized resourced root
    variant.registerGeneratedResFolders(files(configRoot))

Сделать это из задачи l oop. Лучше раньше.

Изменить конец

Проблема в том, что вы создаете файл, но никогда не позволяете Android framework его проиндексировать. Это означает, что файл действительно существует, но он не добавляется в файл R. java со ссылками на ресурсы. Gradle имеет такую ​​возможность:

вы можете сделать что-то вроде resValue "raw", "json_name", file Не работает - см. Редактировать раздел выше

Я не уверен, что это будет работать с необработанным ресурсом, так как я не пробовал его в реальном коде - но со строками и int он работает отлично.

Надеюсь, это поможет.

0 голосов
/ 09 апреля 2020

Экспериментируя с ответом Пола Оста, я натолкнулся на рабочее решение.

В основном все, что вам нужно сделать, это вызвать variant.registerGeneratedResFolders(files(configRoot)), который собирается зарегистрировать сгенерированную папку как ресурсы root, чтобы значения там были будет доступен через R..

Важной частью является то, что это должно быть не внутри задачи, а до внедрения и создания задачи. Я не уверен почему. Кроме того, добавление источника root вручную не требуется, так как это не повлияет на результат. См. Исправленный код для задачи ниже.

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)
                }
            }
        )
    }
}
...