On this page · 12 sections
- What AGP 9.0 actually changed
- What breaks in a Flutter project specifically
- The configuration changes, exactly
- Testing AGP 10.0 behaviour before AGP 10.0 ships
- What AGP 10.0 removes, and why it decides your sequencing
- The two dates that disagree
- The upgrade decision
- India-specific considerations
- A migration checklist that survives contact with a real codebase
- FAQ
- How eCorpIT can help
- References
Summary. Android Gradle plugin 9.0, released as 9.0.1 in January 2026, removed support for applying the Kotlin Gradle Plugin, and that single change is what breaks Flutter Android builds. AGP 9.0 now carries a runtime dependency on KGP 2.2.10, requires Gradle 9.1.0 and JDK 17, and tops out at API level 36.1. Flutter 3.44, the current stable line at 3.44.7, handles this by writing two opt-out flags into your project — android.builtInKotlin=false and android.newDsl=false — so your build keeps working while the ecosystem catches up. The catch that most upgrade posts miss: Flutter's own documentation, updated 5 August 2026, says enabling built-in Kotlin requires Flutter 3.47 or later. On today's stable channel you cannot turn it on at all. Meanwhile Google's two published timelines disagree on when the escape hatch closes: the AGP 9.0 release notes say the opt-out disappears in AGP 10.0 "(mid-2026)", while the AGP roadmap page, last updated 22 July 2026, headlines the same release as "AGP 10.0 (late 2026)". For a team running CI on GitHub-hosted Linux 2-core runners at $0.006 per minute, the cost of this migration is not compute — it is the plugin dependency audit nobody has budgeted for.
This guide covers what actually fails, the exact configuration changes, how to test AGP 10.0 behaviour early, and the timing call for teams shipping production Flutter apps.
What AGP 9.0 actually changed
Two changes in AGP 9.0 matter to Flutter teams, and they are separate.
The first is built-in Kotlin. Before AGP 9.0, an Android module that contained Kotlin source had to apply the Kotlin Android plugin, org.jetbrains.kotlin.android (also written as kotlin-android). AGP 9.0 compiles Kotlin itself and enables that behaviour by default. As the Android build documentation puts it, "Starting with Android Gradle plugin (AGP) 9.0, support for applying the Kotlin Gradle Plugin (KGP) has been removed." Applying it now is not redundant — it is an error.
The second is the DSL. AGP versions 7.x and 8.x still exposed the old DSL types such as BaseExtension, which also implemented the newer public interfaces. AGP 9.0 uses the new interfaces exclusively, and the implementing classes are fully hidden. Access to the old variant API goes with them. If a third-party Gradle plugin in your build still reaches for the old types, you get a specific failure:
java.lang.ClassCastException: class com.android.build.gradle.internal.dsl.ApplicationExtensionImpl$AgpDecorated_Decorated
cannot be cast to class com.android.build.gradle.BaseExtension
Both changes have an opt-out flag, and Flutter sets both for you.
Compatibility floors you cannot negotiate
AGP 9.0's compatibility table is short and strict:
| Component | Minimum version | Default version | Practical consequence for Flutter teams |
|---|---|---|---|
| Gradle | 9.1.0 | 9.1.0 | A Gradle wrapper upgrade lands before anything else works |
| SDK Build Tools | 36.0.0 | 36.0.0 | CI images pinned to older build-tools need rebuilding |
| NDK | Not applicable | 28.2.13676358 | Native plugins with pinned NDK versions need a look |
| JDK | 17 | 17 | Build agents still on JDK 11 or 17-only images must move to 17 |
| Max compile SDK | — | API level 36.1 | AGP 9.0 will not compile against a higher API level |
AGP 9.0 also pulls KGP 2.2.10 as a runtime dependency. You no longer declare a KGP version, and if your build declares one below 2.2.10, Gradle upgrades it automatically. KSP moves to 2.2.10-2.0.2 to match. You can only downgrade KGP if you have opted out of built-in Kotlin, and the floor for a downgrade is KGP 2.0.0.
What breaks in a Flutter project specifically
Flutter's Android tooling sits between your app and AGP, so the failure modes are not identical to a native Android project.
The app's own `build.gradle` breaks first. A Flutter app created before 2026 almost certainly applies kotlin-android in android/app/build.gradle or build.gradle.kts, and sets jvmTarget inside a kotlinOptions block. Under built-in Kotlin, both have to go, replaced by a kotlin { compilerOptions { … } } block.
Plugins break second, and they break harder. A Flutter app pulls in Android build logic from every plugin in its dependency tree. Flutter tracks this in issue #181383, "Flutter plugins should support AGP 9.0.0". Community plugins hit the same wall — wakelock_plus filed issue #117, titled "AGP 9 incompatibility — kotlin-android plugin must be removed". You do not control this code, and a single unmigrated transitive plugin is enough to block the whole build once built-in Kotlin is on.
Add-to-app projects break silently. Flutter's migrator tool writes the two opt-out flags into gradle.properties when you run flutter run or flutter build apk. It cannot do that for an add-to-app Android host, because the host is a pure native Android project and the Flutter tool never runs during its build. Those teams have to add the flags by hand.
KMP modules need a different plugin entirely. If any module applies org.jetbrains.kotlin.multiplatform alongside com.android.library or com.android.application, that combination is no longer compatible with the new DSL. AGP 9.0 introduces com.android.kotlin.multiplatform.library for multiplatform modules, and an app module that mixes KMP with the Android application plugin has to be split into a separate subproject.
The warning you are probably already seeing
Teams that upgraded to Flutter 3.44 report a build-time warning naming every plugin that still applies KGP, with the line that future Flutter versions will fail the build if the app uses such plugins. Treat that warning as your migration backlog. It is the only inventory of your problem that anyone is going to hand you.
The configuration changes, exactly
Flutter's stable default today is the opt-out. Both flags belong in <flutter-project>/android/gradle.properties:
android.newDsl=false
android.builtInKotlin=false
The Flutter migrator adds these automatically on the next flutter run or flutter build apk, and building through Android Studio tooling adds them too. The mechanism is tracked in Flutter issue #183910. Add-to-app hosts get them manually. If your app never applied kotlin-android at all, Flutter's documentation is explicit that you only need android.newDsl=false and no further migration steps.
When you are ready to move off the opt-out, the app-side change is small. Before, in android/app/build.gradle.kts:
plugins {
id("com.android.application")
id("kotlin-android")
// ...
}
android {
// ...
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
}
// ...
}
After, with the plugin and the kotlinOptions block removed and compiler options moved into the kotlin {} block:
plugins {
id("com.android.application")
// ...
}
android {
// ...
}
kotlin {
compilerOptions {
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}
}
The Groovy form is the same edit against apply plugin: 'kotlin-android'. An add-to-app host using version catalogs drops alias(libs.plugins.kotlin.android) from its plugins block and makes the same kotlin {} addition.
Then, and only after every plugin in the tree is migrated, flip the flag:
android.builtInKotlin=true
Flutter's version note on that step is the whole timing story: enabling built-in Kotlin requires Flutter 3.47 or later. Stable is 3.44.7 as of the documentation refreshed on 5 August 2026. Setting android.builtInKotlin=true on today's stable channel is not a migration you can complete — it is a migration you can only prepare for.
Testing AGP 10.0 behaviour before AGP 10.0 ships
The useful part of Google's roadmap is that you can enforce the future's strictness on a current AGP 9.x release. Set both flags to true in gradle.properties and your build validates against the API surface AGP 10.0 will require:
# Enforce modern DSL and Variant API interfaces exclusively
android.newDsl=true
# Enforce built-in Kotlin support without optional opt-out
android.builtInKotlin=true
For a large modular codebase, all-or-nothing is impractical, so AGP 9.4.0-alpha04 added per-subproject opt-out:
android.newDsl=true
android.newDsl.optOut=:lib
Google is clear that android.newDsl.optOut is a temporary aid for the 9.x line and disappears with android.newDsl in AGP 10.0. There is a matching module-level control for Kotlin — setting enableKotlin = false inside a module's android {} block removes the Kotlin compiler task for modules with no Kotlin code, which also trims build time and avoids a Kotlin standard library dependency.
For a Flutter app, run this experiment in a branch, not in your release pipeline. The point is to produce the list of plugins that fail, not to ship from it.
What AGP 10.0 removes, and why it decides your sequencing
AGP 10.0 completes a multi-year move to a fully lazy, configuration-cache-compatible build model. The legacy BaseVariant API was eager and task-centric; the androidComponents {} API is lazy and artifact-centric, and removes all references to Task and TaskProvider. The removals are what make this a hard deadline rather than a suggestion:
| Removed in AGP 10.0 | Replacement | Who this hits in a Flutter build |
|---|---|---|
applicationVariants, libraryVariants, testVariants, unitTestVariants |
androidComponents.onVariants() |
Custom flavour logic in android/app/build.gradle |
variantFilter block |
androidComponents.beforeVariants() with selectors |
Teams disabling debug or flavour combinations |
android.newDsl, android.builtInKotlin opt-out flags |
None — flags removed, modern DSL and built-in Kotlin enforced | Every Flutter app currently relying on the Flutter-written defaults |
| Transform API | Artifacts API plus AsmClassVisitorFactory |
Bytecode-rewriting plugins such as older analytics or obfuscation tooling |
registerJavaGeneratingTask(), registerResGeneratingTask() |
variant.sources.java.addGeneratedSourceDirectory(...) |
Codegen wired into the Android build |
sdkDirectory, ndkDirectory, bootClasspath, adbExecutable |
androidComponents.sdkComponents |
Custom CI tasks that shell out to adb |
buildConfigField(), resValue() eager mutation |
variant.buildConfigFields.put(...), variant.manifestPlaceholders.put(...) |
Build-time config injection, very common in Flutter apps with flavours |
That last row is the one that catches Flutter teams, because per-flavour buildConfigField entries are how most apps inject API base URLs and environment names into the Android side.
Google's recommended sequence is to fix AGP 9.x deprecation warnings first and reach a state where the build is warning-free without either opt-out flag, then move to 10.0. The AGP Upgrade Assistant in Android Studio (Tools > AGP Upgrade Assistant) automates part of it, and there are agent skills for the upgrade in the Android skills repository and a Kotlin Multiplatform equivalent from JetBrains. Google also runs a global tracking bug for Variant API migration blockers, worth checking before you file anything.
The two dates that disagree
Anyone planning a 2026 roadmap around this hits a documentation conflict, and it is worth naming because the two pages are both official and both current.
| Source | Page last updated | What it says about AGP 10.0 |
|---|---|---|
| AGP 9.0.1 release notes | Current release-notes page for the January 2026 release | "The ability to opt-out will be removed in AGP 10.0 (mid-2026)." |
| AGP DSL/API migration timeline | 22 July 2026 | Section headed "AGP 10.0 (late 2026)"; timeframes flagged as estimates |
| JetBrains Kotlin blog | 15 May 2026 update | Opt-out "will no longer work in AGP 10.0, which is expected sometime in 2026" |
The roadmap page carries the later revision date and explicitly labels its timeframes as estimates subject to change, so "late 2026" is the number to plan against. Mid-2026 has already passed without the release, which settles the question in practice. Plan for a release inside 2026 and a Flutter version that supports built-in Kotlin arriving before it.
The upgrade decision
Three positions are defensible right now, depending on what you ship.
Stay on the opt-out and prepare. This is correct for most production Flutter apps in August 2026. Flutter 3.44 already writes the flags, builds pass, and built-in Kotlin cannot be enabled until 3.47 anyway. Use the time to audit plugins and file migration issues upstream.
Test strict mode in a branch now. Correct for teams with heavy custom Gradle logic — flavour matrices, bytecode transforms, generated sources. Those are the AGP 10.0 removals with real engineering behind them, and finding out in a branch costs a week; finding out when the flags disappear costs a release.
Migrate the app-side configuration immediately. Correct for everyone. Removing kotlin-android from your own build.gradle and moving jvmTarget into kotlin { compilerOptions { … } } is a contained edit that is compatible with the opt-out still being in place. There is no reason to carry it.
What is not defensible is doing nothing until Flutter forces the issue. Flutter's own wording is that KGP support was added temporarily "while apps and plugins migrate", and will be removed in a future version. The migration you control is small. The one you do not control — third-party plugins — is the one with the long tail, and it starts with filing issues, which is why Flutter ships a copy-paste issue template for exactly that.
Márton Braun, Kotlin Developer Advocate at JetBrains, put the timing plainly in the Kotlin team's migration post: "We recommend making these configuration changes in your existing projects as soon as possible to ensure smooth upgrades to the latest versions of AGP in the future."
What this costs in CI
The compute cost of the migration is small and worth stating, because it usually gets overestimated. On GitHub-hosted runners, per-minute rates as of August 2026 are $0.006 for Linux 2-core, $0.022 for Linux 8-core, and $0.062 for a macOS 3-core or 4-core runner, with jobs rounded up to the nearest whole minute. Running a parallel strict-mode Android job alongside your existing pipeline roughly doubles the Android leg of the build, not the whole matrix — on a Linux 8-core runner, a 12-minute Android build adds about $0.26 per run. A team merging 20 pull requests a day adds roughly $5.28 a day. The real cost sits in engineering hours spent chasing plugin maintainers, not in runner minutes.
India-specific considerations
Indian product teams and offshore engineering groups carry two extra constraints here.
Build agents are frequently self-managed on cloud VMs rather than GitHub-hosted runners, which means the JDK 17 and Gradle 9.1.0 floors need an image rebuild rather than a config change. That is a platform-team ticket, and it should be raised before the app-side migration, not after.
The plugin tail is also longer for teams shipping India-market apps, because payments, KYC and messaging SDKs are often distributed as Android libraries wrapped in thin Flutter plugins by the vendor. Those wrappers update on the vendor's schedule, not the ecosystem's. If your app depends on a payment gateway plugin, ask the vendor for their AGP 9 built-in Kotlin timeline now, in writing, and put the answer in your release plan. Where those SDKs also handle personal data, the same upgrade window is a reasonable moment to re-check consent and data-handling behaviour against the Digital Personal Data Protection Act 2023, since you are already touching the Android build and its dependency set.
For teams still working through the wider 3.44 upgrade, the Flutter 3.44 production upgrade guide covers the release as a whole, and the related Impeller default rollout on Android and iOS and the CocoaPods sunset and Swift Package Manager migration are the other two forced migrations in the same window. On the platform side, Android 17 API 37 behaviour changes will land in the same planning cycle as AGP 10.0, and the Material UI and Cupertino UI package migration affects the same pubspec.yaml you are already auditing.
A migration checklist that survives contact with a real codebase
- Record your current state: Flutter version, AGP version, Gradle wrapper version, JDK on every build agent.
- Confirm
android.newDsl=falseandandroid.builtInKotlin=falseexist inandroid/gradle.properties; add them by hand for add-to-app hosts.
- Remove
kotlin-androidand thekotlinOptionsblock from your own module, addkotlin { compilerOptions { jvmTarget = … } }, and confirm the build is unchanged.
- Capture the KGP warning output and turn the named plugins into a tracked list.
- For each plugin, check its changelog for a built-in Kotlin release; where none exists, file an issue using Flutter's template.
- In a branch, set both flags to
trueand record every failure. Useandroid.newDsl.optOutfor modules you cannot fix yet.
- Audit custom Gradle logic against the AGP 10.0 removal table above, replacing
applicationVariantswithandroidComponents.onVariants()and eagerbuildConfigFieldcalls withvariant.buildConfigFields.put(...).
- Rebuild CI images for Gradle 9.1.0, SDK Build Tools 36.0.0 and JDK 17.
- Re-run the branch experiment monthly; the plugin ecosystem is the variable, not your code.
- When Flutter 3.47 or later reaches your channel and the plugin list is clear, flip
android.builtInKotlin=truein the main branch.
The real cost here is usually the plugin audit, not the code.
FAQ
How eCorpIT can help
eCorpIT runs Android and Flutter build migrations as a scoped piece of work: a dependency audit that produces the real list of plugins blocking built-in Kotlin, the app-side configuration changes, and a strict-mode CI branch that proves compatibility before the opt-out flags disappear. Our senior engineering teams work to CMMI Level 5 and ISO 27001:2022 practices, which matters when the migration touches payment or KYC SDKs. If your Flutter app is carrying a plugin tail you have not inventoried yet, talk to us about a build-modernisation assessment.
References
- Android Gradle plugin 9.0.1 (January 2026) release notes — Android Developers
- Android Gradle Plugin DSL/API migration timeline — Android Developers, updated 22 July 2026
- Built-in Kotlin migration for app developers — Flutter documentation, updated 5 August 2026
- Migrating Flutter Android projects to built-in Kotlin — Flutter documentation
- Built-in Kotlin migration for plugin authors — Flutter documentation
- Flutter breaking changes index — Flutter documentation
- Flutter 3.44.0 release notes — Flutter documentation
- Update your Kotlin projects for Android Gradle Plugin 9.0 — Márton Braun, JetBrains
- Migrate to built-in Kotlin — Android Developers
- Updating multiplatform projects with Android apps to use AGP 9 — Kotlin Multiplatform documentation
- Flutter issue #181383: Flutter plugins should support AGP 9.0.0 — flutter/flutter
- Flutter issue #183910: add disable built-in Kotlin and new DSL migrators — flutter/flutter
- wakelock_plus issue #117: AGP 9 incompatibility — fluttercommunity/wakelock_plus
- AGP 10.0 Variant API global tracking bug — Google issue tracker
- Actions runner pricing — GitHub Docs
- Android Gradle plugin 9.4 (preview) release notes — Android Developers
Last updated: 6 August 2026.