In this article

Before enabling Android Gradle Plugin 9’s built-in Kotlin in a Flutter project, check the app and every native plugin that applies the Kotlin Gradle Plugin. Readiness is a dependency-level question; changing the app’s properties alone cannot establish it.

Flutter’s built-in Kotlin migration note distinguishes temporary legacy support added in 3.44 from built-in Kotlin support added in 3.47 once the app and plugins have migrated. It also discusses the new AGP DSL and explicitly warns that breaking-change instructions are release-scoped. Do not apply this migration to a project that does not use KGP.

Identify which migration you are doing#

Moving old imperative Gradle plugin application to plugins {} syntax is a different task from moving away from KGP for AGP 9. A project can have modern plugin-application syntax and still have native plugins that are not ready for built-in Kotlin.

Write the intended change in one sentence: “Move this app and its required native plugins to the supported built-in Kotlin path for our recorded Flutter/AGP versions.” That keeps a syntax cleanup from being mistaken for the complete transition.

Record the toolchain and plugin graph#

Capture the Flutter version, AGP version, Gradle wrapper and JDK used by the actual CI job. Then identify every Android plugin involved in the build and the version resolved for it.

For each native plugin, record whether it applies KGP, its documented migration support and any AGP DSL compatibility issue. Include local plugins and add-to-app host configuration; they can be missed by checking only public package names.

Keep a short readiness ledger with owner, supported version, required change and verification step. “Latest” is not a usable version record.

Resolve unsupported dependencies first#

Prefer a compatible released plugin version or a scoped maintained fix. If a dependency blocks migration, document the blocker and the supported temporary configuration for your exact toolchain.

Do not blindly toggle compatibility properties copied from an issue comment. A workaround can be valid for one Flutter release and inappropriate for another. Re-open the official migration note and linked app/plugin guides when you perform the change.

Where you own a local plugin, migrate it as an independently reviewable change. Avoid patching generated dependency directories and treating those edits as reproducible source configuration.

Change one compatibility boundary at a time#

Start from a known working release build. Keep unrelated SDK, billing and flavor changes outside the transition unless they are prerequisites. After the documented changes, inspect the build output for legacy compatibility warnings rather than equating a successful compile with future readiness.

A hypothetical app could pass its basic build while a less frequently used plugin variant fails. Test the required variants and native feature paths, not only the default debug task.

Define the finish line#

The migration is ready when the intended clean CI build succeeds, required configurations are checked, native features still behave correctly and the recorded plugin graph matches the migrated source.

Keep the previous working configuration in version control while investigating failures. Record remaining temporary compatibility settings and a review trigger; do not let them become unexplained permanent defaults.

This article supplies a readiness process, not a tested configuration for every plugin combination. Our AI-generated code review guide is useful when an assistant proposes Gradle edits: inspect the complete diff and verify the required behavior independently.