Приложения для Android обычно создаются с помощью системы сборки Gradle. Прежде чем мы углубимся в детали настройки сборки, мы рассмотрим концепции, лежащие в основе сборки, чтобы вы могли увидеть систему в целом.
Что такое сборка?
Система сборки преобразует исходный код в исполняемое приложение. Сборка часто включает в себя несколько инструментов для анализа, компиляции, связывания и упаковки вашего приложения или библиотеки. Gradle использует подход, основанный на задачах, для организации и запуска этих команд.
Задачи инкапсулируют команды, которые преобразуют входные данные в выходные. Плагины определяют задачи и их конфигурацию. Применение плагина к сборке регистрирует его задачи и связывает их вместе, используя их входные и выходные данные. Например, если вы добавите в файл сборки плагин Android Gradle, будут зарегистрированы все задачи, необходимые для создания APK или библиотеки Android. Плагин java-library позволяет создать JAR-файл из исходного кода Java. Похожие плагины существуют для Kotlin и других языков, но они предназначены для расширения плагинов. Например, плагин protobuf предназначен для добавления поддержки protobuf в существующие плагины, такие как AGP или java-library.
Gradle предпочитает соглашение конфигурации, поэтому плагины будут поставляться с хорошими значениями по умолчанию, но вы можете дополнительно настроить сборку с помощью декларативного предметно-ориентированного языка (DSL). DSL разработан так, чтобы вы могли указать, что нужно создать, а не как это сделать. Логика в плагинах управляет тем, "как". Эта конфигурация задается в нескольких файлах сборки в вашем проекте (и подпроектах).
Входными данными задачи могут быть файлы и каталоги, а также другая информация, закодированная как типы Java (целые числа, строки или пользовательские классы). Выходными данными могут быть только каталоги или файлы, поскольку они должны быть записаны на диск. Подключение выходных данных одной задачи к входным данным другой связывает задачи вместе, так что одна должна выполняться перед другой.
Gradle позволяет писать произвольный код и объявления задач в файлах сборки, но это может усложнить понимание сборки инструментами и ее поддержку. Например, вы можете написать тесты для кода внутри плагинов, но не в файлах сборки. Вместо этого следует ограничить логику сборки и объявления задач плагинами (которые определяете вы или кто-то другой) и объявить, как вы хотите использовать эту логику в файлах сборки.
Что происходит при запуске сборки Gradle?
Сборка Gradle выполняется в три этапа. На каждом из этих этапов выполняются разные части кода, которые вы определяете в файлах сборки.
- На этапе инициализации определяется, какие проекты и подпроекты будут включены в сборку, и настраиваются пути к классам, содержащие файлы сборки и примененные плагины. На этом этапе основное внимание уделяется файлу настроек, в котором вы объявляете проекты для сборки и места, откуда можно получить плагины и библиотеки.
- Конфигурация регистрирует задачи для каждого проекта и выполняет файл сборки, чтобы применить спецификацию сборки пользователя. Важно понимать, что у вашего кода конфигурации не будет доступа к данным или файлам, созданным во время выполнения.
- Выполнение. На этом этапе происходит сборка приложения. Результатом конфигурации является направленный ациклический граф (DAG) задач, представляющий все необходимые шаги сборки, запрошенные пользователем (задачи, указанные в командной строке или по умолчанию в файлах сборки). Этот граф представляет отношения между задачами, которые либо явно указаны в объявлении задачи, либо основаны на ее входных и выходных данных. Если входные данные задачи являются выходными данными другой задачи, то она должна выполняться после другой задачи. На этом этапе устаревшие задачи выполняются в порядке, определенном в графе. Если входные данные задачи не изменились с момента ее последнего выполнения, Gradle пропустит ее.
Подробную информацию можно найти в статье Build lifecycle (Жизненный цикл сборки).
DSL конфигурации
Gradle использует предметно-ориентированный язык (DSL) для настройки сборок. Этот декларативный подход фокусируется на указании ваших данных, а не на написании пошаговых (императивных) инструкций. Файлы сборки можно писать на Kotlin или Groovy, но мы настоятельно рекомендуем использовать Kotlin.
DSLs пытаются облегчить всем, экспертам в предметной области и программистам, внесение вклада в проект, определяя небольшой язык, который представляет данные более естественным образом. Плагины Gradle могут расширять DSL, чтобы настраивать данные, необходимые для их задач.
Например, настройка части сборки для Android может выглядеть следующим образом:
Kotlin
android { namespace = "com.example.app" compileSdk { version = release(36) { minorApiLevel = 1 } } // ... defaultConfig { applicationId = "com.example.app" minSdk { version = release(23) } targetSdk { version = release(36) } // ... } }
Яркий
android { namespace = 'com.example.app' compileSdk { version = release(36) { minorApiLevel = 1 } } // ... defaultConfig { applicationId = 'com.example.app' minSdk { version = release(23) } targetSdk { version = release(36) } // ... } }
Код DSL выглядит примерно так:
fun Project.android(configure: ApplicationExtension.() -> Unit) {
...
}
interface ApplicationExtension {
var namespace: String?
fun compileSdk(configure: CompileSdkSpec.() -> Unit) {
...
}
val defaultConfig: DefaultConfig
fun defaultConfig(configure: DefaultConfig.() -> Unit) {
...
}
}
Каждый блок в DSL представлен функцией, которая принимает лямбду для его настройки, и свойством с тем же именем для доступа к нему. Это делает код в ваших файлах сборки более похожим на спецификацию данных.
Внешние зависимости
Система сборки Maven представила спецификацию, хранилище и систему управления зависимостями. Библиотеки хранятся в репозиториях (серверах или каталогах) вместе с метаданными, включая их версию и зависимости от других библиотек. Вы указываете, в каких хранилищах выполнять поиск и какие версии зависимостей использовать, а система сборки скачивает их в процессе сборки.
Артефакты Maven идентифицируются по названию группы (компания, разработчик и т. д.), названию артефакта (название библиотеки) и его версии. Обычно это значение представлено как group:artifact:version.
Такой подход значительно упрощает управление сборками. Такие хранилища часто называют репозиториями Maven, но все дело в том, как упаковываются и публикуются артефакты. Эти хранилища и метаданные повторно используются в нескольких системах сборки, включая Gradle (и Gradle может публиковать в эти хранилища). Общедоступные репозитории позволяют делиться кодом со всеми, а репозитории компании хранят внутренние зависимости внутри организации.
Вы также можете разбить проект на подпроекты (в Android Studio они называются модулями), которые также можно использовать в качестве зависимостей. Каждый подпроект создает выходные данные (например, JAR-файлы), которые могут использоваться подпроектами или проектом верхнего уровня. Это может сократить время сборки за счет изоляции частей, которые необходимо перестроить, а также лучше разделить обязанности в приложении.
Подробнее о том, как указать зависимости, рассказывается в разделе Добавление зависимостей сборки.
Варианты сборки
При создании приложения для Android обычно требуется создать несколько вариантов. Варианты содержат разный код или создаются с разными параметрами и состоят из типов сборки и версий продукта.
Типы сборки меняют объявленные параметры сборки. По умолчанию AGP настраивает типы сборки release и debug, но вы можете изменить их и добавить другие (например, для промежуточного или внутреннего тестирования).
Отладочная сборка не минифицирует и не обфусцирует приложение, что ускоряет его сборку и сохраняет все символы как есть. Она также помечает приложение как доступное для отладки, подписывая его общим ключом отладки и разрешая доступ к установленным файлам приложения на устройстве. Это позволяет исследовать сохраненные данные в файлах и базах данных во время работы приложения.
Конечная сборка оптимизирует приложение, подписывает его ключом выпуска и защищает установленные файлы приложения.
С помощью версий продукта можно изменить включенные варианты источников и зависимостей для приложения. Например, вы можете создать демо- и полную версии приложения или бесплатную и платную. Общий исходный код записывается в каталог набора исходных файлов main, а в наборе исходных файлов, названном в честь варианта, исходный код переопределяется или добавляется.
AGP создает варианты для каждой комбинации типа сборки и версии продукта. Если вы не определите разновидности, варианты будут названы в соответствии с типами сборки. Если вы укажете оба значения, вариант будет называться <flavor><Buildtype>. Например, если у вас есть типы сборки release и debug и варианты demo и full, AGP создаст следующие варианты:
demoReleasedemoDebugfullReleasefullDebug
Дальнейшие действия
Теперь, когда вы ознакомились с концепциями сборки, посмотрите на структуру сборки Android в своем проекте.