28. 与 Android 新版本演进:PMS 在 Android 12/13/14 中的关键变化
Android 系统每一年一个大版本,PMS 作为核心组件,改动量一直不小。我这些年跟进下来,感觉 Google 在 12、13、14 这三个版本里,对 PMS 的改造思路非常清晰——说白了就是三个关键词:性能、隐私、模块化。今天咱们就逐个版本捋一捋,看看哪些变化真正影响了我们的日常开发。
Android 12:增量更新与前台服务限制
Android 12 是我个人觉得 PMS 改动最「伤筋动骨」的一个版本。为什么这么说?因为 Google 终于对安装流程下了狠手。
增量包安装机制
以前安装大 APK,尤其是游戏,动辄几百 MB,用户等得心焦。Android 12 引入了 增量包(Incremental) 安装机制。它的核心思路是:边下载边安装,而不是等下载完再解压。
我记得第一次看增量包的代码时,差点被绕晕。简单来说,PMS 会把 APK 拆成多个「块」(chunk),下载完一部分就立即验证并写入。用户甚至可以在下载到 30% 时就直接打开应用——当然,只能用到已下载的功能。
关键变化点:
- 新增
IncrementalService系统服务 - PMS 需要管理增量包的安装状态机
- 对存储 I/O 的调度策略做了大幅调整
前台服务启动限制
这个改动跟 PMS 的关系其实挺微妙。Android 12 禁止后台应用通过 startForegroundService() 启动前台服务,除非应用有 FOREGROUND_SERVICE 权限。PMS 在安装时就需要检查目标 SDK 版本,并决定是否授予该权限。
嗯,这里要注意:如果你的应用 targetSdkVersion 低于 31,系统会帮你自动兼容。但一旦升到 31,PMS 就会严格检查。我有个项目就是因为没注意这个,升级后前台服务全挂了,排查了半天才发现是 PMS 在安装阶段就把权限给卡住了。
Android 13:细粒度媒体权限与通知运行时权限
Android 13 的 PMS 改动,我个人觉得是「润物细无声」——表面上看变化不大,但底层逻辑变了。
细粒度媒体权限
以前 READ_EXTERNAL_STORAGE 一把梭,现在拆成了三个:
| 权限名 | 访问范围 |
|---|---|
READ_MEDIA_IMAGES |
仅图片 |
READ_MEDIA_VIDEO |
仅视频 |
READ_MEDIA_AUDIO |
仅音频 |
PMS 在安装时需要解析应用的 uses-permission 声明,并自动做权限映射。比如你声明了 READ_EXTERNAL_STORAGE,PMS 会帮你自动转换成这三个细粒度权限——但前提是你的 targetSdkVersion 是 33 及以上。
避坑指南:我曾经遇到一个 case,应用只声明了 READ_EXTERNAL_STORAGE,targetSdkVersion 是 32。在 Android 13 上安装后,PMS 没有做自动映射,导致应用完全读不到媒体文件。解决方案很简单:要么升 targetSdkVersion,要么在清单里显式声明三个新权限。
通知运行时权限
这个改动影响面很大。Android 13 把 POST_NOTIFICATIONS 变成了运行时权限。PMS 在安装时需要判断:
- 如果应用 targetSdkVersion >= 33,安装后默认不授予通知权限
- 如果应用 targetSdkVersion < 33,系统自动授予
你想想看,这意味着什么?以前安装完就能弹通知,现在必须等用户手动同意。PMS 在 PackageManagerService.java 里新增了 grantDefaultPermissions 的逻辑分支,专门处理这个兼容性问题。
Android 14:后台活动启动限制与更严格的广播限制
Android 14 的 PMS 改动,我个人觉得是最「激进」的。Google 终于对后台启动 Activity 和隐式广播下了死手。
后台活动启动限制
从 Android 14 开始,应用在后台时不能随意启动 Activity。PMS 在 startActivity 的调用链中新增了检查点:
// 伪代码示意
if (callerUid != Process.SYSTEM_UID
&& !app.isForeground()
&& !hasWindowFocus()) {
throw new BackgroundActivityStartException();
}
这个改动对 PMS 的影响在于:安装流程本身也会触发 Activity 启动。比如安装完成后跳转到应用详情页,或者安装器弹出确认对话框。PMS 需要确保这些启动行为不被误杀。
警告:如果你的应用在安装后需要立即启动 Activity(比如引导页),必须使用 PendingIntent 或者通过系统服务代理。直接调用 startActivity 在 Android 14 上会直接崩溃。我有个同事就因为没注意这个,上线后 crash 率飙升了 30%。
更严格的隐式广播限制
Android 14 进一步收紧了隐式广播的发送范围。PMS 在注册广播接收器时,会检查:
- 如果
exported为 true,必须指定package或permission - 如果
exported为 false,只能接收来自同一 UID 的广播
说白了,Google 就是逼着开发者用显式广播。PMS 在 registerReceiver 的流程里新增了 validateBroadcastReceiver 方法,不满足条件的直接拒绝注册。
核心变化对比
为了方便你快速回顾,我整理了一张对比表:
| 版本 | PMS 关键变化 | 影响范围 |
|---|---|---|
| Android 12 | 增量包安装、前台服务限制 | 安装流程、权限管理 |
| Android 13 | 细粒度媒体权限、通知运行时权限 | 权限映射、兼容性处理 |
| Android 14 | 后台活动启动限制、隐式广播收紧 | Activity 启动、广播注册 |
知识体系图
下面这张 SVG 图展示了 PMS 在三个版本中的核心变化脉络:
我的建议
如果你正在维护一个需要兼容多个 Android 版本的应用,我建议你重点关注以下几点:
- 安装流程:Android 12 以上的增量包机制,可能会影响你的安装器实现
- 权限声明:Android 13 的细粒度权限,需要在清单中做显式声明
- 后台行为:Android 14 的后台启动限制,需要重构 Activity 启动逻辑
嗯,说到底,PMS 的演进方向就是让系统更安全、更可控。我们作为开发者,只能跟着 Google 的节奏走。不过换个角度想,这些限制其实也在帮我们写出更规范的应用——至少 crash 的时候,你知道该去查 PMS 的哪个模块了。
一句话总结:Android 12 改安装,Android 13 改权限,Android 14 改行为。PMS 越来越像个「系统警察」了。