Генерация ресурсов в проектах Android — RegisterGeneratedResFolder

Feb 12 2023
В мире Android очень хорошо известны концепции генерации кода и ресурсов. Генерация кода используется в большинстве проектов, являясь основной механикой dagger, room и других библиотек, но как насчет ресурсов? Например, в процессе сборки ваш google-services.

В мире Android очень хорошо известны концепции генерации кода и ресурсов. Генерация кода используется в большинстве проектов, являясь основной механикой dagger, room и других библиотек, но как насчет ресурсов? Например, в процессе сборки файл google-services.jsonанализируется и преобразуется в values.xmlфайл в generatedпапке, который будет использоваться библиотеками Firebase. Как оказалось, создавать и использовать свои собственные сгенерированные ресурсы легко, если вы знаете, что делать с ними, когда они у вас есть. Вроде бы все просто — вы создаете нужные файлы и помещаете их в сгенерированную папку. Тем не менее, это требует немного больше работы.

Задача Gradle для преобразования строк

Давайте создадим простую задачу Gradle, которая преобразует файл JSON с некоторыми строками в XML-файл строк Android и сохраняет результат в generatedпапку. Судя по другим файлам в этом каталоге, путь должен быть следующим:

app/build/generated/res/${generator}/${sourceSet}/values/strings.xml

Этого должно быть достаточно, верно? Если вы попытаетесь собрать приложение, используя ресурсы из сгенерированного файла, оно не сработает. Ни Android Studio, ни Gradle не смогут распознать ваш файл как часть проекта. Есть способ заставить их это сделать.

RegisterGeneratedResFolderв помощь

BaseVariantВ интерфейсе системы сборки Android есть волшебный метод, registerGeneratedResFolderкоторый делает именно это.

Для этого требуется FileCollectionобъект, указывающий на нашу папку и определяющий задачу, которая его генерирует.

Комментарий выше говорит нам, что задача будет подключена к процессу сборки Gradle, поэтому все, что нам нужно сделать, это зарегистрировать папку. Здесь следует отметить, что используемый для этого путь отличается от пути для фактического хранения сгенерированного файла.

app/build/generated/res/${generator}/${sourceSet}

generateStringsFileзадача будет запущена до mergeResources, что сделает все новые ресурсы доступными для следующих этапов сборки и в Android Studio. Вы также можете запустить его вручную, чтобы создать необходимые файлы, чтобы во время работы не было ошибок «ресурс не найден».

Что дальше?

Хотя приведенного выше примера достаточно для простых случаев, у него есть большой недостаток — задача не инкрементальная. Другими словами, он будет запускаться каждый раз при сборке проекта, что неизбежно увеличивает время сборки. Также в настоящее время нет возможности указать файлы, которые должны использоваться в качестве входных данных, и папку для сохранения результата. Мы можем решить первую проблему, сделав саму задачу инкрементной. Второй решается путем добавления входных данных задачи и, возможно, включения их в плагин. Создание собственного плагина выходит за рамки этой статьи, но вы можете найти код в моем репозитории GitHub .

Это было мое первое глубокое погружение в Gradle и систему сборки Android, и я надеюсь, что оно поможет вам решить ваши собственные проблемы. Удачного кодирования!