On this page
You press Run and see: "Android Gradle plugin requires Java 17 to run", or "compileSdk 34 is lower than the version required by dependency X". To fix errors like these with confidence, you need a clear mental model of the build tools.
This article explains the Android SDK, the JDK, Gradle and the Android Gradle Plugin (AGP), plus the three SDK version settings in every Android project, using a real build file as the reference.
The one-line definitions
| Tool | What it is | Analogy |
|---|---|---|
| JDK | Java Development Kit: the Java runtime and compiler tools that Gradle and the Kotlin compiler run on | The engine the workshop machines run on |
| Gradle | A general-purpose build automation tool: runs tasks, resolves dependencies, caches results | The workshop manager scheduling jobs |
| AGP | Android Gradle Plugin: teaches Gradle how to build Android apps (resources, DEX, signing, APK/AAB) | The Android-specific machinery |
| Android SDK | Android platform APIs (android.jar per API level), build tools, platform-tools (adb), emulator | The parts catalogue and test bench |
The JDK: what Gradle runs on
Android apps don't run on a desktop JVM, but the build does. Gradle, the Kotlin compiler and AGP are JVM programs, so they need a JDK. Recent AGP versions require a minimum JDK version to run. Android Studio bundles a suitable JDK (the JetBrains Runtime) and uses it by default.
Two different "Java versions" appear in a project, and mixing them up causes most confusion:
- The Gradle JDK, which runs the build. It's set in Android Studio under Settings โ Build Tools โ Gradle โ Gradle JDK, or with a toolchain.
- The Java/Kotlin target (
jvmTarget,sourceCompatibility), which is the bytecode level your code is compiled to. Android's toolchain supports it through desugaring.
Gradle and the wrapper
Each project pins its Gradle version in gradle/wrapper/gradle-wrapper.properties. The Gradle wrapper (gradlew) downloads exactly that version, so every developer and CI machine builds with the same Gradle.
distributionUrl=https\://services.gradle.org/distributions/gradle-<version>-bin.zip./gradlew assembleDebug # build a debug APK
./gradlew testDebugUnitTest # run local unit tests
./gradlew --version # shows Gradle, Kotlin and JVM versions in useThe Android Gradle Plugin (AGP)
AGP adds the android { } block and Android-specific tasks. AGP versions are tied to minimum Gradle versions, minimum JDK versions and supported Android Studio versions. Google publishes a compatibility table in the AGP release notes. Use the AGP Upgrade Assistant in Android Studio to move between versions safely.
compileSdk, minSdk and targetSdk
android {
namespace = "com.example.notes"
compileSdk = 36 // APIs you can CALL in code (compile against this android.jar)
defaultConfig {
applicationId = "com.example.notes"
minSdk = 24 // oldest Android version that can INSTALL the app
targetSdk = 36 // Android version whose BEHAVIOUR changes you've tested
versionCode = 1
versionName = "1.0"
}
}| Setting | Controls | Practical rule |
|---|---|---|
compileSdk | Which APIs exist at compile time | Use the latest stable SDK. Newer libraries often require it. |
minSdk | Who can install the app | A product decision: balance reach against development cost. Guard newer APIs with version checks. |
targetSdk | Which behaviour changes apply to your app | Keep it recent. Google Play requires new apps and updates to target a recent API level. |
The values above are examples. Check the current Google Play target API requirement before each release.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// POST_NOTIFICATIONS runtime permission exists only on Android 13 (API 33)+
permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
}Version catalogs: one place for dependency versions
[versions]
agp = "<agp-version>"
kotlin = "<kotlin-version>"
composeBom = "<bom-version>"
[libraries]
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }dependencies {
implementation(platform(libs.androidx.compose.bom)) // BOM aligns all Compose library versions
implementation(libs.androidx.material3)
}Reading and fixing common build errors
| Error message (paraphrased) | Which layer | Fix |
|---|---|---|
| "Android Gradle plugin requires Java N to run" | JDK โ AGP | Set Gradle JDK to the bundled JDK or JDK N+ |
| "Minimum supported Gradle version is X" | Gradle โ AGP | Update distributionUrl, or use the Upgrade Assistant |
| "Dependency requires compileSdk X or later" | Library โ SDK | Raise compileSdk and install that SDK platform |
| "Failed to find target with hash string 'android-X'" | SDK | Install the platform in the SDK Manager |
| "Inconsistent JVM-target compatibility" | Kotlin โ Java target | Align jvmTarget and compileOptions, or use a toolchain |
| "Unresolved reference" after adding a library | Dependencies | Sync Gradle; check the artifact name, version and repository |
Real situations
Cloning an old GitHub project
It pins an old AGP that doesn't support your JDK. Either use a matching older JDK for that project, or upgrade AGP and Gradle with the Upgrade Assistant and fix deprecations.
CI build fails, local build works
CI uses a different JDK. Pin the JDK in the CI workflow (for example the setup-java action) and rely on the Gradle wrapper.
Play Console rejects an update
The target API is too old for current Play requirements. Raise targetSdk and test the behaviour changes for that Android version.
Frequently asked questions
Is the Android SDK the same as the JDK?
No. The JDK provides Java tooling that runs the build. The Android SDK provides the Android APIs, build tools and device tools. You need both.
Should compileSdk and targetSdk always match?
Often they do, but they mean different things. You can compile against a newer SDK before you've finished testing its behaviour changes, then raise targetSdk.
Do I need to install Gradle globally?
No. Use the project's Gradle wrapper (./gradlew), which downloads the correct version automatically.
What's the difference between Groovy and Kotlin DSL build files?
Both configure the same build. Kotlin DSL (.kts) is the default for new projects and offers better IDE completion and type safety.
Conclusion
The JDK runs Gradle, Gradle runs AGP, and AGP uses the Android SDK to compile, dex, package and sign your app. Each has its own version, and most build errors are a mismatch between two of them. Read the error, identify the layer, and fix the version at that boundary.
Next step: open your project's libs.versions.toml and gradle-wrapper.properties and identify each version. Then learn what happens after the build in How an Android App Works Internally.
Official references
๐ฑ Apps built by Yunok Tech
Real Android apps on Google Play, free to download.
Walzi4K wallpapers for lock and home screenGet it โธ
NotiVaultNotification history: recover dismissed notificationsGet it โธ
Ready to build real Android applications?
Reading a roadmap is the easy part. The real progress happens when you build a foundation step by step, with someone reviewing your code and answering the questions that come up along the way.
Move beyond theory and strengthen your Android development skills with Yunoktech's Android course. Learn core concepts, practical implementation, modern Android development techniques, and the reasoning behind building maintainable applications.
Explore the Android course and take your next step as an Android developer.