targetSdkVersion — 应用经过测试和优化的 Android API 级别。此参数在 build.gradle 中指定,并确定哪些 behavioural changes(系统行为更改)将在运行时应用于应用。如果 targetSdkVersion 低于设备的 API 级别,Android 将禁用较新版本中引入的 behavioural changes,从而为旧应用保持兼容性。根据 Android Developers,Google Play 要求 targetSdkVersion 不得早于当前 API 级别 1 年以上。
要点
targetSdkVersion — build.gradle 中的一个整数参数,声明应用经过测试的 API 级别。Android 系统使用此参数来决定在运行期间将哪些 behavioural changes 应用于应用。如果 targetSdkVersion = 33,Android 应用包括 API 33 及之前引入的所有 behavioural changes,但不应用 API 34+ 的更改。如果 targetSdkVersion = 34 — 应用 API 34 之前的更改,以此类推。
targetSdkVersion 与 minSdkVersion 的关键区别 — 作用机制。minSdk 在安装时检查一次,如果条件不满足则阻止安装。targetSdkVersion 影响每个设备上系统的运行时行为,无论应用运行在哪个 Android 版本上。具有 targetSdk 31 的同一应用在 Android 13、14 和 15 上将表现不同,因为 31 以上的 behavioural changes 被禁用。
targetSdkVersion 机制 — 是内置于 Android 中的向后兼容工具。没有它,每次操作系统更新都会破坏数千个旧应用。Google 在 Android 2.1(API Level 7)中引入了此机制,从此将其作为引入新安全、隐私和资源管理规则的标准方式,而不干扰现有应用的运行。
// build.gradle.kts — defaultConfig 中的 targetSdkVersion
android {
namespace = "com.example.myapp"
compileSdk = 36
defaultConfig {
applicationId = "com.example.myapp"
minSdk = 26
targetSdk = 36 // 在 Android 16 上测试
versionCode = 1
versionName = "1.0.0"
}
}
// 在代码中检查当前 targetSdk
fun isUsingScopedStorage(): Boolean {
// Context.getApplicationInfo().targetSdkVersion 包含应用的 targetSdk
return context.applicationInfo.targetSdkVersion >= VERSION_CODES.Q
}在示例中,targetSdk = 36 启用 Android 16 的所有 behavioural changes。代码通过 context.applicationInfo.targetSdkVersion 检查 targetSdkVersion — 这允许动态确定启用了哪种兼容模式。辅助函数对于必须适应调用应用 targetSdk 的库很有用。
Behavioural changes — 是仅适用于 targetSdkVersion >= 特定 API 级别的应用的 Android 系统行为修改。每个新的 Android 主要版本都会引入 behavioural changes,如果应用不更新 targetSdk,这些更改不会生效。这种机制允许开发人员按照自己的节奏更新应用,而不是与操作系统新版本的发布同步。
Scoped Storage(API 29) — 最重要的 behavioural changes 之一。targetSdk 29+ 的应用无法直接 File 访问公共目录 Pictures、Downloads、Music、Documents。而是使用 MediaStore 处理多媒体,使用 SAF(Storage Access Framework)处理任意文件,使用 getExternalFilesDir() 处理自己的存储。targetSdk 28 及以下的旧应用继续使用旧的 Full Storage Access,但这会带来安全威胁。
POST_NOTIFICATIONS(API 33) — 发送通知的运行时权限。targetSdk 33+ 的应用必须通过标准对话框向用户请求 Manifest.permission.POST_NOTIFICATIONS 权限。如果未授予权限,NotificationManager.silent() 不会向用户显示通知。在 Android 13+ 上,如果没有此权限,推送通知和本地通知根本不会显示,这可能会显著降低用户参与度。
| API 级别 | Behavioural Change | 更新时所需操作 |
|---|---|---|
| 29 | Scoped Storage | 迁移到 MediaStore 和 SAF 以处理沙箱外的文件 |
| 30 | Package Visibility | 在清单中添加 <queries> 以与包交互 |
| 31 | Foreground Service Notification | 服务启动后 10 秒内显示通知 |
| 33 | POST_NOTIFICATIONS | 运行时请求发送通知的权限 |
| 34 | Foreground Service Types | 在清单中声明前台服务类型 |
| 35 | Privacy Sandbox | 限制广告标识符(Advertising ID) |
应用的 targetSdkVersion 值可以通过 ADB 获取:命令 adb shell dumpsys package com.example.myapp | grep targetSdk 显示 targetSdk=34。在代码中,context.getApplicationInfo().targetSdkVersion 返回一个整数。对于分析,记录 targetSdk 以及 android.os.Build.VERSION.SDK_INT 很有用,以了解每个会话中哪些 behavioural changes 实际处于活动状态。
Google Play 对所有发布的应用设置了 targetSdkVersion 的强制要求。自 2024 年 8 月起,最低 targetSdk = 33(Android 13)。自 2025 年 8 月起 — targetSdk = 34。预计自 2026 年 8 月起,Google 将要求 targetSdk = 35(Android 15)。新应用和现有应用的更新必须满足这些要求,否则控制台将阻止发布。这是 Google Play 政策,而非 Android Runtime 限制:targetSdk 为 34 的应用可以在 Android 16 上运行,但不能在 Play Store 中发布。
Android App Bundle(AAB) — 自 2021 年 8 月起强制要求的发布格式。Google Play 不再接受 APK(例外 — 大小 > 150 MB 的应用和一些遗留项目)。AAB 格式允许 Google 为每个 API 级别和屏幕密度生成优化的 APK,从而将下载大小减少 15-30%。为检查 targetSdk,Google Play 分析 AAB 清单,如果不符合要求,则会显示错误,指出最低要求值。
| 期间 | 最低 targetSdk | Android 版本 | 备注 |
|---|---|---|---|
| 2024 年 8 月 | 33 | Android 13 | Tiramisu — 强制 POST_NOTIFICATIONS |
| 2025 年 8 月 | 34 | Android 14 | Upside Down Cake — 前台服务类型 |
| 2026 年 8 月 | 35 | Android 15 | Vanilla Ice Cream — Privacy Sandbox |
| 2027 年 8 月(计划) | 36 | Android 16 | Baklava — T+ |
Google Play Console 不仅在上传新 AAB 时检查 targetSdkVersion,在更新现有应用时也会检查。如果您的应用 targetSdk 为 33,而 Google 将最低门槛提高到 34 — 在您提高 targetSdk 之前,您将无法发布任何更新。对于长时间未更新的应用,Google Play 可能会自动将其从发布中移除(unpublish)。
更新 targetSdkVersion — 不仅仅是更改 build.gradle 中的数字。如果代码没有提前准备,每个 behavioural change 都可能破坏现有功能。建议在 Google Play 截止日期前 3-6 个月开始准备,特别是如果应用很大且使用许多系统 API 时。
逐步过程:第 1 步 — 在 Android Developers 文档(页面 "Behavioural Changes by API Level")中研究新 API 级别的 behavioural changes。第 2 步 — 创建 targetSdk-update 分支并将 targetSdk 更改为新值。第 3 步 — 在具有新 API 级别的模拟器或设备上运行应用,并检查与更改相关的每个功能。第 4 步 — 修复错误:添加权限,更改文件操作方式,更新清单。
第 5 步 — 在旧设备上测试。提高 targetSdk 不会影响 API 级别低于新 targetSdk 的设备,但 behavioural changes 会应用于所有 API Level >= targetSdk 的设备。如果您将 targetSdk 从 33 提高到 34,在 API 34+ 的设备上,API 34 的 behavioural changes 将启用。在 API 33 的设备上,什么都不会改变。
// 为 targetSdk 35 做准备:Privacy Sandbox
import android.os.Build
import android.os.Build.VERSION_CODES
import com.google.android.gms.ads.identifier.AdvertisingIdClient
class AdsManager {
fun getAdvertisingId(context: android.content.Context): String? {
// Privacy Sandbox 从 API 35 开始限制 Advertising ID
if (Build.VERSION.SDK_INT >= VERSION_CODES.VANILLA_ICE_CREAM) {
// API 35+ — 标识符不可用,使用 MeasurementManager
return null
}
return try {
val adInfo = AdvertisingIdClient.getAdvertisingIdInfo(context)
adInfo.getId()
} catch (e: Exception) {
null
}
}
// 检查:哪些 behavioural changes 处于活动状态
fun getActiveChanges(context: android.content.Context): List<String> {
val sdkInt = Build.VERSION.SDK_INT
val targetSdk = context.applicationInfo.targetSdkVersion
return buildList {
if (sdkInt >= VERSION_CODES.Q && targetSdk >= VERSION_CODES.Q)
add("ScopedStorage")
if (sdkInt >= VERSION_CODES.TIRAMISU && targetSdk >= VERSION_CODES.TIRAMISU)
add("PostNotifications")
if (sdkInt >= VERSION_CODES.UPSIDE_DOWN_CAKE && targetSdk >= VERSION_CODES.UPSIDE_DOWN_CAKE)
add("FgsTypes")
}
}
}AdsManager 类展示了为 Privacy Sandbox(API 35)做的准备。Advertising ID 从 API 35 开始(targetSdk 35+)不再可用。getActiveChanges 函数演示了检查 behavioural changes 的正确模式:需要同时检查设备的 SDK_INT 和应用的 targetSdk。只有两个条件都满足时,更改才真正生效。
Android 15(API 35,Vanilla Ice Cream)引入了几个关键的 behavioural changes,开发人员在将 targetSdk 更新到 35 时必须考虑这些变化。第一个 — Privacy Sandbox for Android。这是 Google 用更私密的 API 取代 Advertising ID 的举措:Topics API(用户兴趣)、Protected Audience(再营销)和 Attribution Reporting(转化)。从 API 35 开始,Advertising ID 不再是稳定的标识符,可能返回零值。
第二个更改 — Foreground Service Types(API 34,在 API 35 中继续)。从 API 34 开始,每个 targetSdk 34+ 的应用必须在清单中指定前台服务类型:dataSync、systemExempted、shortService、location、mediaPlayback 等。否则系统会生成 ForegroundServiceTypeNotAllowedException。在 API 35 中,添加了新的 health 类型,并加强了对现有类型的检查。所有前台服务都必须重新审查。
第三个更改 — SCHEDULE_EXACT_ALARM 限制。从 API 35 开始,targetSdk 35+ 的应用未经用户明确许可不能使用 SCHEDULE_EXACT_ALARM。系统显示对话框,用户必须批准精确调度。对于闹钟和定时器,这意味着用户体验中的额外步骤。替代方案 — 使用具有 10 分钟余量的非精确闹钟。
// Android 15(API 35):检查 SCHEDULE_EXACT_ALARM
import android.app.AlarmManager
import android.os.Build
import android.provider.Settings
class AlarmScheduler {
fun canScheduleExactAlarms(context: android.content.Context): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
// API 35+:需要用户权限
val alarmManager = context.getSystemService(
android.content.Context.ALARM_SERVICE
) as AlarmManager
return alarmManager.canScheduleExactAlarms()
}
// 低于 API 35 — 精确闹钟无需权限即可使用
return true
}
fun requestExactAlarmPermission(activity: android.app.Activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
val intent = android.content.Intent(
Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM
).apply {
data = android.net.Uri.fromParts(
"package", activity.packageName, null
)
}
activity.startActivity(intent)
}
}
}Privacy Sandbox 和闹钟限制 — API 35 的两个最关键的 behavioural changes。对于广告 SDK,需要迁移到 Topics API 和 Attribution Reporting。对于具有闹钟和提醒的应用 — 在权限对话框下的用户体验适配。忽略这些更改将导致应用在 Android 15 上运行时崩溃或广告变现无法工作。
targetSdkVersion 和 compileSdkVersion 的区别 — Android 开发人员中最常见的混淆话题之一。compileSdkVersion — 是编译代码所针对的 SDK 版本。它确定编译期间哪些 API 可用,但不影响运行时行为。targetSdkVersion — 是应用经过测试的版本,它确定哪些 behavioural changes 在运行时应用。compileSdk 可以而且应该高于或等于 targetSdk。
规则很简单:compileSdk >= targetSdk >= minSdk。compileSdk 通常等于最新的稳定 API 级别(2026 年为 36)。targetSdk 应该在经过测试的版本中尽可能高。minSdk 应该尽可能低以最大化覆盖范围。提高 compileSdk 不需要测试 behavioural changes — 它只是为编译器打开对新 API 的访问。提高 targetSdk 需要所有 behavioural changes 的完整测试周期。
| 参数 | 作用时刻 | 影响 | 可以高于其他 |
|---|---|---|---|
| compileSdkVersion | 编译 | API 对代码的可用性 | 是,始终高于 targetSdk |
| targetSdkVersion | 运行时 | Behavioural changes | 是,但低于 compileSdk |
| minSdkVersion | 安装 | 设备兼容性 | 否,始终最低 |
实践中:如果您想使用 Android 16(API 36)的新 API,但尚未测试 API 36 的 behavioural changes,请设置 compileSdk = 36、targetSdk = 35。代码将使用新 API 编译,但 API 36 的 behavioural changes 不会应用。一旦您测试了所有更改 — 将 targetSdk 提高到 36。
常见问题
targetSdkVersion — 应用经过测试的 API 级别。Android 用它来应用 behavioural changes — 此版本中引入的行为更改。如果 targetSdk 低于设备的 API 级别,则不会应用 behavioural changes。Google Play 要求 targetSdk 不得早于当前 API 级别 1 年以上,用于发布新版本和更新。
targetSdkVersion 影响运行时行为:激活特定 API 级别的 behavioural changes。compileSdkVersion 只影响编译:确定编译器可用哪些 API。compileSdk 可以高于 targetSdk,但反之则不行。提高 compileSdk 不需要测试,提高 targetSdk 需要检查所有 behavioural changes。
Android 15(API 35)引入了关键的 behavioural changes:限制 Advertising ID 的 Privacy Sandbox、强制声明的 Foreground Service Types、带权限对话框的 SCHEDULE_EXACT_ALARM 限制、更严格的 Scoped Storage 以及自动切换到无凭证身份验证。targetSdk 35+ 的应用必须完成 API 35 下的完整测试周期。
如果您不更新 targetSdkVersion,Google Play 将阻止应用新版本的发布。Google 每年都会提高最低 targetSdk:自 2025 年 8 月起 — targetSdk 34+,自 2026 年 8 月起预计 targetSdk 35+。不满足要求的应用将从商店中移除。此外,安全 behavioural changes 不会应用,使应用易受攻击。
通过 ADB 检查 targetSdkVersion:adb shell dumpsys package com.example.myapp | grep targetSdk。在 Android Studio 中打开 APK Analyzer:Build → Analyze APK → AndroidManifest.xml → uses-sdk。在代码中:context.applicationInfo.targetSdkVersion。在 Google Play Console 中,targetSdk 显示在应用发布页面的 Artifact Details 部分。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。