kotlin-tooling-agp9-migration by kotlin/kotlin-agent-skills
npx skills add https://github.com/kotlin/kotlin-agent-skills --skill kotlin-tooling-agp9-migrationAndroid Gradle Plugin 9.0 使得 Android 应用和库插件与同一模块中的 Kotlin Multiplatform 插件不兼容。本技能将指导您完成迁移过程。
在进行任何更改之前,请先理解项目结构:
settings.gradle.kts(或 .gradle)以查找所有模块build.gradle.kts 以识别应用了哪些插件gradle/libs.versions.toml)。如果存在,请阅读它以获取当前的 AGP/Gradle/Kotlin 版本。如果不存在,直接在 build.gradle.kts 文件中查找版本(通常在根目录的 buildscript {} 或 plugins {} 块中)。请相应调整本指南中的所有示例 — 版本目录示例使用 alias(libs.plugins.xxx),而直接使用则使用 广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
id("plugin.id") version "x.y.z"gradle/wrapper/gradle-wrapper.properties 以获取 Gradle 版本gradle.properties 中是否存在任何现有的变通方案(android.enableLegacyVariantApi)org.jetbrains.kotlin.android 插件 — AGP 9.0 内置了 Kotlin 支持,必须移除此插件org.jetbrains.kotlin.kapt 插件 — 与内置 Kotlin 不兼容,必须迁移到 KSP 或 com.android.legacy-kapt如果 Bash 可用,请从本技能目录运行 scripts/analyze-project.sh 以获取结构化摘要。
对于每个模块,确定其类型:
| 当前插件 | 迁移路径 |
|---|---|
kotlin.multiplatform + com.android.library | 路径 A — 库插件替换 |
kotlin.multiplatform + com.android.application | 路径 B — 强制 Android 拆分 |
kotlin.multiplatform 在一个模块中包含多个平台入口点 | 路径 C — 完全重构(推荐) |
com.android.application 或 com.android.library(无 KMP) | 参见下面的“纯 Android 提示” |
composeApp(或类似)模块时。这符合新的 JetBrains 默认项目结构,其中每个平台都有自己的应用模块。当一个模块应用了 kotlin.multiplatform + com.android.library 时使用此路径。
完整的前后代码请参见 references/MIGRATION-LIBRARY.md。
摘要:
替换插件:com.android.library → com.android.kotlin.multiplatform.library
移除org.jetbrains.kotlin.android 插件(如果存在)(AGP 9.0 内置了 Kotlin 支持)
迁移 DSL:将配置从顶层的 android {} 块移动到 kotlin { android {} } 中:
kotlin {
android {
namespace = "com.example.lib"
compileSdk = 35
minSdk = 24
}
}
重命名源代码目录(仅当模块使用经典的 Android 布局而不是 KMP 布局时):
src/main → src/androidMainsrc/test → src/androidHostTestsrc/androidTest → src/androidDeviceTestsrc/androidMain/,则无需重命名目录移动依赖项:从顶层的 dependencies {} 移动到 sourceSets 中:
kotlin {
sourceSets {
androidMain.dependencies {
implementation("androidx.appcompat:appcompat:1.7.0")
}
}
}
显式启用资源(如果模块使用 Android 资源):
kotlin {
android {
androidResources { enable = true }
}
}
启用 Java 编译(如果模块有 .java 源文件):
kotlin {
android {
withJava()
}
}
显式启用测试(如果模块有单元测试或仪器化测试):
kotlin {
android {
withHostTest { isIncludeAndroidResources = true }
withDeviceTest {
instrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
}
}
更新 Compose 工具依赖项:
// 旧: debugImplementation(libs.androidx.compose.ui.tooling)
// 新:
dependencies {
androidRuntimeClasspath(libs.androidx.compose.ui.tooling)
}
显式发布消费者 ProGuard 规则(如果适用):
kotlin { android { consumerProguardFiles.add(file("consumer-rules.pro")) } }
当一个模块应用了 kotlin.multiplatform + com.android.application 时使用此路径。这对于 AGP 9.0 兼容性是强制性的。
完整指南请参见 references/MIGRATION-APP-SPLIT.md。
摘要:
创建androidApp模块,并拥有自己的 build.gradle.kts:
plugins {
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/:
MainActivity.kt(以及任何其他 Activities/Fragments)AndroidManifest.xml(应用级清单,包含 <application> 和启动器 <activity>)— 验证 <activity> 上的 android:name 使用了其新位置的完全限定类名添加到settings.gradle.kts:include(":androidApp")
添加到根build.gradle.kts:带有 apply false 的插件声明
转换原始模块:使用路径 A 的步骤将应用模块转换为库模块
确保不同的命名空间:应用模块和库模块必须具有不同的命名空间
从共享模块中移除:applicationId、targetSdk、versionCode、versionName
更新 IDE 运行配置:将模块从旧模块更改为 androidApp
当项目有一个包含多个平台入口点的单一模块(通常是 composeApp)时使用此路径。这是可选的,但符合新的 JetBrains 默认结构。
project/
├── shared/ ← KMP 库(原 composeApp),纯共享代码
├── androidApp/ ← 仅 Android 入口点
├── desktopApp/ ← 仅桌面入口点(如果存在桌面目标)
├── webApp/ ← 仅 Wasm/JS 入口点(如果存在 Web 目标)
├── iosApp/ ← iOS Xcode 项目(通常已独立)
└── ...
androidApp(对于 AGP 9.0 是强制性的)desktopApp(如果存在桌面目标):
org.jetbrains.compose 和 application {} 插件的模块main() 函数从 desktopMain 移动到 desktopApp/src/main/kotlin/compose.desktop { application { ... } } 配置移动到 desktopApp/build.gradle.ktsshared 模块的依赖webApp(如果存在 wasmJs/js 目标):
wasmJsMain/jsMain 移动到 webApp/src/wasmJsMain/kotlin/webApp/build.gradle.ktsshared 模块的依赖iosApp 目录中。请验证:
binaries.framework)保留在 shared 模块中composeApp 重命名为 shared:
settings.gradle.kts 中的 include 语句如果某些平台使用原生 UI(例如,iOS 使用 SwiftUI),则将 shared 拆分为:
sharedLogic — 被所有平台使用的业务逻辑sharedUI — 仅被使用共享 UI 的平台使用的 Compose Multiplatform UI如果项目包含服务器目标:
server 模块app/ 目录下core 模块,用于服务器和客户端之间共享的代码(模型、验证)无论采用哪种迁移路径,以下更新都是必需的:
Gradle wrapper — 更新到 9.1.0+:
# gradle/wrapper/gradle-wrapper.properties
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
AGP 版本 — 更新到 9.0.0+。
如果使用版本目录(gradle/libs.versions.toml):
[versions]
agp = "9.0.0"
如果版本直接在构建文件中设置,请更新所有 com.android.* 插件版本字符串:
// 根 build.gradle.kts
plugins {
id("com.android.application") version "9.0.0" apply false
}
3. 添加 KMP 库插件。
使用版本目录:
[plugins]
android-kotlin-multiplatform-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" }
不使用版本目录 — 直接在构建文件中使用插件 ID:
// 根 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")
}
4. 根 build.gradle.kts — 为新插件添加 apply false(参见上面的示例)
JDK — 确保使用 JDK 17+(AGP 9.0 要求)
SDK 构建工具 — 更新到 36.0.0:
通过 SDK Manager 安装或在 android { buildToolsVersion = "36.0.0" } 中配置
从gradle.properties中移除遗留的变通方案:
android.enableLegacyVariantApi=true(在 AGP 9.0 中已移除,如果存在会导致错误)android.r8.integratedResourceShrinking(在 AGP 9.0 中已移除,如果存在会导致错误)android.enableNewResourceShrinker.preciseShrinking(在 AGP 9.0 中已移除,如果存在会导致错误)android.builtInKotlin=false(除非插件兼容性需要 — 参见插件兼容性)android.newDsl=false(除非插件兼容性需要)检查 gradle.properties 默认值 — 参见“Gradle 属性默认值变更”部分,了解在 AGP 9.0 中默认值发生变化的属性
AGP 9.0 默认对所有 com.android.application 和 com.android.library 模块启用内置 Kotlin 支持。不再需要 org.jetbrains.kotlin.android 插件,如果应用了该插件,将会发生冲突。
重要提示: 内置 Kotlin 并不替代 KMP 支持。KMP 库模块仍然需要 org.jetbrains.kotlin.multiplatform + com.android.kotlin.multiplatform.library。
检查项目是否在任何构建文件中使用了 org.jetbrains.kotlin.android 或 kotlin-android。如果找到,则需要进行此迁移。如果没有找到,请检查 gradle.properties 中是否有 android.builtInKotlin=false,这可能表明之前选择了退出。
从所有模块级和根级构建文件中移除:
// 从模块 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.toml):
[plugins]
# 移除: kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
org.jetbrains.kotlin.kapt 插件与内置 Kotlin 不兼容。
首选:迁移到 KSP — 请参阅每个注解处理器的 KSP 迁移指南。
备选方案:使用com.android.legacy-kapt(版本与 AGP 相同):
# gradle/libs.versions.toml
[plugins]
legacy-kapt = { id = "com.android.legacy-kapt", version.ref = "agp" }
// 模块 build.gradle.kts — 将 kotlin-kapt 替换为 legacy-kapt
plugins {
// 移除: alias(libs.plugins.kotlin.kapt)
alias(libs.plugins.legacy.kapt)
}
对于纯 Android 模块(非 KMP),将 android.kotlinOptions {} 迁移到顶层的 kotlin.compilerOptions {}:
// 旧
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 时,jvmTarget 默认为 android.compileOptions.targetCompatibility,因此如果您已经设置了 compileOptions,则 jvmTarget 可能是可选的。
使用内置 Kotlin 时,仅支持带有 kotlin 集合的 android.sourceSets {}:
// 内置 Kotlin 不支持:
kotlin.sourceSets.named("main") {
kotlin.srcDir("additionalSourceDirectory/kotlin")
}
// 正确:
android.sourceSets.named("main") {
kotlin.directories += "additionalSourceDirectory/kotlin"
}
对于生成的源代码,请使用 Variant API:
androidComponents.onVariants { variant ->
variant.sources.kotlin!!.addStaticSourceDirectory("additionalSourceDirectory/kotlin")
}
对于大型项目,逐个模块进行迁移:
全局禁用:在 gradle.properties 中设置 android.builtInKotlin=false
为每个已迁移的模块启用,方法是应用选择加入插件:
plugins {
id("com.android.built-in-kotlin") version "AGP_VERSION"
}
为该模块遵循步骤 1-4
一旦所有模块都迁移完毕,移除 android.builtInKotlin=false 和所有 com.android.built-in-kotlin 插件
对于包含没有 Kotlin 源代码的模块,禁用内置 Kotlin 以节省构建时间:
android {
enableKotlin = false
}
如果因插件不兼容而受阻,可以临时选择退出:
# gradle.properties
android.builtInKotlin=false
android.newDsl=false # 如果使用新 DSL 选择退出,也需要此项
警告: 询问用户是否想要选择退出,如果是,请提醒他们这只是临时措施。
完整的兼容性表格,包括已知兼容版本、选择退出标志的变通方案以及已损坏的插件,请参见 references/PLUGIN-COMPATIBILITY.md。
在迁移之前,请清点项目中的所有插件,并根据该表格检查每个插件。如果有任何插件损坏且没有变通方案,请通知用户。如果插件需要选择退出标志,请将它们添加到 gradle.properties 中,并注明它们是临时的变通方案。
AGP 9.0 更改了许多 gradle 属性的默认值。检查 gradle.properties 中是否有任何显式设置的值可能与新默认值冲突。关键变更:
| 属性 | 旧默认值 | 新默认值 | 操作 |
|---|---|---|---|
android.uniquePackageNames | false | true | 确保每个库都有唯一的命名空间 |
android.enableAppCompileTimeRClass | false | true | 将 R 字段上的 switch 重构为 if/else |
android.defaults.buildfeatures.resvalues | true | false | 在需要的地方启用 resValues = true |
android.defaults.buildfeatures.shaders | true | false | 在需要的地方启用着色器 |
android.r8.optimizedResourceShrinking | false | true | 检查 R8 保留规则 |
android.r8.strictFullModeForKeepRules | false | true | 更新保留规则使其更明确 |
android.proguard.failOnMissingFiles | false | true | 移除无效的 ProGuard 文件引用 |
android.r8.proguardAndroidTxt.disallowed | false | true | 仅使用 proguard-android-optimize.txt |
android.r8.globalOptionsInConsumerRules.disallowed | false | true | 从库消费者规则中移除全局选项 |
android.sourceset.disallowProvider | false | true | 在 androidComponents 上使用 Sources API |
android.sdk.defaultTargetSdkToCompileSdkIfUnset | false | true | 显式指定 targetSdk |
android.onlyEnableUnitTestForTheTestedBuildType | false | true | 仅当测试非默认构建类型时 |
检查并移除现在会导致错误的属性:
android.r8.integratedResourceShrinking — 已移除,始终启用android.enableNewResourceShrinker.preciseShrinking — 已移除,始终启用对于升级到 AGP 9.0 的非 KMP Android 模块:
org.jetbrains.kotlin.android 插件 — AGP 9.0 内置了 Kotlin 支持(参见上面的“内置 Kotlin 迁移”)com.android.legacy-kaptkotlinOptions迁移到 kotlin { compilerOptions {} }kotlin.sourceSets迁移到带有 .kotlin 访问器的 android.sourceSetsBaseExtension 已被移除;使用 CommonExtension 或特定的扩展类型compileOptions 反映了这一点switch 语句重构为 if/elsetargetSdk 以避免意外ndkVersiongradle.properties 中设置 android.builtInKotlin=false + android.newDsl=false(在 AGP 10 中移除)迁移后,请使用检查清单进行验证。关键检查点:
./gradlew build 成功且无错误./gradlew :androidApp:assembleDebug 成功(如果存在应用模块)com.android.library 或 com.android.applicationorg.jetbrains.kotlin.androidandroidMain、androidHostTest、androidDeviceTest)详细信息请参见 references/KNOWN-ISSUES.md。关键陷阱:
AppConfiguration 接口,或使用 BuildKonfig 或 gradle-buildconfig-plugin 获取编译时常量com.android.library 模块androidResources { enable = true } 时 Compose 资源会崩溃(CMP-9547)consumerProguardFiles.add(file(...)) 会被静默丢弃org.jetbrains.kotlin.android;kapt 必须被替换applicationVariants、libraryVariants、variantFilter 被 androidComponents 取代switch 会失败;重构为 if/elseandroid {} 扩展助手已过时每周安装次数
71
代码仓库
GitHub 星标数
214
首次出现
9 天前
安全审计
安装于
opencode66
codex66
gemini-cli66
github-copilot66
amp65
cline65
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.
Before making any changes, understand the project structure:
settings.gradle.kts (or .gradle) to find all modulesbuild.gradle.kts to identify which plugins are appliedgradle/libs.versions.toml). If it exists, read it for current AGP/Gradle/Kotlin versions. If not, find versions directly in build.gradle.kts files (typically in the root buildscript {} or plugins {} block). Adapt all examples in this guide accordingly — version catalog examples use alias(libs.plugins.xxx) while direct usage uses id("plugin.id") version "x.y.z"gradle/wrapper/gradle-wrapper.properties for the Gradle versiongradle.properties for any existing workarounds (android.enableLegacyVariantApi)org.jetbrains.kotlin.android plugin usage — AGP 9.0 has built-in Kotlin and this plugin must be removedorg.jetbrains.kotlin.kapt plugin usage — incompatible with built-in Kotlin, must migrate to KSP or com.android.legacy-kaptIf Bash is available, run scripts/analyze-project.sh from this skill's directory to get a structured summary.
For each module, determine its type:
| Current plugins | Migration path |
|---|---|
kotlin.multiplatform + com.android.library | Path A — Library plugin swap |
kotlin.multiplatform + com.android.application | Path B — Mandatory Android split |
kotlin.multiplatform with multiple platform entry points in one module | Path C — Full restructure (recommended) |
com.android.application or com.android.library (no KMP) |
composeApp (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.Use this when a module applies kotlin.multiplatform + com.android.library.
See references/MIGRATION-LIBRARY.md for full before/after code.
Summary:
Replace plugin : com.android.library → com.android.kotlin.multiplatform.library
Removeorg.jetbrains.kotlin.android plugin if present (AGP 9.0 has built-in Kotlin support)
Migrate DSL : Move config from top-level android {} block into kotlin { android {} }:
kotlin {
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/main → Use this when a module applies kotlin.multiplatform + com.android.application. This is mandatory for AGP 9.0 compatibility.
See references/MIGRATION-APP-SPLIT.md for full guide.
Summary:
CreateandroidApp module with its own build.gradle.kts:
plugins {
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 src/androidMain/ to androidApp/src/main/:
Use this when the project has a monolithic module (typically composeApp) containing entry points for multiple platforms. This is optional but aligns with the new JetBrains default.
See references/MIGRATION-FULL-RESTRUCTURE.md for full guide.
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)
└── ...
androidApp (mandatory for AGP 9.0)desktopApp (if desktop target exists):
org.jetbrains.compose and application {} pluginmain() function from desktopMain to desktopApp/src/main/kotlin/compose.desktop { application { ... } } config to desktopApp/build.gradle.ktsIf some platforms use native UI (e.g., SwiftUI for iOS), split shared into:
sharedLogic — business logic consumed by ALL platformssharedUI — Compose Multiplatform UI consumed only by platforms using shared UIIf the project includes a server target:
server module at the rootapp/ directorycore module for code shared between server and client (models, validation)These are required regardless of migration path:
Gradle wrapper — update to 9.1.0+:
# 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.toml):
[versions]
agp = "9.0.0"
If versions are set directly in build files, update all com.android.* plugin version strings:
// root build.gradle.kts
plugins {
id("com.android.application") version "9.0.0" apply false
}
3. Add the KMP library plugin.
With version catalog:
[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:
// 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")
}
4. Root build.gradle.kts — add apply false for new plugin (see examples above)
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:
android.enableLegacyVariantApi=true (removed in AGP 9.0, causes error if present)android.r8.integratedResourceShrinking (removed in AGP 9.0, causes error if present)android.enableNewResourceShrinker.preciseShrinking (removed in AGP 9.0, causes error if present)android.builtInKotlin=false (unless needed for plugin compatibility — see Plugin Compatibility)AGP 9.0 enables built-in Kotlin support by default for all com.android.application and com.android.library modules. The org.jetbrains.kotlin.android plugin is no longer needed and will conflict if applied.
Important: Built-in Kotlin does NOT replace KMP support. KMP library modules still need org.jetbrains.kotlin.multiplatform + com.android.kotlin.multiplatform.library.
Check if the project uses org.jetbrains.kotlin.android or kotlin-android in any build files. If found, this migration is needed. If not, check gradle.properties for android.builtInKotlin=false which may indicate a previous opt-out.
Remove from all module-level and root-level build files:
// 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.toml):
[plugins]
# REMOVE: kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
The org.jetbrains.kotlin.kapt plugin is incompatible with built-in Kotlin.
Preferred: Migrate to KSP — see the KSP migration guide for each annotation processor.
Fallback: Usecom.android.legacy-kapt (same version as AGP):
# gradle/libs.versions.toml
[plugins]
legacy-kapt = { id = "com.android.legacy-kapt", version.ref = "agp" }
// Module build.gradle.kts — replace kotlin-kapt with legacy-kapt
plugins {
// REMOVE: alias(libs.plugins.kotlin.kapt)
alias(libs.plugins.legacy.kapt)
}
For pure Android modules (non-KMP), migrate android.kotlinOptions {} to the top-level kotlin.compilerOptions {}:
// 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, jvmTarget defaults to android.compileOptions.targetCompatibility, so it may be optional if you already set compileOptions.
With built-in Kotlin, only android.sourceSets {} with the kotlin set is supported:
// 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:
androidComponents.onVariants { variant ->
variant.sources.kotlin!!.addStaticSourceDirectory("additionalSourceDirectory/kotlin")
}
For large projects, migrate module-by-module:
Disable globally: android.builtInKotlin=false in gradle.properties
Enable per migrated module by applying the opt-in plugin:
plugins {
id("com.android.built-in-kotlin") version "AGP_VERSION"
}
Follow Steps 1-4 for that module
Once all modules are migrated, remove android.builtInKotlin=false and all com.android.built-in-kotlin plugins
For modules that contain no Kotlin sources , disable built-in Kotlin to save build time:
android {
enableKotlin = false
}
If blocked by plugin incompatibilities, opt out temporarily:
# 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.
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 gradle.properties and note them as temporary workarounds.
AGP 9.0 changes the defaults for many gradle properties. Check gradle.properties for any explicitly set values that may now conflict. Key changes:
| Property | Old Default | New Default | Action |
|---|---|---|---|
android.uniquePackageNames | false | true | Ensure each library has a unique namespace |
android.enableAppCompileTimeRClass | false | true | Refactor switch on R fields to |
Check for and remove properties that now cause errors:
android.r8.integratedResourceShrinking — removed, always onandroid.enableNewResourceShrinker.preciseShrinking — removed, always onFor non-KMP Android modules upgrading to AGP 9.0:
org.jetbrains.kotlin.android plugin — AGP 9.0 includes Kotlin support built-in (see "Built-in Kotlin Migration" above)com.android.legacy-kaptkotlinOptions to kotlin { compilerOptions {} }kotlin.sourceSets to android.sourceSets with .kotlin accessorBaseExtension is removed; use CommonExtension or specific extension typesAfter migration, verify with the checklist. Key checks:
./gradlew build succeeds with no errors./gradlew :androidApp:assembleDebug succeeds (if app module exists)com.android.library or com.android.application in KMP modulesorg.jetbrains.kotlin.android in AGP 9.0 modulesandroidMain, androidHostTest, androidDeviceTest)See references/KNOWN-ISSUES.md for details. Key gotchas:
AppConfiguration interface, or use BuildKonfig or gradle-buildconfig-plugin for compile-time constantscom.android.library moduleandroidResources { enable = true } (CMP-9547)consumerProguardFiles.add(file(...)) in new DSLorg.jetbrains.kotlin.android must be removed; kapt must be replacedapplicationVariants, libraryVariants, variantFilter replaced by androidComponentsswitch on R fields fails in app modules; refactor to if/elseWeekly Installs
71
Repository
GitHub Stars
214
First Seen
9 days ago
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode66
codex66
gemini-cli66
github-copilot66
amp65
cline65
Kotlin Exposed ORM 模式指南:DSL查询、DAO、事务管理与生产配置
1,100 周安装
Symfony值对象与DTOs架构优化指南:安全重构与工作流改进
190 周安装
漫画风格视频生成器 - 一键生成日式/国风/美式等8种动画视频
191 周安装
AI图像生成工具 - 支持OpenAI、Google、阿里通义万象多平台API调用
190 周安装
Feature-Sliced Design (FSD) v2.1 前端架构方法:页面优先原则与分层组织指南
189 周安装
Next.js、Turborepo、RemixIcon 全栈 Web 开发指南:构建现代高性能应用
194 周安装
微信公众号文章获取器 - 批量下载解析文章、提取元数据、图片和Markdown转换
199 周安装
| See "Pure Android Tips" below |
src/androidMainsrc/test → src/androidHostTestsrc/androidTest → src/androidDeviceTestsrc/androidMain/, no directory renames are neededMove dependencies from top-level dependencies {} into sourceSets:
kotlin {
sourceSets {
androidMain.dependencies {
implementation("androidx.appcompat:appcompat:1.7.0")
}
}
}
Enable resources explicitly if the module uses Android resources:
kotlin {
android {
androidResources { enable = true }
}
}
Enable Java compilation if module has .java source files:
kotlin {
android {
withJava()
}
}
Enable tests explicitly if the module has unit or instrumented tests:
kotlin {
android {
withHostTest { isIncludeAndroidResources = true }
withDeviceTest {
instrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
}
}
Update Compose tooling dependency :
// Old: debugImplementation(libs.androidx.compose.ui.tooling)
// New:
dependencies {
androidRuntimeClasspath(libs.androidx.compose.ui.tooling)
}
Publish consumer ProGuard rules explicitly if applicable:
kotlin { android { consumerProguardFiles.add(file("consumer-rules.pro")) } }
MainActivity.kt (and any other Activities/Fragments)AndroidManifest.xml (app-level manifest with <application> and launcher <activity>) — verify android:name on <activity> uses the fully qualified class name in its new locationAdd tosettings.gradle.kts: include(":androidApp")
Add to rootbuild.gradle.kts: plugin declarations with apply 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, versionCode, versionName
Update IDE run configurations : change the module from the old module to androidApp
shared modulewebApp (if wasmJs/js target exists):
wasmJsMain/jsMain to webApp/src/wasmJsMain/kotlin/webApp/build.gradle.ktsshared moduleiosApp directory. Verify:
binaries.framework) stays in shared modulecomposeApp to shared:
settings.gradle.kts includeandroid.newDsl=falseReview gradle.properties defaults — see "Gradle Properties Default Changes" section for properties whose defaults changed in AGP 9.0
if/elseandroid.defaults.buildfeatures.resvalues | true | false | Enable resValues = true where needed |
android.defaults.buildfeatures.shaders | true | false | Enable shaders where needed |
android.r8.optimizedResourceShrinking | false | true | Review R8 keep rules |
android.r8.strictFullModeForKeepRules | false | true | Update keep rules to be explicit |
android.proguard.failOnMissingFiles | false | true | Remove invalid ProGuard file references |
android.r8.proguardAndroidTxt.disallowed | false | true | Use proguard-android-optimize.txt only |
android.r8.globalOptionsInConsumerRules.disallowed | false | true | Remove global options from library consumer rules |
android.sourceset.disallowProvider | false | true | Use Sources API on androidComponents |
android.sdk.defaultTargetSdkToCompileSdkIfUnset | false | true | Specify targetSdk explicitly |
android.onlyEnableUnitTestForTheTestedBuildType | false | true | Only if testing non-default build types |
compileOptions reflects thisswitch statements on R class fields to if/elsetargetSdk explicitly to avoid surprisesndkVersion explicitly if using native codeandroid.builtInKotlin=false + android.newDsl=false in gradle.properties (removed in AGP 10)android {} extension helpers are obsolete