FSA全栈行动 FSA全栈行动
首页
  • 移动端文章

    • Android
    • iOS
    • Flutter
  • 学习笔记

    • 《Kotlin快速入门进阶》笔记
    • 《Flutter从入门到实战》笔记
    • 《Flutter复习》笔记
  • 内功心法

    • 《深入浅出设计模式Java版》笔记
前端
后端
  • 产品
  • 代理
  • 提效
  • 逆向
  • 分类
  • 标签
  • 归档
  • LinXunFeng
  • GitLqr

公众号:FSA全栈行动

记录学习过程中的知识
首页
  • 移动端文章

    • Android
    • iOS
    • Flutter
  • 学习笔记

    • 《Kotlin快速入门进阶》笔记
    • 《Flutter从入门到实战》笔记
    • 《Flutter复习》笔记
  • 内功心法

    • 《深入浅出设计模式Java版》笔记
前端
后端
  • 产品
  • 代理
  • 提效
  • 逆向
  • 分类
  • 标签
  • 归档
  • LinXunFeng
  • GitLqr
  • AndroidUI

  • Android第三方SDK

  • Android混淆

  • Android仓库

  • Android新闻

  • Android系统开发

  • Android源码

  • Android注解AOP

  • Android脚本

  • AndroidTv开发

  • AndroidNDK

  • Android音视频

  • Android热修复

  • Android性能优化

  • Android云游戏

  • Android插件化

  • iOSUI

  • iOS工具

  • iOS底层原理与应用

  • iOS组件化

  • iOS音视频

  • iOS疑难杂症

  • iOS之Swift

  • iOS之RxSwift

  • iOS开源项目

  • iOS逆向

  • Flutter开发

    • Dart - 抽象类的实例化
    • Flutter - 打印好用的Debug日志
    • Flutter - 混合开发
    • Flutter - 解决混合开发iOS脚本打包遇到的问题
    • Flutter - 低版本在iOS14上遇到的问题与解决方案
    • Flutter - 解决原生弹窗的触摸事件被Flutter响应的问题
    • Flutter - 实现列表上下拉切换header
    • Flutter - 获取ListView当前正在显示的Widget信息
    • Flutter - 列表滚动定位超强辅助库,墙裂推荐!🔥
    • Flutter - 快速实现聊天会话列表的效果,完美💯
    • Flutter - 聊天输入框更新文本时的必备优化点🔖
    • Flutter - 我给官方提PR,解决run命令卡住问题 😃
    • Flutter - 探索run命令到底做了什么 🤔
    • Flutter - 引擎调试(iOS篇)🛠
    • Flutter - 引擎调试bug到提交PR实战 🐞
    • Flutter - 船新升级😱支持观察第三方构建的滚动视图💪
    • Flutter - 瀑布流交替播放视频 🎞
    • Flutter - IM保持消息位置大升级(支持ChatGPT生成式消息) 🤖
    • Flutter - 滚动视图中的表单防遮挡 🗒
    • Flutter - 秒杀1/2曝光统计 📊
    • 一天内加入 Flutter 和 FlutterCandies 两大组织是什么体验 🧐
    • Flutter - 如何快速搓一个微信通讯录列表(azlist) 📓
    • Flutter - 混编项目集成Shorebird热更新🐦(安卓篇)
    • Flutter - 混编项目集成Shorebird热更新🐦(iOS篇)
    • Flutter - 解决返回原生页面时dispose方法未被触发的问题 🐞
    • Flutter - 升级3.19之后页面多次rebuild?🤨
    • Flutter - 热更新 Shorebird 1.0 正式版来了 🐦
    • Flutter - 使用Pigeon实现视频缓存插件 🐌
    • Flutter - 轻松搞定屏幕旋转功能 😎
    • Flutter - 解决Connection closed before full header was received
    • Flutter - 实现聊天键盘与功能面板的丝滑切换 🍻
    • Flutter - 支持观察NestedScrollView,兼容性更强 😈
    • Flutter - 聊天键盘与面板丝滑切换的强势升级 🍻
    • Flutter - 升级到3.24后页面还会多次rebuild吗?🧐
    • Flutter - 轻松实现PageView卡片偏移效果
    • Flutter - 轻松搞定炫酷视差(Parallax)效果
    • Flutter - 危!3.24版本苹果审核被拒!
    • Flutter - 子部件任意位置观察滚动数据
    • Flutter - iOS编译加速
    • Flutter - Xcode16 还原编译速度
    • Flutter - GetX Helper 助你规范应用 tag
    • Flutter - GetX Helper 如何应用于旧页面
    • Flutter - 聊天面板库动画生硬?这次让你丝滑个够
    • Flutter - 使用本地 DevTools 验证 SVG 加载优化
    • Flutter - 详情页 TabBar 与模块联动?秒了!
    • Flutter - 详情页初始锚点与优化
    • Flutter - Melos Pub workspaces 实践
    • Flutter webview 崩溃率上升怎么办?我的分析与解决方案
    • Flutter 多仓库本地 Monorepo 方案与体验优化
    • Flutter 拖拉对比组件,换装图片前后对比必备
    • Flutter 3.44 插件内置 Kotlin (KGP) 双向兼容适配指南
      • 一、简述
      • 二、新旧版本对比
      • 三、动态兼容方案
        • 1、动态应用 kotlin-android 插件
        • 2、动态配置 JVM 目标版本 (jvmTarget)
      • 四、最后
  • 移动端
  • Flutter开发
GitLqr
2026-07-05
目录

Flutter 3.44 插件内置 Kotlin (KGP) 双向兼容适配指南

欢迎关注微信公众号:[FSA全栈行动 👋]

# 一、简述

最近升级到 Flutter 3.44.x 及以上版本的朋友,想必在编译项目时都被控制台这行显眼的警告刷过屏:

WARNING: Your app uses the following plugins that apply Kotlin Gradle Plugin (KGP)...
Future versions of Flutter will fail to build if your app uses plugins that apply KGP.

万恶的 KGP(Kotlin Gradle Plugin)要被“抛弃”了!

原来,从 Android Gradle Plugin (AGP) 9.0 开始,对 Kotlin 的支持被彻底收归“内置”(Built-in Kotlin)。任何在插件中单方面显式声明的 apply plugin: 'kotlin-android',在未来的 Flutter 编译环境中都会直接导致构建崩溃。

官方指引(Built-in Kotlin migration for plugin authors (opens new window))中给的路线非常直接:只要把插件的最低 Flutter 版本限制一刀切升到 3.44,然后删掉 apply plugin: 'kotlin-android',收工!

但是,在实际开源组件的维护中,如果我们作为维护者强行把最低版本拔高到 Flutter 3.44,这就相当于与那些还在坚守 Flutter 3.x 早期版本(甚至 Flutter 3.0)的用户们“割袍断义”了!所以,本篇指南就带各位朋友搞一套新旧 Flutter 双向兼容的适配秘籍。

# 二、新旧版本对比

在开整之前,我们先用一张表直观对比一下新旧两种编译环境下的机制差异。知己知彼,才好“对症下药”:

维度 旧版 Flutter 构建体系 (< 3.44) 新版 Flutter 构建体系 (>= 3.44 / AGP 9+)
Kotlin 加载机制 依赖插件通过 kotlin-android 显式激活 由 AGP 9.0+ 内置处理,插件手动 apply 会与内置逻辑产生冲突
Kotlin 插件配置 必须在 buildscript.dependencies 中引入 KGP 依赖 移交至主 App 项目或由 Flutter 构建链管理,子插件中无需重复声明
JVM Target 设置 必须在 android 内部通过 kotlinOptions {} 指定 引入了外层的 kotlin { compilerOptions {} } 新型 DSL

# 三、动态兼容方案

这里以我们维护的 chat_bottom_container (opens new window) 插件为例,为了让插件在旧版 Flutter (AGP < 9.0) 环境下能正常编译,而在新版 Built-in Kotlin (AGP >= 9.0) 下又不会因 KGP 冲突报错,我们需要在 chat_bottom_container/android/build.gradle (opens new window) 中采取“动态嗅探”策略。

# 1、动态应用 kotlin-android 插件

我们通过解析 AGP 实际的版本号以及检查宿主工程是否开启了内置 Kotlin,来决定是否手动 apply 插件:

// 1. 获取当前编译环境中 Android Gradle 插件的主版本号
def agpMajor = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize(".")[0] as int

