Google Play 强制要求 targetSdk 35,适配成本盘点
Google Play 强制要求 targetSdk 35,适配成本盘点
上个月底打开 Play Console,后台直接弹了一条黄色警告,说现有应用如果不在限定日期前把 targetSdkVersion 抬到 35,后续更新提交会被直接打回。我盯着那条通知看了几秒,脑子里先冒出来的不是技术方案,而是一个挺荒诞的画面:Android 15 正式版是 2024 年 9 月才全面推送的,Google 这边已经急不可耐地要把刀架在所有开发者的脖子上,逼着整个生态在几个月内完成一次全量迁移。这节奏,苹果看了都自愧不如。
不是"升级建议",是"拒审通知书"
先给还没收到弹窗的同学提个醒。Google Play 对 targetSdk 的强制策略这些年已经套路化了:每年一个大版本,新应用先砍,老应用更新随后跟上,缓冲期越来越短。targetSdk 35 对应的是 Android 15,按官方时间表,新应用和现有应用的更新都已经被划了死线。这意味着你不能再像前几年那样,把 targetSdk 33 或 34 的包打 patch 去交差。Play 商店的审核机器人现在第一件事就是扫 AndroidManifest.xml 里的 targetSdkVersion,数字不对,连人工审核的机会都不给。
表面看,Google 的理由永远是那套"保障用户隐私和安全"的说辞。Android 15 确实带进了一堆行为变更,有些甚至改到了系统底层。但问题在于,这些变更的落地成本,被完全转嫁给了应用层开发者。Google 每年发几篇迁移指南,开几场 I/O 讲座,把 Breaking Changes 列成清单,好像只要照着勾选就能平滑过渡。真去干过这事的人都知道,那几张清单背后是多少个通宵和返工。
Edge-to-Edge:全屏显示成了默认项,老项目直接裂开
如果让我只选一个最恶心的变动,那绝对是 Android 15 里针对 targetSdk 35+ 应用的 Edge-to-Edge 强制全屏。从这一代开始,只要你 target 到 35,系统默认认为你的应用要接管整个屏幕,状态栏和导航栏会稳稳地盖在你的内容上面。以前那种系统帮你自动留好状态栏高度的时代,一去不复返了。
很多后端的、做 SDK 的同学可能还没意识到这事的杀伤力。对 UI 层来说,这等于在宣布:所有老旧的 XML 布局,所有写死的 fitsSystemWindows="true",所有靠 SYSTEM_UI_FLAG_LIGHT_STATUS_BAR 这种已经 deprecated 的 flag 撑起来的沉浸式逻辑,全部要重写。尤其是那些从 Android 5 或 6 时代一路迭代过来的项目,布局文件可能有几千个,Activity 和 Fragment 里还散落着各种手动计算 statusBarHeight 的魔法数字。你现在要全部迁移到 WindowInsetsCompat 体系里,用 Type.statusBars() 和 Type.navigationBars() 去动态处理内边距。
更阴间的是,Google 在文档里轻飘飘地写了一句:"如果您的应用已经适配了 edge-to-edge,则无需额外工作。" 这话纯属废话。国内多少应用真正完全适配了 edge-to-edge?大多数团队之前都是"能跑就行",状态栏颜色靠 android:statusBarColor 在 theme 里写死,内容区域老老实实躲在系统栏下面。现在可好,Android 15 一强制,你的 Toolbar 会直接被状态栏文字盖住,底部 TabBar 会被手势导航条遮住一半。而且不同厂商的刘海屏、挖孔屏、折叠屏的 WindowInsets 表现还不一样,小米、三星、Pixel 各自的 insets 分发机制有细微差异,你处理不好就是一个机型一个 bug。
Jetpack 虽然提供了 WindowInsetsCompat,但那玩意儿在 Fragment 嵌套、ViewPager2 切换、BottomSheetDialog 弹出的场景下,行为极其诡异。很多团队最后不得不自己写一个全局的 OnApplyWindowInsetsListener,递归遍历 ViewTree 去自动 padding,这中间的坑能再写一篇文章。一个成熟应用要完整跑通 edge-to-edge 适配,从方案设计、UI 回归测试到线上灰度,没有一个月根本下不来。而 Google 给的这个 deadline,根本没留这么多时间。
16KB Page Size:Native 层的雷,埋得比想象中深
如果说 Edge-to-Edge 是 UI 同学的噩梦,那 16KB Page Size 就是 Native 开发者和音视频团队的索命符。Android 15 开始支持 16KB 内存页面大小,虽然看上去是"支持"而非"强制",但 Google Play 已经放话了:从 2025 年 8 月 31 日起,提交到 Play 商店的新应用和更新,所有原生库(.so 文件)必须兼容 16KB 页面。
这什么意思?过去 Android 设备的内存页大小是 4KB,这是个业界默认了十几年的假设。大量的 C/C++ 代码、第三方 so 库、游戏引擎底层,都默认了 PAGE_SIZE 等于 4096。有些代码做内存对齐、地址计算、mmap 分配的时候,直接把 4KB 硬编码进去,或者依赖 ELF 文件的加载地址按 4KB 对齐。现在一旦跑在 16KB page size 的设备上,这些假设全部失效,轻则性能暴跌,重则直接 segfault 崩溃。
更坑的是,这个改动不是改几行 Java/Kotlin 代码能解决的。你项目里引用的每一个 Native 库,不管是 ffmpeg、OpenCV、某家广告 SDK 的 so、还是友盟/Firebase 的底层库,全都要重新编译,而且要确保编译链里加了对齐参数。Android NDK r28 开始默认支持 16KB ELF 对齐,但老版本的 NDK 不行。很多老项目为了稳定性,NDK 版本锁在 r21 或 r23,现在等于要连带着升级整个构建工具链。
很多中小团队自己并不维护 so 库,依赖的是第三方厂商。问题是,市面上大量的 SDK 提供商动作慢得要死,尤其是国内的某些推送 SDK、统计 SDK、安全加固 SDK,你问他们的客服"什么时候出 16KB 兼容版本",对方可能连你在问什么都没听懂。最后就卡在这里:Play 商店 deadline 到了,你有一个 so 库没准备好,整个应用就发不了版。这种被上下游卡脖子的感觉,做过出海的同学应该都懂。
前台服务与后台启动:业务逻辑面临重写
Android 14 已经对前台服务(Foreground Service)砍了一刀,要求必须在 manifest 里声明 android:foregroundServiceType,而且每种类型都要申请对应的权限。Android 15 在这个基础上继续收紧,比如针对 BOOT_COMPLETED 启动前台服务做了更严格的限制,后台应用启动 Activity 的门槛也越来越高。
对于那些依赖保活、定时任务、后台唤醒的业务来说,这几乎是灭顶之灾。很多工具类应用、运动健康类应用、还有那种需要长时间后台录音或定位的专业软件,它们的业务核心就是要在后台跑一个 FGS。以前靠 startForeground 就能搞定的事情,现在你要先检查是不是满足系统定义的"合理场景",还要处理用户手动杀掉进程后系统不再允许自启动的情况。
Google 现在推崇的是 WorkManager 加精确闹钟(Exact Alarms)那套方案,但 WorkManager 的延迟和系统调度策略根本替代不了真正的后台服务。很多开发者被逼着把核心业务逻辑改得七零八落,最后用户体验反而变差——比如以前能实时同步的数据,现在因为后台限制只能定时拉取,结果用户打开应用看到一片空白,还以为是 bug。
还有那个 SCHEDULE_EXACT_ALARM 权限,Android 14 开始变成普通权限里的特殊权限,用户得手动去设置里开。targetSdk 35 之后,这个限制更死。做闹钟、日历、提醒类应用的团队,光是处理这个权限的引导流程和降级方案,就要多写几百行代码。关键是,这些代码不是为了提升用户体验写的,纯粹是为了过审。
国内出海的双轨制:同一个包,两套生存逻辑
最让中国开发者血压飙升的,是 Google Play 和国内应用商店的割裂。Google 这边 targetSdk 35 的刀已经落下了,但回头看看华为应用市场、小米应用商店、OPPO/vivo 的渠道,很多还停留在 targetSdk 30 或 33 的要求上,而且审核尺度完全另一套标准。
这就导致一个极其荒诞的局面:同一套