build(android): move to Flutter 3.47 template toolchain (Gradle 9.3.1 / AGP 9.1.0 / Kotlin 2.4.0)

The project pinned Gradle 8.12 / AGP 8.9.1 / Kotlin 2.1.0, all three below the
hard error floors that Flutter 3.47.1 enforces in DependencyVersionChecker.kt
(8.14.0 / 8.11.1 / 2.2.20). Nothing here had rotted; the SDK moved.

Targets Flutter's own template defaults rather than the lowest combo that
clears the floors, because Flutter promotes its warn floor to the error floor
in the very next release -- clearing only the hard floor buys one release of
runway. `flutter-android-preflight` on the host re-derives all of this from
the installed SDK.

Also:
- kotlinOptions{} -> kotlin{compilerOptions{}}: the old DSL is a script
  COMPILATION error under Kotlin >= 2.3, not a warning.
- Java/jvmTarget 11 -> 17, matching what the AndroidX artifacts now require.
- Drop android.enableJetifier (obsolete, removed outright in AGP 9); the
  Flutter migrator adds builtInKotlin/newDsl=false in its place. Keep them:
  builtInKotlin=true makes AGP 9.1.0 supply Kotlin 2.2.10, which is BELOW
  Flutter's own 2.2.20 floor, so Flutter rejects its own recommendation.
- Force plugin subprojects to compileSdk 36 / minSdk 24. bg_launcher 0.1.0 is
  abandoned at compileSdk 31 and the AndroidX artifacts it resolves to refuse
  it. The override must be registered before evaluationDependsOn(":app"),
  which evaluates subprojects eagerly. Dropping bg_launcher is the real fix.

Verified: flutter build apk --debug and --release, as both mikkeli and hermes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dKAqFo9Uj3mPZWvDzj3G8
This commit is contained in:
2026-08-23 11:56:20 +09:00
parent a9844e9665
commit 7a58483ba2
7 changed files with 67 additions and 24 deletions
+7
View File
@@ -3,3 +3,10 @@ include: package:flutter_lints/flutter.yaml
analyzer:
exclude:
- backup_v1.1/**
- build/**
- android/**
- ios/**
- web/**
- windows/**
- macos/**
- linux/**
+10 -6
View File
@@ -1,3 +1,5 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
id("com.android.application")
id("kotlin-android")
@@ -11,12 +13,8 @@ android {
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
defaultConfig {
@@ -39,6 +37,12 @@ android {
}
}
kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_17)
}
}
flutter {
source = "../.."
}
+29
View File
@@ -15,6 +15,35 @@ subprojects {
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
project.layout.buildDirectory.value(newSubprojectBuildDir)
}
// Force plugin subprojects onto a modern compileSdk/minSdk.
// Several pinned pub plugins are stuck on ancient values -- bg_launcher 0.1.0 is
// compileSdk 31 / minSdk 16, flutter_overlay_window 0.5.0 is compileSdk 34 -- and the
// AndroidX artifacts they now resolve to refuse to be consumed by them.
// The fix belongs HERE, not in ~/.pub-cache: that cache is shared between users,
// unversioned, and invisible to git, so an edit there silently poisons every build on
// the machine and is wiped by the next `pub get`.
// Reflection is used because AGP's types are not on the root build script classpath.
// NOTE: must be registered BEFORE evaluationDependsOn(":app") below, which evaluates
// subprojects eagerly -- after it, afterEvaluate throws.
subprojects {
afterEvaluate {
val androidExt = extensions.findByName("android") ?: return@afterEvaluate
runCatching {
androidExt.javaClass
.getMethod("setCompileSdkVersion", Int::class.javaPrimitiveType)
.invoke(androidExt, 36)
}
runCatching {
val defaultConfig = androidExt.javaClass
.getMethod("getDefaultConfig")
.invoke(androidExt)
defaultConfig.javaClass
.getMethod("setMinSdkVersion", Int::class.javaPrimitiveType)
.invoke(defaultConfig, 24)
}
}
}
subprojects {
project.evaluationDependsOn(":app")
}
+4 -1
View File
@@ -1,3 +1,6 @@
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
android.enableJetifier=true
# This builtInKotlin flag was added automatically by Flutter migrator
android.builtInKotlin=false
# This newDsl flag was added automatically by Flutter migrator
android.newDsl=false
+1 -1
View File
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-all.zip
+2 -2
View File
@@ -19,8 +19,8 @@ pluginManagement {
plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.9.1" apply false
id("org.jetbrains.kotlin.android") version "2.1.0" apply false
id("com.android.application") version "9.1.0" apply false
id("org.jetbrains.kotlin.android") version "2.4.0" apply false
}
include(":app")
+13 -13
View File
@@ -45,10 +45,10 @@ packages:
dependency: transitive
description:
name: characters
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
url: "https://pub.dev"
source: hosted
version: "1.4.0"
version: "1.4.1"
checked_yaml:
dependency: transitive
description:
@@ -308,26 +308,26 @@ packages:
dependency: transitive
description:
name: matcher
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd"
url: "https://pub.dev"
source: hosted
version: "0.12.17"
version: "0.12.20"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
url: "https://pub.dev"
source: hosted
version: "0.11.1"
version: "0.13.0"
meta:
dependency: transitive
description:
name: meta
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
sha256: "307249ce4ff29d58a18e97f6345f539382eb9c9c29ecda628900f31de0443dd9"
url: "https://pub.dev"
source: hosted
version: "1.16.0"
version: "1.19.0"
nested:
dependency: transitive
description:
@@ -593,10 +593,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11"
url: "https://pub.dev"
source: hosted
version: "0.7.6"
version: "0.7.12"
typed_data:
dependency: transitive
description:
@@ -617,10 +617,10 @@ packages:
dependency: transitive
description:
name: vector_math
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
sha256: f36f9f3be64c6198714492bb455c11056e33e2f85d9a0b676a48301e44fdcf47
url: "https://pub.dev"
source: hosted
version: "2.2.0"
version: "2.4.2"
vm_service:
dependency: transitive
description:
@@ -686,5 +686,5 @@ packages:
source: hosted
version: "3.1.3"
sdks:
dart: ">=3.9.0 <4.0.0"
dart: ">=3.11.0-0 <4.0.0"
flutter: ">=3.35.0"