Gradle Basics & Build System (Android, Java)
Gradle is Android’s build system: it compiles code/resources, merges manifests, processes dependencies, shrinks/obfuscates (R8), signs, and outputs APK or AAB. In this page we learn the essential files, common configuration blocks, and commands you’ll use every day.
Where Gradle Fits
Source
Java/Kotlin + XML + assets
Gradle
Plugins + Tasks + Dependencies
R8/Packaging
S hrink/obfuscate/align/sign
Output
APK (debug/install) or AAB (Play)
Key Files in an Android Project
| File | Purpose |
|---|---|
settings.gradle / settings.gradle.kts | Declares which modules are included in the build. |
build.gradle (Project) | Repositories & plugin management for the whole project. |
app/build.gradle (Module) | Android plugin + android{} config, dependencies, build types, flavors. |
gradle/wrapper/ | Gradle Wrapper (fixed Gradle version for reproducible builds). |
gradle.properties | Global build flags (performance, JVM args, feature toggles). |
local.properties | Local machine paths (e.g., sdk.dir). Not committed to VCS. |
settings.gradle (Single or Multi-Module)
rootProject.name = "MyAndroidApp"
include(":app") // add more like ":core", ":feature-login"
Multi-module projects build faster (isolated changes) and enforce better architecture.
Project-level build.gradle
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
// Android Gradle Plugin (version example)
classpath 'com.android.tools.build:gradle:8.6.0'
}
}
Module app/build.gradle Essentials
plugins {
id 'com.android.application'
// id 'kotlin-android' if using Kotlin
}
android {
namespace "com.example.myapp"
compileSdk 34
defaultConfig {
applicationId "com.example.myapp"
minSdk 21
targetSdk 34
versionCode 1
versionName "1.0"
// BuildConfig & res values:
buildConfigField "String", "API_BASE", "\"https://api.example.com\""
resValue "string", "app_env", "prod"
// Manifest placeholders (used inside AndroidManifest.xml)
manifestPlaceholders = [ appAuthRedirectScheme: "myapp" ]
}
buildTypes {
debug {
applicationIdSuffix ".debug"
versionNameSuffix "-debug"
minifyEnabled false
}
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
// signingConfig signingConfigs.release (configured below)
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'com.google.android.material:material:1.12.0'
// Testing
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
}
Dependency Configurations (When to use which)
| Configuration | Meaning |
|---|---|
implementation | Normal runtime + compile dependency; not exposed to consumers. |
api | (Library modules) Exposes transitive APIs to consumers. |
compileOnly | Available at compile-time only (provided at runtime elsewhere). |
runtimeOnly | Only at runtime (not visible to compiler). |
testImplementation | Unit test dependencies. |
androidTestImplementation | Instrumentation test dependencies. |
Build Types vs Product Flavors
Build Types represent how you build (debug vs release). Flavors represent what you build (free vs paid, dev vs prod URLs).
android {
flavorDimensions "tier"
productFlavors {
dev {
dimension "tier"
applicationIdSuffix ".dev"
versionNameSuffix "-dev"
buildConfigField "String", "API_BASE", "\"https://dev.api.example.com\""
}
prod {
dimension "tier"
buildConfigField "String", "API_BASE", "\"https://api.example.com\""
}
}
}
Signing Configs (Release)
android {
signingConfigs {
release {
storeFile file("my-release-key.jks")
storePassword "***"
keyAlias "mykey"
keyPassword "***"
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
Gradle Wrapper & Common Commands
| Command | What it does |
|---|---|
./gradlew tasks | Lists available tasks. |
./gradlew assembleDebug | Builds a debug APK. |
./gradlew assembleRelease | Builds a release APK (requires signing). |
./gradlew bundleRelease | Builds a release AAB (Play Store upload). |
./gradlew clean | Deletes build outputs. |
./gradlew test | Runs unit tests. |
./gradlew connectedAndroidTest | Runs instrumentation tests on device/emulator. |
./gradlew dependencies | Prints dependency tree (debugging conflicts). |
R8 / ProGuard (Shrinking & Obfuscation)
R8 is enabled for release when minifyEnabled true. Add keep rules in proguard-rules.pro to prevent stripping critical classes (e.g., JSON models used via reflection).
# proguard-rules.pro examples
# Keep model classes (Gson/reflective)
-keep class com.example.myapp.model.** { *; }
# Keep names for JSON fields
-keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault
Resource Shrinking
Combine with R8 using shrinkResources true to remove unused resources in release builds.
Performance Tuning (gradle.properties)
# gradle.properties (project)
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.configureondemand=true
org.gradle.jvmargs=-Xmx4g -Dfile.encoding=UTF-8
# Enable configuration cache (AGP/Gradle version dependent)
org.gradle.configuration-cache=true
Multi-Module Setup (Example)
// settings.gradle
include(":app", ":core", ":feature-login")
// feature-login/build.gradle (Android Library)
plugins { id 'com.android.library' }
android {
namespace "com.example.feature.login"
compileSdk 34
defaultConfig { minSdk 21 }
}
dependencies {
implementation project(':core')
implementation 'androidx.appcompat:appcompat:1.7.0'
}
Benefits: faster incremental builds, independent testing, clearer boundaries.
Versioning Strategies
- Keep
versionCodeincreasing (integer).versionNameis user-visible (e.g.,1.1.0). - You can script version from Git tags or CI using Gradle tasks.
- Use BOMs (bill of materials) when available to keep library versions aligned.
APK vs AAB
| Format | Use |
|---|---|
| APK | Install directly on devices; great for testing and sharing internal builds. |
| AAB | Upload to Play Console; Google generates optimized per-device APKs. |
Common Errors & Fixes
- “Could not find …” → Add/verify
google()andmavenCentral()repositories. - Dependency version conflict → Run
./gradlew :app:dependenciesand align versions/BOM. - Dex/Method count → Enable MultiDex for old minSdk (
multiDexEnabled true, add dependency). - Build slow → Enable configuration cache, parallel builds, increase JVM heap; avoid huge monolithic modules.
- Release crash only → Check R8 rules; keep classes used via reflection.