Gradle یک سیستم ساخت است که کامپایل، تست و بستهبندی برنامههای Android را خودکار میکند. برخلاف Apache Ant یا Maven، از ساخت افزایشی و ذخیرهسازی نتایج پشتیبانی میکند. جزئیات بیشتر درباره قابلیتها را در مستندات رسمی Gradle بخوانید. از سال ۲۰۱۳ این ابزار به عنوان سیستم استاندارد ساخت برای پروژههای Android در Android Studio استفاده میشود.
نکات اصلی
Gradle یک ابزار خودکارسازی ساخت متنباز به زبان جاوا است که روی JVM کار میکند. این ابزار کد منبع، وابستگیها و منابع را دریافت کرده و در خروجی یک برنامه آماده — APK یا AAB برای Android — تحویل میدهد. در هسته Gradle مفهوم گراف غیرمدور جهتدار وظایف (DAG) قرار دارد، جایی که هر وظیفه یک واحد کاری اتمی است و ارتباطات بین آنها ترتیب اجرا را مشخص میکند. برخلاف Make یا Ant، Gradle نیازی به توصیف دستی توالی مراحل ندارد: کافیست وابستگیهای بین وظایف را اعلام کنید و سیستم خودش ترتیب بهینه را میسازد. این رویکرد Gradle را برای پروژههای با هر اندازهای انعطافپذیر و مقیاسپذیر میکند.
سیستم از سه فاز اجرا استفاده میکند: مقداردهی اولیه (تعیین پروژههای شرکتکننده)، پیکربندی (ساخت گراف وظایف) و اجرا (راهاندازی وظایف به ترتیب مناسب). فاز پیکربندی تفاوت کلیدی Gradle است: کل اسکریپت ساخت قبل از راهاندازی وظایف اجرا میشود که امکان تغییر پویای گراف را بسته به شرایط فراهم میکند. این امکان را میدهد، مثلاً، وظایفی را فقط برای انواع خاصی از ساخت بدون تکرار کد اضافه کنید. سازنده به زبان Groovy نوشته شده است، اما فایلهای پیکربندی از دو زبان پشتیبانی میکنند: Groovy DSL و Kotlin DSL.
پلاگین Android برای Gradle — com.android.application و com.android.library هستند که وظایفی برای کار با ابزارهای Android به پروژه اضافه میکنند. وقتی توسعهدهنده ساخت را اجرا میکند، Gradle دهها وظیفه را به ترتیب انجام میدهد: کامپایل Kotlin و Java از طریق javac یا kotlinc، پردازش منابع از طریق AAPT2، تولید R.java، کامپایل بایتکد به DEX از طریق D8 یا R8، امضا و زیپ کردن APK. هر وظیفه بررسی میکند که آیا دادههای ورودی آن تغییر کرده است یا خیر، و اگر نه — از نتیجه ذخیرهشده استفاده میکند. این مکانیزم ساخت افزایشی نامیده میشود و کامپایل مجدد را در مقایسه با ساخت کامل ۶۰–۸۰٪ سریعتر میکند.
پیکربندی ماژول Android در بلوک android فایل build.gradle.kts تعریف میشود. در داخل بلوک، compileSdk، minSdk، targetSdk، نسخه برنامه، امضاها و سایر پارامترها تعیین میشوند. Gradle بهطور خودکار برای هر ماژول چندین نوع ساخت ایجاد میکند — ترکیبی از نوع (release, debug) و flavor. مثلاً، برای ماژولی با دو flavor و دو نوع، Gradle چهار وظیفه تولید میکند: assembleDemoDebug، assembleDemoRelease، assembleFullDebug، assembleFullRelease. همه این وظایف را میتوان جداگانه اجرا کرد یا با یک دستور برای همه انواع بهطور همزمان راهاندازی کرد.
هر پروژه Android شامل دو سطح پیکربندی است: build.gradle.kts ریشه (تنظیمات برای همه ماژولها) و build.gradle.kts ماژول (تنظیمات برای ماژول خاص). در فایل ریشه، پلاگینها بدون اعمال، مخازن و متغیرهای مشترک اعلام میشوند. در فایل ماژول، پلاگینها به ماژول خاص اعمال میشوند و پارامترهای ساخت پیکربندی میشوند. این رویکرد امکان مدیریت متمرکز نسخههای وابستگی را از طریق کاتالوگ نسخه یا بلوک ext فراهم میکند.
@Suppress("UnstableApiUsage")
plugins {
id("com.android.application") version "8.2.2"
id("org.jetbrains.kotlin.android") version "1.9.22"
}
android {
namespace = "com.example.myapp"
compileSdk = 34
defaultConfig {
applicationId = "com.example.myapp"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
}
}بلوک dependencies — یکی دیگر از عناصر حیاتی build.gradle.kts است. در آن کتابخانهها، ماژولها و وابستگیهای فایلی که برنامه به آنها نیاز دارد فهرست میشوند. Gradle از چندین پیکربندی وابستگی پشتیبانی میکند: implementation (فقط برای ماژول فعلی قابل دسترسی است)، api (برای ماژولهای وابسته نیز قابل دسترسی است)، testImplementation (فقط برای تستها)، androidTestImplementation (برای تستهای ابزاری) و compileOnly (فقط در مرحله کامپایل). هر پیکربندی قابلیت مشاهده کلاسها را در گراف وابستگی مدیریت میکند که بر زمان ساخت و اندازه مصنوع نهایی تأثیر میگذارد.
dependencies {
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
implementation("androidx.activity:activity-compose:1.8.2")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
}Build variant — ترکیبی از build type و product flavor است که نسخهای از برنامه را با تنظیمات، کد و منابع منحصربهفرد تعریف میکند. Build type (نوع ساخت) پارامترهای بستهبندی را تعیین میکند: debug (با اشکالزدایی و پسوند .debug) یا release (با مبهمسازی و امضا). Product flavor (طعم محصول) انواع عملکردی را مشخص میکند: مثلاً، demo (نسخه محدود) و full (نسخه کامل با قابلیتهای اضافی). Gradle بهطور خودکار برای هر ترکیب وظایفی تولید میکند که امکان ساخت همه نسخهها را با یک دستور فراهم میکند.
android {
buildTypes {
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
debug {
applicationIdSuffix = ".debug"
}
}
flavorDimensions += "version"
productFlavors {
create("demo") {
dimension = "version"
applicationIdSuffix = ".demo"
}
create("full") {
dimension = "version"
applicationIdSuffix = ".full"
}
}
}به هر build variant یک source set جداگانه مربوط میشود. Gradle از دایرکتوریهای src/demo/release، src/full/debug و غیره استفاده میکند که در آنها منابع، مانیفستها و کدهای منحصربهفرد برای نوع خاص ذخیره میشود. کد مشترک در src/main باقی میماند. این رویکرد امکان استفاده مجدد از منطق اصلی و جایگزینی فقط بخشهای متفاوت را فراهم میکند: رشتهها، آیکونها، نقاط پایانی API یا فایلهای پیکربندی. Source set میتواند هر منبعی را از main بازنویسی کند: مانیفست، drawable، values یا حتی کلاسهای Kotlin. هنگام ساخت نوع خاص، Gradle فایلها را از main و source set مربوطه ترکیب میکند و فایلهای نوع اولویت دارند.
اکوسیستم پلاگینهای Gradle تمام مراحل توسعه برنامههای Android را پوشش میدهد. پلاگینهای رسمی Google شامل com.android.application (برای ماژول برنامه)، com.android.library (برای ماژول کتابخانه)، com.android.test (برای ماژولهای تست) و پلاگینهای Kotlin از JetBrains هستند. پلاگینها وظایف جدیدی به پروژه اضافه میکنند، DSL را با بلوکهای پیکربندی جدید گسترش میدهند و ابزارهای اضافی را متصل میکنند. بدون پلاگین com.android.application پروژه نمیتواند APK بسازد: این پلاگین تمام وظایف خاص Android را ثبت کرده و آنها را در گراف ساخت متصل میکند.
پلاگینهای شخص ثالث وظایف محدودتری را حل میکنند. Google Services (com.google.gms.google-services) Firebase و Google Play Services را ادغام میکند و بهطور خودکار google-services.json را در ساخت قرار میدهد. Hilt (dagger.hilt.android.plugin) کدی برای تزریق وابستگیها در مرحله کامپایل تولید میکند. Safe Args (androidx.navigation.safeargs.kotlin) کلاسهای نوعامن برای ناوبری بین فرگمنتها ایجاد میکند. هر پلاگین در build.gradle.kts ریشه از طریق بلوک plugins متصل میشود و معمولاً به پیکربندی حداقلی نیاز دارد. Gradle بهطور خودکار وابستگیهای انتقالی بین پلاگینها را حل میکند و سازگاری نسخهها را از طریق فایلهای Bom و کاتالوگ نسخه تضمین میکند.
تسک (وظیفه) — واحد کاری اتمی در Gradle است. هر تسک دادههای ورودی، دادههای خروجی و یک اقدام دارد. تسکهای داخلی برای Android شامل assemble (ساخت همه انواع)، lint (بررسی کد)، test (اجرای تستهای واحد) و clean (پاکسازی فایلهای موقت) هستند. توسعهدهنده میتواند تسکهای سفارشی خود را با استفاده از Groovy یا Kotlin DSL اضافه کند. تسکهای سفارشی برای خودکارسازی عملیات روتین مفید هستند: تولید گزارشها، کپی مصنوعات، استقرار روی دستگاههای تست یا ادغام با سیستمهای CI.
tasks.register("printBuildInfo") {
description = "اطلاعات ساخت را نمایش میدهد"
group = "custom"
doLast {
println("Build variant: ${project.name}")
println("Version: ${android.defaultConfig.versionName}")
}
}هر تسک میتواند از طریق مکانیزم dependsOn به تسکهای دیگر وابسته باشد. اگر تسک A به تسک B وابسته باشد، Gradle تضمین میکند که B قبل از A اجرا شود. سیستم نیازی به تعیین دستی ترتیب برای هر جفت ندارد — کافیست وابستگیها را اعلام کنید و Gradle یک گراف جهتدار بهینهشده برای اجرای موازی تسکهای مستقل میسازد. تسکهای داخلی پلاگین Android از قبل به هم متصل هستند: lint به کامپایل وابسته است، test به assemble وابسته است، assembleDebug به compileDebugKotlin وابسته است. توسعهدهنده میتواند تسکهای خود را با استفاده از dependsOn، mustRunAfter یا shouldRunAfter در هر گرهای از گراف قرار دهد.
یکی از مشکلات رایج — تعارض نسخههای وابستگی است، زمانی که دو کتابخانه به نسخههای مختلف یک وابستگی انتقالی نیاز دارند. Gradle خطای تعارض را گزارش میدهد، اما همیشه راهحل خودکار ارائه نمیدهد. برای تشخیص از دستور ./gradlew :app:dependencies استفاده کنید که درخت کامل وابستگیها را نمایش میدهد. توصیه میشود نسخه کتابخانه تعارضآمیز را از طریق بلوک resolutionStrategy بهاجبار تعیین کنید. سناریوی رایج دیگر — ساخت آهسته به دلیل عدم پردازش افزایشی است. بررسی کنید که همه پلاگینها بهروز هستند، Gradle Daemon فعال است (org.gradle.daemon=true) و در gradle.properties حافظه کافی تنظیم شده است: org.gradle.jvmargs=-Xmx4096m.
مشکلات ذخیرهسازی پس از بهروزرسانی وابستگیها رخ میدهد: Gradle ممکن است از کش قدیمی استفاده کند و ساخت با خطا پایان یابد. راهحل — ساخت را با پرچم --refresh-dependencies اجرا کنید یا کش را بهصورت دستی از طریق ./gradlew cleanBuildCache پاک کنید. سومین خطای رایج — ناسازگاری نسخههای Android Gradle Plugin (AGP) و Gradle. هر نسخه AGP به نسخه حداقلی خاصی از Gradle نیاز دارد. جدول سازگاری در developer.android.com منتشر میشود. اگر نسخهها ناسازگار باشند، Gradle در مرحله پیکربندی با خطایی حاوی پیام حداقل نسخه مورد نیاز خاتمه مییابد. همیشه بررسی کنید که نسخه Gradle wrapper با الزامات AGP مطابقت دارد.
سوالات متداول
Gradle یک برنامه خودکارساز ساخت پروژهها است. این برنامه کد منبع شما به Kotlin یا Java را میگیرد، کتابخانهها را از اینترنت متصل میکند، همه را به بایتکد کامپایل کرده و در APK بستهبندی میکند. روی JVM کار میکند و از اسکریپتهای اعلامی به جای دستورالعملهای دستی استفاده میکند. توسعهدهنده فقط باید قوانین را توصیف کند و بقیه کار را Gradle خودش انجام میدهد.
Build.gradle به زبان Groovy نوشته میشود — زبانی پویا با نحو منعطف و دقت کمتر. Build.gradle.kts از Kotlin DSL استفاده میکند: تایپبندی قوی، تکمیل خودکار در Android Studio و بررسی خطاها در مرحله کامپایل. Google برای همه پروژههای جدید Kotlin DSL را توصیه میکند. فایلهای Groovy مهاجرت آسانتری دارند، اما فایلهای Kotlin در نگهداری قابلاطمینانتر هستند.
Gradle Daemon (org.gradle.daemon=true) و ساخت موازی (org.gradle.parallel=true) را فعال کنید. حافظه JVM را از طریق org.gradle.jvmargs به ۴–۸ گیگابایت افزایش دهید. از پیکربندی پروژهها بر اساس تقاضا استفاده کنید (org.gradle.configureondemand=true). برای پروژههای Android، ذخیرهسازی وظایف و ساخت فقط برای ABI مورد نیاز را پیکربندی کنید. در Android Studio از Build Analyzer برای یافتن نقاط تنگنا استفاده کنید.
Build variant — ترکیبی از build type (مثلاً debug یا release) و product flavor (مثلاً demo یا full) است. هر نوع میتواند نام بسته، نسخه، منابع و فایلهای مبدأ خود را داشته باشد. Gradle بهطور خودکار یک وظیفه ساخت جداگانه برای هر نوع ایجاد میکند. این امکان ساخت چندین نسخه از برنامه را از یک پروژه فراهم میکند.
وابستگیها در بلوک dependencies فایل build.gradle.kts اضافه میشوند. فرمت نوشتار: configuration("group:artifact:version"). مثلاً، implementation("androidx.core:core-ktx:1.12.0"). برای تستها از testImplementation، برای تستهای ابزاری از androidTestImplementation استفاده کنید. نسخهها را میتوان به راحتی در یک کاتالوگ نسخه جداگانه (version catalog) از طریق فایل libs.versions.toml قرار داد.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید