2、安装流程总览:从安装请求到应用就用的完整链路图
大家好,我是你们的老朋友。今天我们来聊聊 PackageManager 安装流程的全貌。
说实话,我刚接触 Android 源码那会儿,最头疼的就是安装流程。代码调用链太长了,从用户点击安装按钮到应用图标出现在桌面上,中间到底经历了什么?我花了整整两周才理清楚。今天我就把这张「地图」直接画给你看。
2.1 安装请求的起点
安装请求从哪里来?最常见的有三种:
- 应用商店(如 Google Play、华为应用市场)通过 Intent 调起安装
- 文件管理器点击 APK 文件触发安装
- adb install 命令行安装
不管哪种方式,最终都会走到 PackageInstaller 这个系统服务。嗯,这里要注意,Android 5.0 之后安装流程重构了,统一走 PackageInstallerSession 机制。
核心入口: PackageInstallerService 的 createSession() 方法。所有安装请求必须先创建一个 Session,然后往 Session 里写入 APK 数据。
2.2 安装流程的四大阶段
我个人习惯把安装流程拆成四个阶段,这样理解起来更清晰:
| 阶段 | 主要工作 | 关键类 |
|---|---|---|
| 阶段一:数据准备 | 拷贝 APK 文件、校验签名、解析 Manifest | PackageInstallerSession |
| 阶段二:安装执行 | 创建应用目录、优化 DEX、注册组件 | PackageManagerService |
| 阶段三:权限分配 | 授予运行时权限、更新权限状态 | PermissionManagerService |
| 阶段四:通知完成 | 发送广播、更新桌面图标、通知用户 | LauncherAppsService |
你看,是不是一下子就清晰了?每个阶段各司其职,环环相扣。
2.3 完整链路图(文字版)
我试着用文字描述一下这条链路,你跟着走一遍:
- 用户点击安装 → 系统调起
PackageInstallerActivity - 创建安装 Session →
PackageInstallerService.createSession()返回 Session ID - 写入 APK 数据 → 通过
Session.write()将 APK 流式写入/data/app/临时目录 - 提交安装 → 调用
Session.commit(),触发PackageManagerService.installStage() - 安装前校验 → 检查签名、解析
AndroidManifest.xml、验证包名冲突 - 执行安装 →
installPackageTracedLI()创建应用数据目录、安装 DEX、注册四大组件 - 权限处理 → 根据 targetSdkVersion 决定是否自动授予运行时权限
- 通知完成 → 发送
ACTION_PACKAGE_ADDED广播,Launcher 刷新桌面
小技巧: 如果你想在源码里快速定位安装流程,直接搜 installPackageTracedLI 这个方法。它是 PMS 里安装逻辑的真正入口,几乎所有安装路径最后都会汇聚到这里。
2.4 我踩过的坑
我曾经在项目里遇到一个诡异的问题:APK 安装成功后,桌面图标死活不显示。查了两天才发现,原来是 PackageManagerService 在安装完成后发送广播时,Launcher 还没注册完广播接收器。说白了就是时序问题。
后来怎么解决的?在 commit() 之后加了一个 500ms 的延迟重试机制。虽然不优雅,但确实管用。
2.5 关键数据结构
安装过程中有几个核心数据结构,我建议你记住:
PackageSetting:记录每个已安装应用的元信息,比如 uid、安装路径、权限列表InstallArgs:封装安装参数,包括 APK 路径、安装标志、用户 IDPackageParser.Package:解析后的 APK 信息,包含所有组件声明
你想想看,整个安装流程本质上就是:把 APK 文件解析成 PackageParser.Package,然后根据它创建 PackageSetting,最后注册到系统里。
2.6 流程图速览
为了让你更直观地理解,我画了一个简化的流程图(文字版):
用户点击安装
↓
PackageInstallerActivity
↓
PackageInstallerService.createSession()
↓
Session.write(APK数据)
↓
Session.commit()
↓
PackageManagerService.installStage()
↓
installPackageTracedLI()
↓
创建应用目录 /data/app/包名-xxx/
↓
解析AndroidManifest.xml
↓
优化DEX (dex2oat)
↓
注册组件到PackageManager
↓
授予权限
↓
发送ACTION_PACKAGE_ADDED广播
↓
Launcher刷新桌面 → 应用就绪
注意: 上面的流程是简化版。实际源码里还有大量异常处理、回滚机制、多用户支持等逻辑。比如安装过程中如果断电了怎么办?系统会保留 Session 状态,重启后继续安装或回滚。这部分我们后面章节会详细讲。
2.7 总结
好了,这一章我们走马观花地看了一遍安装流程的全貌。说白了就是四个字:创建 → 写入 → 提交 → 完成。
下一章我会带你深入 PackageInstallerSession 的源码,看看 APK 数据到底是怎么写入的,以及为什么 Android 要设计成 Session 机制而不是直接安装。嗯,这里面的设计思想很有意思,值得好好琢磨。
记住这张链路图,后面每一章我们都会沿着这条线往下挖。等你学完整个课程,再回头看这张图,会发现每个节点背后都是一片源码的海洋。