kotlin-tooling-agp9-migration
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseKMP AGP 9.0 Migration
KMP 迁移至AGP 9.0
Android Gradle Plugin 9.0 makes the Android application and library plugins incompatible
with the Kotlin Multiplatform plugin in the same module. This skill guides you through the
migration.
Android Gradle Plugin 9.0 使得Android应用和库插件无法与同一模块中的Kotlin Multiplatform插件兼容。本指南将引导你完成迁移流程。
Step 0: Analyze the Project
步骤0:分析项目
Before making any changes, understand the project structure:
- Read (or
settings.gradle.kts) to find all modules.gradle - For each module, read its to identify which plugins are applied
build.gradle.kts - Check if the project uses a Gradle version catalog (). If it exists, read it for current AGP/Gradle/Kotlin versions. If not, find versions directly in
gradle/libs.versions.tomlfiles (typically in the rootbuild.gradle.ktsorbuildscript {}block). Adapt all examples in this guide accordingly — version catalog examples useplugins {}while direct usage usesalias(libs.plugins.xxx)id("plugin.id") version "x.y.z" - Read for the Gradle version
gradle/wrapper/gradle-wrapper.properties - Check for any existing workarounds (
gradle.properties)android.enableLegacyVariantApi - Check for plugin usage — AGP 9.0 has built-in Kotlin and this plugin must be removed
org.jetbrains.kotlin.android - Check for plugin usage — incompatible with built-in Kotlin, must migrate to KSP or
org.jetbrains.kotlin.kaptcom.android.legacy-kapt - Check for third-party plugins that may be incompatible with AGP 9.0 (see "Plugin Compatibility" section below)
If Bash is available, run from this skill's directory to get a
structured summary.
scripts/analyze-project.sh在进行任何修改前,请先了解项目结构:
- 阅读(或
settings.gradle.kts)文件,找出所有模块.gradle - 针对每个模块,阅读其文件,识别已应用的插件
build.gradle.kts - 检查项目是否使用Gradle版本目录()。如果存在,查看其中当前的AGP/Gradle/Kotlin版本;如果不存在,直接在
gradle/libs.versions.toml文件中查找版本信息(通常在根目录的build.gradle.kts或buildscript {}块中)。请根据实际情况调整本指南中的所有示例——版本目录示例使用plugins {},而直接引用版本则使用alias(libs.plugins.xxx)id("plugin.id") version "x.y.z" - 阅读文件获取Gradle版本
gradle/wrapper/gradle-wrapper.properties - 检查文件中是否存在任何现有变通方案(如
gradle.properties)android.enableLegacyVariantApi - 检查是否使用插件——AGP 9.0已内置Kotlin支持,必须移除该插件
org.jetbrains.kotlin.android - 检查是否使用插件——与内置Kotlin不兼容,必须迁移至KSP或
org.jetbrains.kotlin.kaptcom.android.legacy-kapt - 检查可能与AGP 9.0不兼容的第三方插件(详见下方“插件兼容性”章节)
如果系统支持Bash,可运行本技能目录下的脚本,获取结构化的项目摘要。
scripts/analyze-project.shClassify Each Module
对每个模块进行分类
For each module, determine its type:
| Current plugins | Migration path |
|---|---|
| Path A — Library plugin swap |
| Path B — Mandatory Android split |
| Path C — Full restructure (recommended) |
| See "Pure Android Tips" below |
针对每个模块,确定其类型:
| 当前插件 | 迁移路径 |
|---|---|
| 路径A — 库插件替换 |
| 路径B — 强制拆分Android模块 |
| 路径C — 完全重构(推荐) |
| 详见下方“纯Android项目提示” |
Determine Scope
确定迁移范围
- Path B is mandatory for any module combining KMP + Android application plugin
- Path C is recommended when the project has a monolithic (or similar) module containing entry points for multiple platforms (Android, Desktop, Web). This aligns with the new JetBrains default project structure where each platform gets its own app module.
composeApp - Ask the user whether they want Path B only (minimum required) or Path C (recommended full restructure)
- 路径B为强制要求:任何同时使用KMP和Android应用插件的模块都需遵循此路径
- 路径C为推荐方案:当项目包含一个单体(或类似)模块,且该模块包含多平台(Android、桌面端、Web)入口点时适用。此方案符合JetBrains新的默认项目结构,即每个平台拥有独立的应用模块
composeApp - 询问用户需求:确认用户仅需执行路径B(最低要求)还是路径C(推荐的完全重构)
Path A: Library Module Migration
路径A:库模块迁移
Use this when a module applies + .
kotlin.multiplatformcom.android.librarySee references/MIGRATION-LIBRARY.md for full before/after code.
Summary:
- Replace plugin: →
com.android.librarycom.android.kotlin.multiplatform.library - Remove plugin if present (AGP 9.0 has built-in Kotlin support)
org.jetbrains.kotlin.android - Migrate DSL: Move config from top-level block into
android {}:kotlin { android {} }kotlinkotlin { android { namespace = "com.example.lib" compileSdk = 35 minSdk = 24 } } - Rename source directories (only if the module uses classic Android layout instead of KMP layout):
- →
src/mainsrc/androidMain - →
src/testsrc/androidHostTest - →
src/androidTestsrc/androidDeviceTest - If the module already uses , no directory renames are needed
src/androidMain/
- Move dependencies from top-level into
dependencies {}:sourceSetskotlinkotlin { sourceSets { androidMain.dependencies { implementation("androidx.appcompat:appcompat:1.7.0") } } } - Enable resources explicitly if the module uses Android resources:
kotlin
kotlin { android { androidResources { enable = true } } } - Enable Java compilation if module has source files:
.javakotlinkotlin { android { withJava() } } - Enable tests explicitly if the module has unit or instrumented tests:
kotlin
kotlin { android { withHostTest { isIncludeAndroidResources = true } withDeviceTest { instrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } } } - Update Compose tooling dependency:
kotlin
// Old: debugImplementation(libs.androidx.compose.ui.tooling) // New: dependencies { androidRuntimeClasspath(libs.androidx.compose.ui.tooling) } - Publish consumer ProGuard rules explicitly if applicable:
kotlin
kotlin { android { consumerProguardFiles.add(file("consumer-rules.pro")) } }
适用于已应用 + 的模块。
kotlin.multiplatformcom.android.library完整的前后代码对比请参考references/MIGRATION-LIBRARY.md。
摘要:
- 替换插件:→
com.android.librarycom.android.kotlin.multiplatform.library - 移除插件(如果存在)——AGP 9.0已内置Kotlin支持
org.jetbrains.kotlin.android - 迁移DSL:将顶级块中的配置移至
android {}内部:kotlin { android {} }kotlinkotlin { android { namespace = "com.example.lib" compileSdk = 35 minSdk = 24 } } - 重命名源码目录(仅当模块使用经典Android布局而非KMP布局时需要):
- →
src/mainsrc/androidMain - →
src/testsrc/androidHostTest - →
src/androidTestsrc/androidDeviceTest - 如果模块已使用,则无需重命名目录
src/androidMain/
- 移动依赖:将顶级中的依赖移至
dependencies {}:sourceSetskotlinkotlin { sourceSets { androidMain.dependencies { implementation("androidx.appcompat:appcompat:1.7.0") } } } - 显式启用资源(如果模块使用Android资源):
kotlin
kotlin { android { androidResources { enable = true } } } - 启用Java编译(如果模块包含源码文件):
.javakotlinkotlin { android { withJava() } } - 显式启用测试(如果模块包含单元测试或仪器化测试):
kotlin
kotlin { android { withHostTest { isIncludeAndroidResources = true } withDeviceTest { instrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } } } - 更新Compose工具依赖:
kotlin
// 旧写法: debugImplementation(libs.androidx.compose.ui.tooling) // 新写法: dependencies { androidRuntimeClasspath(libs.androidx.compose.ui.tooling) } - 显式发布消费者ProGuard规则(如适用):
kotlin
kotlin { android { consumerProguardFiles.add(file("consumer-rules.pro")) } }
Path B: Android App + Shared Module Split
路径B:拆分Android应用与共享模块
Use this when a module applies + .
This is mandatory for AGP 9.0 compatibility.
kotlin.multiplatformcom.android.applicationSee references/MIGRATION-APP-SPLIT.md for full guide.
Summary:
- Create module with its own
androidApp:build.gradle.ktskotlinplugins { alias(libs.plugins.androidApplication) // Do NOT apply kotlin-android — AGP 9.0 includes Kotlin support alias(libs.plugins.composeMultiplatform) // if using Compose alias(libs.plugins.composeCompiler) // if using Compose } android { namespace = "com.example.app" compileSdk = 35 defaultConfig { applicationId = "com.example.app" minSdk = 24 targetSdk = 35 versionCode = 1 versionName = "1.0" } buildFeatures { compose = true } } dependencies { implementation(projects.shared) // or whatever the shared module is named implementation(libs.androidx.activity.compose) } - Move Android entry point code from to
src/androidMain/:androidApp/src/main/- (and any other Activities/Fragments)
MainActivity.kt - (app-level manifest with
AndroidManifest.xmland launcher<application>) — verify<activity>onandroid:nameuses the fully qualified class name in its new location<activity> - Android Application class if present
- App-level resources (launcher icons, theme, etc.)
- Add to :
settings.gradle.ktsinclude(":androidApp") - Add to root : plugin declarations with
build.gradle.ktsapply false - Convert original module from application to library using Path A steps
- Ensure different namespaces: app module and library module must have distinct namespaces
- Remove from shared module: ,
applicationId,targetSdk,versionCodeversionName - Update IDE run configurations: change the module from the old module to
androidApp
适用于已应用 + 的模块。
此路径是AGP 9.0兼容性的强制要求。
kotlin.multiplatformcom.android.application完整指南请参考references/MIGRATION-APP-SPLIT.md。
摘要:
- 创建模块,并编写独立的
androidApp文件:build.gradle.ktskotlinplugins { alias(libs.plugins.androidApplication) // 请勿应用kotlin-android — AGP 9.0已包含Kotlin支持 alias(libs.plugins.composeMultiplatform) // 如果使用Compose alias(libs.plugins.composeCompiler) // 如果使用Compose } android { namespace = "com.example.app" compileSdk = 35 defaultConfig { applicationId = "com.example.app" minSdk = 24 targetSdk = 35 versionCode = 1 versionName = "1.0" } buildFeatures { compose = true } } dependencies { implementation(projects.shared) // 或共享模块的实际名称 implementation(libs.androidx.activity.compose) } - 将Android入口点代码从移至
src/androidMain/:androidApp/src/main/- (及其他Activities/Fragments)
MainActivity.kt - (包含
AndroidManifest.xml和启动器<application>的应用级清单)——验证<activity>的<activity>是否指向其新位置的全限定类名android:name - 若存在Android Application类,一并移动
- 应用级资源(启动器图标、主题等)
- 添加至:
settings.gradle.ktsinclude(":androidApp") - 添加至根目录:使用
build.gradle.kts声明插件apply false - 将原始模块从应用转换为库:遵循路径A的步骤
- 确保命名空间不同:应用模块和库模块必须使用不同的命名空间
- 从共享模块中移除:、
applicationId、targetSdk、versionCodeversionName - 更新IDE运行配置:将运行模块从旧模块更改为
androidApp
Path C: Full Restructure (Recommended)
路径C:完全重构(推荐)
Use this when the project has a monolithic module (typically ) containing entry
points for multiple platforms. This is optional but aligns with the new JetBrains default.
composeAppSee references/MIGRATION-FULL-RESTRUCTURE.md for full guide.
适用于项目包含单体模块(通常为)且该模块包含多平台入口点的场景。此方案为可选,但符合JetBrains的新默认结构。
composeApp完整指南请参考references/MIGRATION-FULL-RESTRUCTURE.md。
Target Structure
目标结构
project/
├── shared/ ← KMP library (was composeApp), pure shared code
├── androidApp/ ← Android entry point only
├── desktopApp/ ← Desktop entry point only (if desktop target exists)
├── webApp/ ← Wasm/JS entry point only (if web target exists)
├── iosApp/ ← iOS Xcode project (usually already separate)
└── ...project/
├── shared/ ← KMP库模块(原composeApp),仅包含纯共享代码
├── androidApp/ ← 仅包含Android入口点
├── desktopApp/ ← 仅包含桌面端入口点(如果存在桌面目标平台)
├── webApp/ ← 仅包含Wasm/JS入口点(如果存在Web目标平台)
├── iosApp/ ← iOS Xcode项目(通常已独立)
└── ...Steps
步骤
- Apply Path B first — extract (mandatory for AGP 9.0)
androidApp - Extract (if desktop target exists):
desktopApp- Create module with and
org.jetbrains.composepluginapplication {} - Move function from
main()todesktopMaindesktopApp/src/main/kotlin/ - Move config to
compose.desktop { application { ... } }desktopApp/build.gradle.kts - Add dependency on module
shared
- Create module with
- Extract (if wasmJs/js target exists):
webApp- Create module with appropriate Kotlin/JS or Kotlin/Wasm configuration
- Move web entry point from /
wasmJsMaintojsMainwebApp/src/wasmJsMain/kotlin/ - Move browser/distribution config to
webApp/build.gradle.kts - Add dependency on module
shared
- iOS — typically already in a separate directory. Verify:
iosApp- Framework export config () stays in
binaries.frameworkmoduleshared - Xcode project references the correct framework path
- Framework export config (
- Rename module from to
composeApp:shared- Rename directory
- Update include
settings.gradle.kts - Update all dependency references across modules
- Clean up shared module: remove all platform entry point code and app-specific config that was moved to the platform app modules
- 先执行路径B——提取模块(AGP 9.0兼容性强制要求)
androidApp - 提取模块(如果存在桌面目标平台):
desktopApp- 创建应用和
org.jetbrains.compose插件的模块application {} - 将函数从
main()移至desktopMaindesktopApp/src/main/kotlin/ - 将配置移至
compose.desktop { application { ... } }desktopApp/build.gradle.kts - 添加对模块的依赖
shared
- 创建应用
- 提取模块(如果存在wasmJs/js目标平台):
webApp- 创建配置了适当Kotlin/JS或Kotlin/Wasm的模块
- 将Web入口点从/
wasmJsMain移至jsMainwebApp/src/wasmJsMain/kotlin/ - 将浏览器/分发配置移至
webApp/build.gradle.kts - 添加对模块的依赖
shared
- iOS平台——通常已在独立的目录中。验证:
iosApp- 框架导出配置()保留在
binaries.framework模块中shared - Xcode项目引用了正确的框架路径
- 框架导出配置(
- 重命名模块:将更改为
composeApp:shared- 重命名目录
- 更新中的include配置
settings.gradle.kts - 更新所有模块间的依赖引用
- 清理共享模块:移除所有已移至平台应用模块的平台入口点代码和应用特定配置
Variant: Native UI
变体:原生UI
If some platforms use native UI (e.g., SwiftUI for iOS), split into:
shared- — business logic consumed by ALL platforms
sharedLogic - — Compose Multiplatform UI consumed only by platforms using shared UI
sharedUI
如果部分平台使用原生UI(如iOS的SwiftUI),可将拆分为:
shared- — 所有平台共享的业务逻辑
sharedLogic - — 仅由使用共享UI的平台消费的Compose Multiplatform UI
sharedUI
Variant: Server
变体:服务端
If the project includes a server target:
- Add module at the root
server - Move all client modules under an directory
app/ - Add module for code shared between server and client (models, validation)
core
如果项目包含服务端目标平台:
- 在根目录添加模块
server - 将所有客户端模块移至目录下
app/ - 添加模块,用于服务端和客户端共享的代码(如模型、验证逻辑)
core
Version Updates
版本更新
These are required regardless of migration path:
-
Gradle wrapper — update to 9.1.0+:properties
# gradle/wrapper/gradle-wrapper.properties distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip -
AGP version — update to 9.0.0+.If using a version catalog ():
gradle/libs.versions.tomltoml[versions] agp = "9.0.0"If versions are set directly in build files, update allplugin version strings:com.android.*kotlin// root build.gradle.kts plugins { id("com.android.application") version "9.0.0" apply false } -
Add the KMP library plugin.With version catalog:toml
[plugins] android-kotlin-multiplatform-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" }Without version catalog — use the plugin ID directly in build files:kotlin// root build.gradle.kts plugins { id("com.android.kotlin.multiplatform.library") version "9.0.0" apply false } // module build.gradle.kts plugins { id("com.android.kotlin.multiplatform.library") } -
Root build.gradle.kts — addfor new plugin (see examples above)
apply false -
JDK — ensure JDK 17+ is used (required by AGP 9.0)
-
SDK Build Tools — update to 36.0.0:
Install via SDK Manager or configure in android { buildToolsVersion = "36.0.0" } -
Remove legacy workarounds from:
gradle.properties- Remove (removed in AGP 9.0, causes error if present)
android.enableLegacyVariantApi=true - Remove (removed in AGP 9.0, causes error if present)
android.r8.integratedResourceShrinking - Remove (removed in AGP 9.0, causes error if present)
android.enableNewResourceShrinker.preciseShrinking - Remove (unless needed for plugin compatibility — see Plugin Compatibility)
android.builtInKotlin=false - Remove (unless needed for plugin compatibility)
android.newDsl=false
- Remove
-
Review gradle.properties defaults — see "Gradle Properties Default Changes" section for properties whose defaults changed in AGP 9.0
无论选择哪种迁移路径,以下更新均为必需:
-
Gradle包装器——升级至9.1.0+:properties
# gradle/wrapper/gradle-wrapper.properties distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip -
AGP版本——升级至9.0.0+。如果使用版本目录():
gradle/libs.versions.tomltoml[versions] agp = "9.0.0"如果直接在构建文件中设置版本,更新所有插件的版本字符串:com.android.*kotlin// 根目录build.gradle.kts plugins { id("com.android.application") version "9.0.0" apply false } -
添加KMP库插件。使用版本目录:toml
[plugins] android-kotlin-multiplatform-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" }不使用版本目录——直接在构建文件中使用插件ID:kotlin// 根目录build.gradle.kts plugins { id("com.android.kotlin.multiplatform.library") version "9.0.0" apply false } // 模块build.gradle.kts plugins { id("com.android.kotlin.multiplatform.library") } -
根目录build.gradle.kts——为新插件添加声明(见上方示例)
apply false -
JDK——确保使用JDK 17+(AGP 9.0要求)
-
SDK构建工具——升级至36.0.0:
通过SDK Manager安装,或在android { buildToolsVersion = "36.0.0" }中配置 -
移除gradle.properties中的旧版变通方案:
- 移除(AGP 9.0已移除,若存在会导致错误)
android.enableLegacyVariantApi=true - 移除(AGP 9.0已移除,若存在会导致错误)
android.r8.integratedResourceShrinking - 移除(AGP 9.0已移除,若存在会导致错误)
android.enableNewResourceShrinker.preciseShrinking - 移除(除非因插件兼容性需要——详见插件兼容性章节)
android.builtInKotlin=false - 移除(除非因插件兼容性需要)
android.newDsl=false
- 移除
-
检查gradle.properties默认值变更——查看“Gradle属性默认值变更”章节,了解AGP 9.0中默认值已变更的属性
Built-in Kotlin Migration
内置Kotlin迁移
AGP 9.0 enables built-in Kotlin support by default for all and
modules. The plugin is no longer needed and will conflict if applied.
com.android.applicationcom.android.libraryorg.jetbrains.kotlin.androidImportant: Built-in Kotlin does NOT replace KMP support. KMP library modules still need
+ .
org.jetbrains.kotlin.multiplatformcom.android.kotlin.multiplatform.libraryAGP 9.0默认对所有和模块启用内置Kotlin支持。插件不再需要,若应用会产生冲突。
com.android.applicationcom.android.libraryorg.jetbrains.kotlin.android重要提示:内置Kotlin并不替代KMP支持。KMP库模块仍需使用 + 。
org.jetbrains.kotlin.multiplatformcom.android.kotlin.multiplatform.libraryDetection
检测
Check if the project uses or in any build files.
If found, this migration is needed. If not, check for
which may indicate a previous opt-out.
org.jetbrains.kotlin.androidkotlin-androidgradle.propertiesandroid.builtInKotlin=false检查项目是否在任何构建文件中使用或。如果存在,需要进行此迁移;如果不存在,检查中是否有(这可能表示之前选择了退出内置支持)。
org.jetbrains.kotlin.androidkotlin-androidgradle.propertiesandroid.builtInKotlin=falseStep 1: Remove kotlin-android Plugin
步骤1:移除kotlin-android插件
Remove from all module-level and root-level build files:
kotlin
// Remove from module build.gradle.kts
plugins {
// REMOVE: alias(libs.plugins.kotlin.android)
// REMOVE: id("org.jetbrains.kotlin.android")
}
// Remove from root build.gradle.kts
plugins {
// REMOVE: alias(libs.plugins.kotlin.android) apply false
}Remove from version catalog ():
gradle/libs.versions.tomltoml
[plugins]从所有模块级和根目录级构建文件中移除:
kotlin
// 从模块build.gradle.kts中移除
plugins {
// 移除: alias(libs.plugins.kotlin.android)
// 移除: id("org.jetbrains.kotlin.android")
}
// 从根目录build.gradle.kts中移除
plugins {
// 移除: alias(libs.plugins.kotlin.android) apply false
}从版本目录()中移除:
gradle/libs.versions.tomltoml
[plugins]REMOVE: kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
移除: kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
undefinedundefinedStep 2: Migrate kapt to KSP or legacy-kapt
步骤2:将kapt迁移至KSP或legacy-kapt
The plugin is incompatible with built-in Kotlin.
org.jetbrains.kotlin.kaptPreferred: Migrate to KSP — see the KSP migration guide for each annotation processor.
Fallback: Use (same version as AGP):
com.android.legacy-kapttoml
undefinedorg.jetbrains.kotlin.kapt首选方案:迁移至KSP——请参考每个注解处理器的KSP迁移指南。
备选方案:使用(版本与AGP相同):
com.android.legacy-kapttoml
undefinedgradle/libs.versions.toml
gradle/libs.versions.toml
[plugins]
legacy-kapt = { id = "com.android.legacy-kapt", version.ref = "agp" }
```kotlin
// Module build.gradle.kts — replace kotlin-kapt with legacy-kapt
plugins {
// REMOVE: alias(libs.plugins.kotlin.kapt)
alias(libs.plugins.legacy.kapt)
}[plugins]
legacy-kapt = { id = "com.android.legacy-kapt", version.ref = "agp" }
```kotlin
// 模块build.gradle.kts — 用legacy-kapt替换kotlin-kapt
plugins {
// 移除: alias(libs.plugins.kotlin.kapt)
alias(libs.plugins.legacy.kapt)
}Step 3: Migrate kotlinOptions to compilerOptions
步骤3:将kotlinOptions迁移至compilerOptions
For pure Android modules (non-KMP), migrate to the top-level
:
android.kotlinOptions {}kotlin.compilerOptions {}kotlin
// Old
android {
kotlinOptions {
jvmTarget = "11"
languageVersion = "2.0"
freeCompilerArgs += listOf("-Xopt-in=kotlin.RequiresOptIn")
}
}
// New
kotlin {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11)
languageVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0)
optIn.add("kotlin.RequiresOptIn")
}
}Note: With built-in Kotlin, defaults to ,
so it may be optional if you already set .
jvmTargetandroid.compileOptions.targetCompatibilitycompileOptions对于纯Android模块(非KMP),将迁移至顶级:
android.kotlinOptions {}kotlin.compilerOptions {}kotlin
// 旧写法
android {
kotlinOptions {
jvmTarget = "11"
languageVersion = "2.0"
freeCompilerArgs += listOf("-Xopt-in=kotlin.RequiresOptIn")
}
}
// 新写法
kotlin {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11)
languageVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0)
optIn.add("kotlin.RequiresOptIn")
}
}注意:使用内置Kotlin时,默认值为,因此如果已设置,该配置可能为可选。
jvmTargetandroid.compileOptions.targetCompatibilitycompileOptionsStep 4: Migrate kotlin.sourceSets to android.sourceSets
步骤4:将kotlin.sourceSets迁移至android.sourceSets
With built-in Kotlin, only with the set is supported:
android.sourceSets {}kotlinkotlin
// NOT SUPPORTED with built-in Kotlin:
kotlin.sourceSets.named("main") {
kotlin.srcDir("additionalSourceDirectory/kotlin")
}
// Correct:
android.sourceSets.named("main") {
kotlin.directories += "additionalSourceDirectory/kotlin"
}For generated sources, use the Variant API:
kotlin
androidComponents.onVariants { variant ->
variant.sources.kotlin!!.addStaticSourceDirectory("additionalSourceDirectory/kotlin")
}使用内置Kotlin时,仅支持搭配集合:
android.sourceSets {}kotlinkotlin
// 内置Kotlin不支持此写法:
kotlin.sourceSets.named("main") {
kotlin.srcDir("additionalSourceDirectory/kotlin")
}
// 正确写法:
android.sourceSets.named("main") {
kotlin.directories += "additionalSourceDirectory/kotlin"
}对于生成的源码,使用Variant API:
kotlin
androidComponents.onVariants { variant ->
variant.sources.kotlin!!.addStaticSourceDirectory("additionalSourceDirectory/kotlin")
}Per-Module Migration Strategy
分模块迁移策略
For large projects, migrate module-by-module:
- Disable globally: in
android.builtInKotlin=falsegradle.properties - Enable per migrated module by applying the opt-in plugin:
kotlin
plugins { id("com.android.built-in-kotlin") version "AGP_VERSION" } - Follow Steps 1-4 for that module
- Once all modules are migrated, remove and all
android.builtInKotlin=falsepluginscom.android.built-in-kotlin
对于大型项目,可分模块进行迁移:
- 全局禁用:在中设置
gradle.propertiesandroid.builtInKotlin=false - 对已迁移的模块启用:应用opt-in插件:
kotlin
plugins { id("com.android.built-in-kotlin") version "AGP_VERSION" } - 对该模块执行步骤1-4
- 所有模块迁移完成后,移除以及所有
android.builtInKotlin=false插件com.android.built-in-kotlin
Optional: Disable Kotlin for Non-Kotlin Modules
可选:为非Kotlin模块禁用Kotlin
For modules that contain no Kotlin sources, disable built-in Kotlin to save build time:
kotlin
android {
enableKotlin = false
}对于不包含任何Kotlin源码的模块,可禁用内置Kotlin以节省构建时间:
kotlin
android {
enableKotlin = false
}Opt-Out (Temporary)
退出(临时)
If blocked by plugin incompatibilities, opt out temporarily:
properties
undefined如果因插件兼容性问题受阻,可临时退出:
properties
undefinedgradle.properties
gradle.properties
android.builtInKotlin=false
android.newDsl=false # also required if using new DSL opt-out
**Warning:** Ask the user if they want to opt out, and if so,
remind them this is a temporary measure.android.builtInKotlin=false
android.newDsl=false # 如果使用新DSL退出,也需要设置此属性
**警告**:请询问用户是否要退出,并提醒这只是临时措施。Plugin Compatibility
插件兼容性
See references/PLUGIN-COMPATIBILITY.md for the full compatibility
table with known compatible versions, opt-out flag workarounds, and broken plugins.
Before migrating, inventory all plugins in the project and check each against that table. If any
plugin is broken without workaround, inform the user. If plugins need opt-out flags, add them to
and note them as temporary workarounds.
gradle.properties完整的兼容性表格(包含已知兼容版本、退出标志变通方案和已损坏插件)请参考references/PLUGIN-COMPATIBILITY.md。
迁移前,请清点项目中的所有插件,并逐一对照该表格。如果任何插件已损坏且无变通方案,请告知用户;如果插件需要退出标志,请将其添加至并注明为临时变通方案。
gradle.propertiesGradle Properties Default Changes
Gradle属性默认值变更
AGP 9.0 changes the defaults for many gradle properties. Check for any explicitly
set values that may now conflict. Key changes:
gradle.properties| Property | Old Default | New Default | Action |
|---|---|---|---|
| | | Ensure each library has a unique namespace |
| | | Refactor |
| | | Enable |
| | | Enable shaders where needed |
| | | Review R8 keep rules |
| | | Update keep rules to be explicit |
| | | Remove invalid ProGuard file references |
| | | Use |
| | | Remove global options from library consumer rules |
| | | Use |
| | | Specify |
| | | Only if testing non-default build types |
Check for and remove properties that now cause errors:
- — removed, always on
android.r8.integratedResourceShrinking - — removed, always on
android.enableNewResourceShrinker.preciseShrinking
AGP 9.0变更了许多Gradle属性的默认值。请检查中是否存在任何显式设置的值,这些值现在可能与默认值冲突。主要变更如下:
gradle.properties| 属性 | 旧默认值 | 新默认值 | 操作 |
|---|---|---|---|
| | | 确保每个库都有唯一的命名空间 |
| | | 将基于R字段的 |
| | | 在需要的地方启用 |
| | | 在需要的地方启用着色器 |
| | | 检查R8保留规则 |
| | | 更新保留规则使其更明确 |
| | | 移除无效的ProGuard文件引用 |
| | | 仅使用 |
| | | 从库消费者规则中移除全局选项 |
| | | 在androidComponents上使用 |
| | | 显式指定 |
| | | 仅在测试非默认构建类型时需要调整 |
检查并移除现在会导致错误的属性:
- — 已移除,始终启用
android.r8.integratedResourceShrinking - — 已移除,始终启用
android.enableNewResourceShrinker.preciseShrinking
Pure Android Tips
纯Android项目提示
For non-KMP Android modules upgrading to AGP 9.0:
- Remove plugin — AGP 9.0 includes Kotlin support built-in (see "Built-in Kotlin Migration" above)
org.jetbrains.kotlin.android - Migrate kapt to KSP or
com.android.legacy-kapt - Migrate to
kotlinOptionskotlin { compilerOptions {} } - Migrate to
kotlin.sourceSetswithandroid.sourceSetsaccessor.kotlin - Review new DSL interfaces — is removed; use
BaseExtensionor specific extension typesCommonExtension - Java default changed from Java 8 to Java 11 — ensure reflects this
compileOptions - R class is now compile-time non-final in app modules — refactor any statements on R class fields to
switchif/else - targetSdk defaults to compileSdk if not set — specify explicitly to avoid surprises
targetSdk - NDK default changed to r28c — specify explicitly if using native code
ndkVersion - Temporary opt-out: +
android.builtInKotlin=falseinandroid.newDsl=false(removed in AGP 10)gradle.properties
对于未使用KMP的Android项目升级至AGP 9.0:
- 移除插件——AGP 9.0已内置Kotlin支持(详见“内置Kotlin迁移”章节)
org.jetbrains.kotlin.android - 将kapt迁移至KSP或
com.android.legacy-kapt - 将迁移至
kotlinOptionskotlin { compilerOptions {} } - 将迁移至带有
kotlin.sourceSets访问器的.kotlinandroid.sourceSets - 查看新DSL接口——已移除;请使用
BaseExtension或特定的扩展类型CommonExtension - Java默认版本从8变更为11——确保反映此变更
compileOptions - R类在应用模块中现为编译时非final——将任何基于R类字段的语句重构为
switchif/else - 如果未设置,默认值为compileSdk——请显式指定
targetSdk以避免意外targetSdk - NDK默认版本变更为r28c——如果使用原生代码,请显式指定
ndkVersion - 临时退出:在中设置
gradle.properties+android.builtInKotlin=false(AGP 10中将移除该选项)android.newDsl=false
Verification
验证
After migration, verify with the checklist. Key checks:
- succeeds with no errors
./gradlew build - succeeds (if app module exists)
./gradlew :androidApp:assembleDebug - No or
com.android.libraryin KMP modulescom.android.application - No in AGP 9.0 modules
org.jetbrains.kotlin.android - Source sets use correct names (,
androidMain,androidHostTest)androidDeviceTest - No deprecation warnings about variant API
- Run configurations point to correct modules
迁移完成后,请使用检查清单进行验证。关键检查点:
- 执行成功,无错误
./gradlew build - 执行成功(如果存在应用模块)
./gradlew :androidApp:assembleDebug - KMP模块中不存在或
com.android.library插件com.android.application - AGP 9.0模块中不存在插件
org.jetbrains.kotlin.android - 源码集使用正确的名称(、
androidMain、androidHostTest)androidDeviceTest - 无关于variant API的弃用警告
- 运行配置指向正确的模块
Common Issues
常见问题
See references/KNOWN-ISSUES.md for details. Key gotchas:
详细内容请参考references/KNOWN-ISSUES.md。主要注意事项:
KMP Library Plugin Issues
KMP库插件问题
- BuildConfig unavailable in library modules — use DI/interface, or use BuildKonfig or gradle-buildconfig-plugin for compile-time constants
AppConfiguration - No build variants — single variant architecture; compile-time constants can use BuildKonfig/gradle-buildconfig-plugin flavors, but variant-specific dependencies/resources/signing must move to app module
- NDK/JNI unsupported in new plugin — extract to separate module
com.android.library - Compose resources crash without (CMP-9547)
androidResources { enable = true } - Consumer ProGuard rules silently dropped if not migrated to in new DSL
consumerProguardFiles.add(file(...)) - KSP requires version 2.3.4+ for AGP 9.0 compatibility
- BuildConfig在库模块中不可用——使用DI/接口,或使用BuildKonfig或gradle-buildconfig-plugin生成编译时常量
AppConfiguration - 无构建变体——单一变体架构;编译时常量可使用BuildKonfig/gradle-buildconfig-plugin的flavors,但变体特定的依赖/资源/签名必须移至应用模块
- 新插件不支持NDK/JNI——将其提取至独立的模块
com.android.library - 未设置时Compose资源崩溃(CMP-9547)
androidResources { enable = true } - 如果未迁移至新DSL中的,消费者ProGuard规则会被静默丢弃
consumerProguardFiles.add(file(...)) - KSP需要2.3.4+版本才能兼容AGP 9.0
AGP 9.0 General Issues
AGP 9.0通用问题
- Built-in Kotlin conflicts — must be removed; kapt must be replaced
org.jetbrains.kotlin.android - BaseExtension removed — convention plugins using old DSL types need rewriting
- Variant APIs removed — ,
applicationVariants,libraryVariantsreplaced byvariantFilterandroidComponents - R class non-final — on R fields fails in app modules; refactor to
switchif/else - targetSdk defaults to compileSdk — set explicitly to avoid unexpected behavior changes
- R8 rule changes — strict full mode, no global options in consumer rules
- Plugin compatibility — many plugins need updates or opt-out flags; check Plugin Compatibility section
- Convention plugins need refactoring — old extension helpers are obsolete
android {}
- 内置Kotlin冲突——必须移除;必须替换kapt
org.jetbrains.kotlin.android - BaseExtension已移除——使用旧DSL类型的约定插件需要重写
- Variant API已移除——、
applicationVariants、libraryVariants已被variantFilter替代androidComponents - R类非final——应用模块中基于R字段的语句会失败;需重构为
switchif/else - targetSdk默认值为compileSdk——请显式设置以避免意外行为变更
- R8规则变更——严格全模式,消费者规则中不允许全局选项
- 插件兼容性——许多插件需要更新或退出标志;请查看插件兼容性章节
- 约定插件需要重构——旧的扩展助手已过时
android {}
Reference Files
参考文件
- DSL Reference — side-by-side old→new DSL mapping
- Version Matrix — AGP/Gradle/KGP/IDE compatibility
- Plugin Compatibility — third-party plugin status and workarounds
- DSL参考——新旧DSL映射对比
- 版本矩阵——AGP/Gradle/KGP/IDE兼容性
- 插件兼容性——第三方插件状态和变通方案