Как зарегистрировать сгенерированные ресурсы в задаче Android Gradle? - PullRequest
1 голос
/ 12 февраля 2020

Я пытаюсь сгенерировать некоторые ресурсы Android в задаче Gradle.

Я написал задачу, которая анализирует входной файл и записывает файл XML в папку в каталоге build приложения.

app / build. gradle

import groovy.xml.MarkupBuilder


task generateSomeAppResources {
    ext.outputDir = new File(projectDir, "build/generated/res/values")
    doFirst {
        mkdir outputDir

        new File(outputDir, "generated.xml").withWriter { writer ->
            def destXml = new MarkupBuilder(new IndentPrinter(writer, "    ", true, true))
            destXml.setDoubleQuotes(true)
            def destXmlMkp = destXml.getMkp()
            destXmlMkp.xmlDeclaration(version: "1.0", encoding: "utf-8")
            destXmlMkp.comment("Generated at ${new Date()}")
            destXmlMkp.yield "\r\n"

            destXml.resources() {
                "string"("name": "generated_app_resource") {
                    destXmlMkp.yield("Some generated value for the app")
                }
            }
        }
    }
}

Это работает нормально, и сгенерированный вывод выглядит так, как я ожидал.

сгенерирован. xml

<?xml version="1.0" encoding="utf-8"?>
<!-- Generated at Wed Feb 12 12:46:12 GMT 2020 -->
<resources>
    <string name="generated_app_resource">Some generated value for the app</string>
</resources>


Я изо всех сил пытаюсь заставить систему сборки Android обнаружить сгенерированный файл. Совет Google - это

, чтобы написать задачу, которая выводит сгенерированную структуру каталогов ресурсов с чем угодно, используйте BaseVariant.registerGeneratedResFolders ()

Но документации по registerGeneratedResFolders() не существует. После долгих утомительных поисков я нашел несколько примеров использования в источнике Play Services Plugin, например, , поэтому я попытался добавить что-то вроде этого.

app / build.gradle

android.applicationVariants.all { variant ->
    def files = project.files(generateSomeAppResources.outputDir)
    files.builtBy(generateSomeAppResources)
    variant.preBuildProvider.configure { dependsOn(generateSomeAppResources) }
    variant.mergeResourcesProvider.configure { dependsOn(generateSomeAppResources) }
    variant.registerGeneratedResFolders(files)
}

Но я что-то упустил. Сгенерированный ресурс отображается пурпурным цветом в Android Studio, что означает, что IDE считает, что он существует ...

enter image description here

... но код завершается ошибкой для компиляции с ошибкой Unresolved reference: generated_app_resource.

Я не знаю, какие магические заклинания c необходимы, чтобы система сборки Android собирала эти ресурсы. Как мне это построить?

1 Ответ

1 голос
/ 14 февраля 2020

Для создания ресурсов android требуется

1) Каталог ресурсов над папкой values, затем вы можете добавить нужные ресурсы согласно вашему требованию

2) Поручить процессу сборки добавьте сгенерированные ресурсы при сборке R.java

Итак, сначала настройте задачу по сборке ресурсов следующим образом:

task generateSomeAppResources {
    ext.outputDir = new File(projectDir, "build/generated/res/custom/values")
    print("path is "+projectDir)
    doFirst {
        mkdir outputDir

        new File(outputDir, "strings.xml").withWriter { writer ->
            def destXml = new MarkupBuilder(new IndentPrinter(writer, "    ", true, true))
            destXml.setDoubleQuotes(true)
            def destXmlMkp = destXml.getMkp()
            destXmlMkp.xmlDeclaration(version: "1.0", encoding: "utf-8")
            destXmlMkp.comment("Generated at ${new Date()}")
            destXmlMkp.yield "\r\n"

            destXml.resources() {
                "string"("name": "generated_app_resource") {
                    destXmlMkp.yield("Some generated value for the app")
                }
            }
        }
    }
}

Теперь добавьте путь в процессе сборки, используя sourceSets в build.gradle ( app) like

android {
    //....
    sourceSets {
        main {
            res.srcDirs += [
                    'build/generated/res/custom',
            ]
        }
    }
}

Кроме того, добавьте задачу в текущем процессе сборки как

gradle.projectsEvaluated {
    preBuild.dependsOn('generateSomeAppResources')
} // no need of `android.applicationVariants.all...` 

Теперь синхронизируйте c проект, и он будет работать как положено.

Результат:

enter image description here

...