// 2. 判断当前内置 Kotlin 是否生效(要求 AGP 版本 >= 9 且未被显式禁用)
def builtInKotlinActive = agpMajor >= 9 &&
    (!project.hasProperty("android.builtInKotlin") ||
        Boolean.parseBoolean(project.property("android.builtInKotlin").toString()))

// 3. 仅在内置 Kotlin 不生效的旧版构建环境下,才手动应用旧版 kotlin-android 插件
if (!builtInKotlinActive) {
    apply plugin: "kotlin-" + "android"
}
  1. 在 Gradle 配置阶段,从 com.android.Version 中获取当前的 AGP 主版本号(例如:8 或 9)。
  2. 结合 agpMajor 和 android.builtInKotlin 属性,计算出 builtInKotlinActive 布尔值,用于判定当前内置 Kotlin 是否处于活动状态。
  3. 如果宿主工程依旧没有启用 Built-in Kotlin,我们就打上“补丁”,通过动态拼接字符串的方式手动执行 apply plugin,在保持向后兼容的同时避免被 Flutter 误判。

Q:为什么不直接用 apply plugin: "kotlin-android"?

A:这是为了避免由于 Flutter CLI 静态正则扫描机制的局限性导致的误报。

在构建应用时,Flutter 构建工具(flutter_tools)并不会去真正解析并执行 Groovy 的 if-else 条件分支,它只是简单粗暴地使用静态正则表达式(RegExp)扫描依赖插件的 build.gradle 文本。只要文件里出现了 apply plugin: "kotlin-android" 或 id "org.jetbrains.kotlin.android" 的字面量,不管这段代码处于什么禁用分支内,都会被判定为“手动应用了 KGP”,从而抛出警告。

# 2、动态配置 JVM 目标版本 (jvmTarget)

由于 Kotlin 插件版本的不同,设置 JVM 目标的 DSL 语法也有两套。如果直接写新语法,老项目在老版本 KGP 下编译会报错(找不到属性);写旧语法,在新环境编译时又会抛出过时或不支持的错误。

因此,我们需要采用如下动态属性嗅探法:

// 1. 获取 project 中的 kotlin 扩展配置对象
def kotlinExt = project.extensions.findByName("kotlin")

// 2. 判断该扩展对象中是否支持 compilerOptions 属性
if (kotlinExt?.hasProperty("compilerOptions")) {
    kotlin {
        compilerOptions {
            jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
        }
    }
} else {
    // 3. 降级使用传统的 kotlinOptions 配置方式,防止老版 Kotlin Gradle 插件报错
    android.kotlinOptions {
        jvmTarget = JavaVersion.VERSION_1_8.toString()
    }
}
  1. 通过 extensions.findByName("kotlin") 安全获取 Kotlin 扩展对象,防止因项目未引入 Kotlin 导致直接报空指针异常。
  2. 如果该扩展包含了新的 compilerOptions,说明当前处于新版 KGP (1.9+) 或内置 Kotlin 环境,此时直接使用新语法 compilerOptions 配置 JVM 目标。
  3. 若为老版本,则降级使用传统的 android.kotlinOptions { jvmTarget = '1.8' } 语法,以保障老项目顺利编译通过。

# 四、最后

通过以上这两处 Gradle 动态判定以及巧妙的字面量拼接,插件就可以在不做任何 Breaking Change 的前提下,平滑兼容新旧版本的 Flutter 和 Kotlin 编译环境。

对于使用者来说,直接引入修改后的插件即可,无需在主项目的 gradle.properties 中强行添加 android.builtInKotlin=false 这类治标不治本的规避配置。

希望本篇秘籍能帮各位朋友少踩几个编译坑,下期再会!

#Dart#Flutter
上次更新: 2026/07/05, 10:57:44
Flutter 拖拉对比组件,换装图片前后对比必备

← Flutter 拖拉对比组件,换装图片前后对比必备

最近更新
01
Obsidian - 使用 Share Note 分享笔记并自部署
06-21
02
AI - Antigravity 不认全局 skills 怎么办?
03-02
03
AI - 通过 Docker 来安装与访问 OpenClaw
02-02
更多文章>
Theme by Vdoing | Copyright © 2020-2026 FSA全栈行动
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×