Gradle представляет набор инструментов для автоматической сборки, который позволяет настраивать и управлять сборкой проектов с помощью специальных файлов конфигурации. В частности, можно задать, как будет собираться проект, какие зависимости необходимо добавить для успешной сборки и каким должен быть конечный результат (или результаты) процесса сборки. Правила конфигурации для сборки проекта объявляются в файлах сборки Gradle и сценариях на основе языка программирования Groovy. Стоит отметить, что в Android Studio интеграция Gradle обеспечивается через специальный одноименный плагин.
Gradle имеет предопределенный набор параметров конфигурации по умолчанию, которые будут использоваться, если только настройки в файлах сборки не переопределят их. Это означает, что сборки могут выполняться с минимальной конфигурацией, необходимой разработчику. Изменения в файлах сборки необходимы только в том случае, если конфигурация по умолчанию не соответствует текущим потребностям сборки.
Один из ключевых моментов конфигурации Gradle — это зависимости - модули, которые необходимы для работы приложения и функционаьность которых используется в приложении. Зависимости Gradle можно разделить на локальные и удаленные. Локальная зависимость ссылается на элемент, присутствующий в локальной файловой системе на текущем компьютере, на котором выполняется сборка. Удаленная зависимость относится к элементу, который присутствует на удаленном сервере (обычно называемом репозиторием).
Удаленные зависимости для проектов Android Studio обрабатываются с помощью другого инструмента управления проектами под названием Maven. Если удаленная зависимость объявлена в файле сборки Gradle с использованием синтаксиса Maven, то зависимость будет автоматически загружена из назначенного репозитория и включена в процесс сборки.
Gradle также обеспечивает поддержку вариантов сборки для проектов Android Studio. Это позволяет создавать несколько вариантов приложения из одного проекта. Android работает на множестве различных устройств с разными типами процессоров и размерами экранов. Чтобы охватить как можно более широкий диапазон типов и размеров устройств, часто бывает необходимо создать несколько вариантов приложения (например, один с пользовательским интерфейсом для телефонов, а другой — для планшетов).
С каждым проектом Android Studio связан файл AndroidManifest.xml (файл манифеста), который содержит сведения о конфигурации приложения. В файлах сборки Gradle можно указать несколько записей манифеста, которые затем автоматически генерируются в файл манифеста при сборке проекта. Эта возможность дополняет функцию вариантов сборки, позволяя настраивать такие элементы, как номер версии приложения, идентификатор приложения и информацию о версии SDK, для каждого варианта сборки.
ProGuard — это инструмент, включенный в Android Studio, который оптимизирует, сжимает и запутывает байт-код Java, чтобы сделать его более эффективным и трудным для дизассемблирования/декомпиляции. Файлы сборки Gradle позволяют контролировать, будет ли ProGuard запускаться при сборке проекта.
Все файлы Gradle в проекте можно увидеть в узле Gradle Scripts:
Файл gradle.properties содержит в основном настройки флагов командной строки, используемым виртуальной машиной Java (JVM), а также указывают, использует ли проект библиотеки AndroidX и поддерживает ли стиль кодирования Kotlin:
# Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects # org.gradle.parallel=true # AndroidX package structure to make it clearer which packages are bundled with the # Android operating system, and which are packaged with your app's APK android.useAndroidX=true # Kotlin code style for this project: "official" or "obsolete": kotlin.code.style=official # Enables namespacing of each library's R class so that its R class includes only the # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library android.nonTransitiveRClass=true
Обычно не требуется изменить какие-либо параметры в этом файле.
Файл settings.gradle.kts определяет, какие онлайн-репозитории следует использовать, когда системе сборки необходимо загрузить и установить любые дополнительные библиотеки и плагины, необходимые для сборки проекта, а также имя проекта. Типичный файл settings.gradle.kts выглядит следующим образом:
pluginManagement { repositories { google { content { includeGroupByRegex("com\.android.*") includeGroupByRegex("com\.google.*") includeGroupByRegex("androidx.*") } } mavenCentral() gradlePluginPortal() } } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() } } rootProject.name = "HelloApp" include(":app")
Каждый проект содержит один файл сборки Gradle верхнего уровня. Этот файл указан как build.gradle.kts (Project: <имя проекта>)
По умолчанию он имеет содержимое типа следующего:
plugins { alias(libs.plugins.androidApplication) apply false alias(libs.plugins.jetbrainsKotlinAndroid) apply false }
В большинстве случаев не требуется изменять данных файл.
Проект приложения может состоять из одного или нескольких модулей. И для каждого модуля потребуется собственный файл сборки Gradle. По умолчанию, когда создается проект в Android Studio, в нем создается один модулья, который называется app. Соответственно для него определяется файл сборки Gradle уровня модуля, который называется build.gradle.kts (Module :app):
По умолчанию он выглядит примерно следующим образом:
plugins { alias(libs.plugins.androidApplication) alias(libs.plugins.jetbrainsKotlinAndroid) } android { namespace = "com.example.helloapp" compileSdk = 34 defaultConfig { applicationId = "com.example.helloapp" minSdk = 24 targetSdk = 34 versionCode = 1 versionName = "1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary = true } } buildTypes { release { isMinifyEnabled = false proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = "1.8" } buildFeatures { compose = true } composeOptions { kotlinCompilerExtensionVersion = "1.5.1" } packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" } } } dependencies { implementation(libs.androidx.core.ktx) implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.activity.compose) implementation(platform(libs.androidx.compose.bom)) implementation(libs.androidx.ui) implementation(libs.androidx.ui.graphics) implementation(libs.androidx.ui.tooling.preview) implementation(libs.androidx.material3) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(platform(libs.androidx.compose.bom)) androidTestImplementation(libs.androidx.ui.test.junit4) debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.test.manifest) }
Как правило, если требуется внести некоторые изменения в конфигурацию сборки модуля, то именно то место, где подобные изменения производятся. Вкратце рассмотрим основные секции файла.
Aайл сборки начинается с объявления плагинов приложения Android и Kotlin:
plugins { alias(libs.plugins.androidApplication) alias(libs.plugins.jetbrainsKotlinAndroid) }
Далее идет раздел android
, который начинается с объявляения пространствоа имен проекта и версии SDK, которая будет использоваться при сборке модуля:
android { namespace = "com.example.helloapp" compileSdk = 34
Элементы, объявленные в подразделе defaultConfig
, определяют элементы, которые будут созданы в файле AndroidManifest.xml
модуля во время сборки:
defaultConfig { applicationId = "com.example.helloapp" minSdk = 24 targetSdk = 34 versionCode = 1 versionName = "1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary = true } }
Подраздел buildTypes указывает, следует ли и как запускать ProGuard в APK-файле при сборке релизной версии приложения:
buildTypes { release { isMinifyEnabled = false proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } }
В текущей конфигурации ProGuard не будет запускаться при сборке модуля. Чтобы включить ProGuard, запись minifyEnabled
должна быть изменена с false
на true
.
А выражение proguardFiles()
определяет применяемые файлы ProGuard. Файл proguard-rules.pro можно найти в каталоге модулей проекта. Изменения, внесенные в этот файл, переопределяют настройки по умолчанию в файле
proguard-android.txt, который находится в каталоге установки Android SDK в папке "sdk/tools/proguard".
Поскольку в данном случае подраздел buildTypes не определяет конфигурацию для сборки в режиме отладки (режим debug
), то при отладке
будут использоваться значения по умолчанию (созданные без ProGuard, подписанные ключом отладки и включенными символами отладки).
Далее идет подразделы compileOptions и kotlinOptions которые определяют используемую при сборке проекта версию компилятора Java:
compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = "1.8" }
И в самом конце идет секция dependencies перечисляет все локальные и удаленные зависимости, от которых зависит модуль. Строки зависимостей в приведенном выше файле примера обозначают библиотеки Android, которые необходимо включить из репозитория Android:
dependencies { implementation(libs.androidx.core.ktx) implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.activity.compose) implementation(platform(libs.androidx.compose.bom)) implementation(libs.androidx.ui) implementation(libs.androidx.ui.graphics) implementation(libs.androidx.ui.tooling.preview) implementation(libs.androidx.material3) ..................................... }
Когда Gradle собирает проект, ему необходимо знать, какие библиотеки необходимы для завершения сборки и соответствующие номера их версий. И каталог версий - файле libs.versions.toml позволяет указать, какие версии каких библиотек будут использоваться в проекте. Этот файл имеет содержимое наподобие следующего:
[versions] agp = "8.3.0" kotlin = "1.9.0" coreKtx = "1.10.1" junit = "4.13.2" junitVersion = "1.1.5" espressoCore = "3.5.1" lifecycleRuntimeKtx = "2.6.1" activityCompose = "1.7.0" composeBom = "2023.08.00" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" } androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } androidx-ui = { group = "androidx.compose.ui", name = "ui" } androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } androidx-material3 = { group = "androidx.compose.material3", name = "material3" } [plugins] androidApplication = { id = "com.android.application", version.ref = "agp" } jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
Данный файл подразделен на три секции: [versions], [libraries] [plugins]. Чтобы понять, как работает каталог, в качестве примера рассмотрим подключение библиотеки "androidx-core-ktx". Итак, в секции [libraries] библиотека "androidx-core-ktx" объявлена следующим образом:
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
Параметр versions.ref
указывает, как на библиотеку будут ссылаться в секции [versions] - через имя "coreKtx".
В секции [versions] мы можем увидеть, что для этой библиотеки указана версия 1.10.1:
[versions] coreKtx = "1.10.1"
Наконец, библиотека объявляется в секции dependencies файла Gradle уровня модуля:
dependencies { implementation(libs.androidx.core.ktx) ......................................... }
Обратите внимание, что синтаксис ссылки на библиотеку в файле Gradle заключается в добавлении к имени, используемому в записи каталога [libraries], префикса "libs".