Gradle 8.0+中minSdk和targetSdk必须置于android块顶层并用{ version = N }闭包形式声明,写在defaultConfig内将被忽略导致APK manifest值错误;需配合clean构建并验证权限、服务、存储等系统行为变更。

直接在模块级 build.gradle(通常是 app/build.gradle)里写 minSdk 和 targetSdk 就行,但必须放在 android { } 块顶层,不能塞进 defaultConfig 里——这是 Gradle 8.0+ 的新写法,老写法会报错或被忽略。
Gradle 8.0+ 正确写法:minSdk 和 targetSdk 必须在 android 块顶层
从 Gradle 8.0 开始,minSdk 和 targetSdk 已从 defaultConfig 移出,变成 android 块的直接子属性。如果你还写在 defaultConfig 里,构建会成功但实际不生效,APK 的 manifest 里仍沿用旧值或默认值(比如 minSdkVersion=1),上线后可能被 Google Play 拒绝。
正确示例:
android {
namespace 'com.example.app'
compileSdk 36
minSdk { version = 23 }
targetSdk { version = 36 }
defaultConfig {
applicationId "com.example.app"
versionCode 1
versionName "1.0"
}
}
-
minSdk和targetSdk是闭包,必须用{ version = N }形式,不能写成minSdk 23(那是旧语法,已废弃) - 数值必须是整数,不能是字符串或变量引用(除非该变量已在
gradle.properties中定义并正确注入) - 如果项目启用了
settings.gradle中的版本集中管理(如libs.versions.toml),则这里应留空,否则会覆盖全局配置
为什么不能写在 defaultConfig 里?
因为 Gradle 构建流程中,minSdk 和 targetSdk 的解析发生在 android 块初始化阶段,早于 defaultConfig 合并。写在 defaultConfig 里会被完全跳过,Android Gradle Plugin(AGP)日志里会出现类似 WARNING: Ignoring minSdkVersion set in defaultConfig 的提示,但不会中断构建,容易被忽略。
常见错误现象:
- 明明改了
defaultConfig.minSdkVersion 23,但生成的 APK 的AndroidManifest.xml里仍是minSdkVersion="1" - Google Play Console 提示 “Your app’s targetSdkVersion is lower than required”,即使你确认改过值
- 运行时调用
Build.VERSION.SDK_INT >= Build.VERSION_CODES.P判断失败,实际设备是 Android 9+,但应用因targetSdk未生效而进入兼容模式
和 gradle.properties 配合时的坑
如果你习惯用 gradle.properties 管理版本号(比如 minSdkVersion=23),在 build.gradle 中引用时必须用 ${} 且确保类型匹配:
// gradle.properties minSdkVersion=23 targetSdkVersion=36
// build.gradle
minSdk { version = Integer.parseInt(project.findProperty("minSdkVersion") ?: "21") }
targetSdk { version = Integer.parseInt(project.findProperty("targetSdkVersion") ?: "36") }
- 直接写
version = minSdkVersion会报错:Groovy 把它当字符串处理,而version要求是Integer -
project.findProperty()返回的是String或null,必须显式转Integer,否则构建失败 - 没设默认值(如
?: "21")会导致 CI 环境缺失 property 时构建中断
targetSdk 改动后必须验证的三件事
targetSdk 不只是个数字,它会触发系统级行为变更。升级后务必检查:
- 权限弹窗逻辑:Android 11+ 对
MANAGE_EXTERNAL_STORAGE的限制、Android 12+ 的模糊定位开关是否正常出现 - 后台服务启动:targetSdk ≥ 26 后,
startService()在后台被禁止,需改用startForegroundService() - 存储访问:targetSdk ≥ 30 启用分区存储(Scoped Storage),
getExternalStorageDirectory()返回路径不可写,必须用getExternalFilesDir()或申请MANAGE_EXTERNAL_STORAGE
最容易被忽略的是:改完 targetSdk 后没清缓存就直接运行,Android Studio 可能复用旧的 AAPT2 缓存,导致 manifest 未更新。务必执行 ./gradlew clean 再构建。











