Gradle è un sistema di build che automatizza la compilazione, il test e il confezionamento delle applicazioni Android. A differenza di Apache Ant o Maven, supporta il build incrementale e la memorizzazione nella cache dei risultati. Per saperne di più sulle sue funzionalità, consultare la documentazione ufficiale di Gradle. Dal 2013, lo strumento è utilizzato come sistema di build standard per i progetti Android in Android Studio.
Punti chiave
Gradle è un strumento di automazione del build open source scritto in Java, che funziona sulla JVM. Prende come input codice sorgente, dipendenze e risorse, e produce come output un'applicazione pronta — APK o AAB per Android. Al suo interno, Gradle utilizza il concetto di un Grafo Aciclico Diretto (DAG) di task, dove ogni task è un'unità atomica di lavoro e le connessioni tra di essi determinano l'ordine di esecuzione. A differenza di Make o Ant, Gradle non richiede la descrizione manuale di una sequenza di passaggi: basta dichiarare le dipendenze tra i task, e il sistema determinerà automaticamente l'ordine ottimale. Questo approccio rende Gradle flessibile e scalabile per progetti di qualsiasi dimensione.
Il sistema utilizza tre fasi di esecuzione: inizializzazione (identificazione dei progetti partecipanti), configurazione (costruzione del grafo dei task) ed esecuzione (esecuzione dei task nell'ordine richiesto). La fase di configurazione è una caratteristica distintiva di Gradle: l'intero script di build viene eseguito prima dell'inizio dei task, consentendo modifiche dinamiche del grafo in base alle condizioni. Ciò rende possibile, ad esempio, aggiungere task solo per varianti di build specifiche senza duplicare codice. Il builder è scritto in Groovy, ma i file di configurazione supportano due linguaggi: Groovy DSL e Kotlin DSL.
Il plugin Android per Gradle è costituito da com.android.application e com.android.library, che aggiungono task al progetto per lavorare con gli strumenti Android. Quando uno sviluppatore avvia un build, Gradle esegue sequenzialmente decine di task: compilare Kotlin e Java tramite javac o kotlinc, elaborare le risorse tramite AAPT2, generare R.java, compilare il bytecode in DEX tramite D8 o R8, firmare e comprimere l'APK. Ogni task controlla se i suoi dati di input sono cambiati e, in caso contrario, utilizza il risultato memorizzato nella cache. Questo meccanismo è chiamato build incrementale e accelera la ricompilazione del 60–80% rispetto a una ricostruzione completa.
La configurazione del modulo Android viene impostata nel blocco android del file build.gradle.kts. All'interno del blocco vengono definiti compileSdk, minSdk, targetSdk, versione dell'app, firme e altri parametri. Gradle crea automaticamente diverse varianti di build per ogni modulo — una combinazione di tipo (release, debug) e variante. Ad esempio, per un modulo con due varianti e due tipi, Gradle genera quattro task: assembleDemoDebug, assembleDemoRelease, assembleFullDebug, assembleFullRelease. Tutti questi task possono essere eseguiti individualmente o avviati con un unico comando per tutte le varianti contemporaneamente.
Ogni progetto Android contiene due livelli di configurazione: il build.gradle.kts root (impostazioni per tutti i moduli) e il build.gradle.kts a livello di modulo (impostazioni per un modulo specifico). Nel file root, i plugin vengono dichiarati senza applicazione, i repository e le variabili comuni. Nel file del modulo, i plugin vengono applicati al modulo specifico e vengono configurati i parametri di build. Questo approccio consente la gestione centralizzata delle versioni delle dipendenze tramite un catalogo versioni o blocco 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"
}
}Il blocco dependencies è un altro elemento critico di build.gradle.kts. Elenca le librerie, i moduli e le dipendenze file di cui l'applicazione ha bisogno. Gradle supporta diverse configurazioni di dipendenza: implementation (disponibile solo per il modulo corrente), api (disponibile anche per i moduli dipendenti), testImplementation (solo per i test), androidTestImplementation (per i test strumentati) e compileOnly (solo in fase di compilazione). Ogni configurazione gestisce la visibilità delle classi nel grafo delle dipendenze, influenzando il tempo di build e la dimensione dell'artefatto finale.
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")
}Una build variant è una combinazione di tipo di build e variante di prodotto che definisce una versione dell'app con impostazioni, codice e risorse unici. Il tipo di build definisce i parametri di confezionamento: debug (con debug e suffisso .debug) o release (con offuscamento e firma). La variante di prodotto definisce varianti funzionali: ad esempio, demo (versione limitata) e full (versione completa con funzionalità aggiuntive). Gradle genera automaticamente task per ogni combinazione, consentendo di costruire tutte le versioni con un unico comando.
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"
}
}
}Ogni build variant ha un source set separato. Gradle utilizza le directory src/demo/release, src/full/debug e altre, che memorizzano risorse, manifesti e file sorgente unici per una variante specifica. Il codice comune rimane in src/main. Questo approccio consente di riutilizzare la logica principale e sostituire solo le parti differenti: stringhe, icone, endpoint API o file di configurazione. Un source set può sovrascrivere qualsiasi risorsa da main: manifesto, drawable, values o persino classi Kotlin. Durante la costruzione di una variante specifica, Gradle unisce i file da main e dal source set corrispondente, con i file della variante che hanno priorità.
L'ecosistema di plugin Gradle copre tutte le fasi dello sviluppo di applicazioni Android. I plugin ufficiali di Google includono com.android.application (per il modulo app), com.android.library (per il modulo libreria), com.android.test (per i moduli di test) e i plugin Kotlin di JetBrains. I plugin aggiungono nuovi task al progetto, estendono il DSL con nuovi blocchi di configurazione e collegano strumenti aggiuntivi. Senza il plugin com.android.application, un progetto non può costruire un APK: questo plugin registra tutti i task specifici di Android e li collega nel grafo di build.
I plugin di terze parti risolvono task più specifici. Google Services (com.google.gms.google-services) integra Firebase e Google Play Services, inserendo automaticamente google-services.json nel build. Hilt (dagger.hilt.android.plugin) genera codice di injection delle dipendenze in fase di compilazione. Safe Args (androidx.navigation.safeargs.kotlin) crea classi type-safe per la navigazione tra fragment. Ogni plugin viene aggiunto nel build.gradle.kts root tramite il blocco plugins e di solito richiede una configurazione minima. Gradle risolve automaticamente le dipendenze transitive tra i plugin e garantisce la compatibilità delle versioni tramite file Bom e cataloghi versioni.
Un task è un'unità atomica di lavoro in Gradle. Ogni task ha dati di input, dati di output e un'azione. I task integrati per Android includono assemble (costruzione di tutte le varianti), lint (controllo del codice), test (esecuzione di test unitari) e clean (pulizia dei file temporanei). Gli sviluppatori possono aggiungere i propri task utilizzando Groovy o Kotlin DSL. I task personalizzati sono utili per automatizzare operazioni di routine: generare report, copiare artefatti, distribuire su dispositivi di test o integrarsi con sistemi CI.
tasks.register("printBuildInfo") {
description = "Mostra informazioni di build"
group = "custom"
doLast {
println("Build variant: ${project.name}")
println("Version: ${android.defaultConfig.versionName}")
}
}Ogni task può dipendere da altri task tramite il meccanismo dependsOn. Se il task A dipende dal task B, Gradle garantisce che B verrà eseguito prima di A. Il sistema non richiede la specifica manuale dell'ordine per ogni coppia — basta dichiarare le dipendenze, e Gradle costruirà un grafo diretto ottimizzato per l'esecuzione parallela di task indipendenti. I task integrati del plugin Android sono già collegati tra loro: lint dipende dalla compilazione, test dipende da assemble, assembleDebug dipende da compileDebugKotlin. Gli sviluppatori possono inserire i propri task in qualsiasi nodo del grafo utilizzando dependsOn, mustRunAfter o shouldRunAfter.
Uno dei problemi frequenti sono i conflitti di versione delle dipendenze, quando due librerie richiedono versioni diverse della stessa dipendenza transitiva. Gradle segnala un errore di conflitto, ma non offre sempre una soluzione automatica. Per la diagnosi, utilizzare il comando ./gradlew :app:dependencies, che visualizza l'albero completo delle dipendenze. Si consiglia di forzare la versione della libreria in conflitto tramite il blocco resolutionStrategy. Un altro scenario comune è il build lento a causa della mancanza di elaborazione incrementale. Assicurarsi che tutti i plugin siano aggiornati, che Gradle Daemon sia abilitato (org.gradle.daemon=true) e che sia impostata memoria sufficiente in gradle.properties: org.gradle.jvmargs=-Xmx4096m.
I problemi di cache sorgono dopo l'aggiornamento delle dipendenze: Gradle potrebbe utilizzare una cache obsoleta e il build fallisce. La soluzione è eseguire il build con il flag --refresh-dependencies o svuotare manualmente la cache tramite ./gradlew cleanBuildCache. Il terzo errore più comune è l'incompatibilità di versione tra Android Gradle Plugin (AGP) e Gradle. Ogni versione di AGP richiede una versione minima specifica di Gradle. La tabella di compatibilità è pubblicata su developer.android.com. Se le versioni sono incompatibili, Gradle fallisce in fase di configurazione con un messaggio sulla versione minima richiesta. Verificare sempre che la versione del wrapper di Gradle corrisponda ai requisiti di AGP.
Domande frequenti
Gradle è un programma di automazione per la costruzione di progetti. Prende il tuo codice sorgente in Kotlin o Java, collega le librerie da Internet, compila tutto in bytecode e lo impacchetta in APK. Funziona sulla JVM e utilizza script dichiarativi invece di istruzioni manuali. Lo sviluppatore deve solo descrivere le regole, e Gradle fa il resto.
Build.gradle è scritto in Groovy — un linguaggio dinamico con sintassi flessibile e minore rigidità. Build.gradle.kts utilizza Kotlin DSL: tipizzazione forte, completamento automatico in Android Studio e controllo degli errori in fase di compilazione. Google raccomanda Kotlin DSL per tutti i nuovi progetti. I file Groovy sono più facili da migrare, ma i file Kotlin sono più affidabili nella manutenzione.
Abilitare Gradle Daemon (org.gradle.daemon=true) e il build parallelo (org.gradle.parallel=true). Aumentare la memoria JVM a 4–8 GB tramite org.gradle.jvmargs. Utilizzare la configurazione dei progetti su richiesta (org.gradle.configureondemand=true). Per i progetti Android, configurare la cache dei task e costruire solo per l'ABI richiesto. In Android Studio, eseguire Build Analyzer per trovare i colli di bottiglia.
Una build variant è una combinazione di tipo di build (ad esempio, debug o release) e variante di prodotto (ad esempio, demo o full). Ogni variante può avere il proprio nome del package, versione, risorse e file sorgente. Gradle crea automaticamente un task di build separato per ogni variante. Questo consente di costruire più versioni dell'applicazione da un singolo progetto.
Le dipendenze vengono aggiunte nel blocco dependencies del file build.gradle.kts. Il formato è: configuration("group:artifact:version"). Ad esempio, implementation("androidx.core:core-ktx:1.12.0"). Per i test utilizzare testImplementation, per i test strumentati — androidTestImplementation. Le versioni sono comodamente organizzate in un catalogo versioni separato tramite il file libs.versions.toml.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche