2、安装流程总览:从安装请求到应用就用的完整链路图

大家好,我是你们的老朋友。今天我们来聊聊 PackageManager 安装流程的全貌。

说实话,我刚接触 Android 源码那会儿,最头疼的就是安装流程。代码调用链太长了,从用户点击安装按钮到应用图标出现在桌面上,中间到底经历了什么?我花了整整两周才理清楚。今天我就把这张「地图」直接画给你看。

2.1 安装请求的起点

安装请求从哪里来?最常见的有三种:

  • 应用商店(如 Google Play、华为应用市场)通过 Intent 调起安装
  • 文件管理器点击 APK 文件触发安装
  • adb install 命令行安装

不管哪种方式,最终都会走到 PackageInstaller 这个系统服务。嗯,这里要注意,Android 5.0 之后安装流程重构了,统一走 PackageInstallerSession 机制。

核心入口: PackageInstallerServicecreateSession() 方法。所有安装请求必须先创建一个 Session,然后往 Session 里写入 APK 数据。

2.2 安装流程的四大阶段

我个人习惯把安装流程拆成四个阶段,这样理解起来更清晰:

阶段 主要工作 关键类
阶段一:数据准备 拷贝 APK 文件、校验签名、解析 Manifest PackageInstallerSession
阶段二:安装执行 创建应用目录、优化 DEX、注册组件 PackageManagerService
阶段三:权限分配 授予运行时权限、更新权限状态 PermissionManagerService
阶段四:通知完成 发送广播、更新桌面图标、通知用户 LauncherAppsService

你看,是不是一下子就清晰了?每个阶段各司其职,环环相扣。

2.3 完整链路图(文字版)

我试着用文字描述一下这条链路,你跟着走一遍:

  1. 用户点击安装 → 系统调起 PackageInstallerActivity
  2. 创建安装 SessionPackageInstallerService.createSession() 返回 Session ID
  3. 写入 APK 数据 → 通过 Session.write() 将 APK 流式写入 /data/app/ 临时目录
  4. 提交安装 → 调用 Session.commit(),触发 PackageManagerService.installStage()
  5. 安装前校验 → 检查签名、解析 AndroidManifest.xml、验证包名冲突
  6. 执行安装installPackageTracedLI() 创建应用数据目录、安装 DEX、注册四大组件
  7. 权限处理 → 根据 targetSdkVersion 决定是否自动授予运行时权限
  8. 通知完成 → 发送 ACTION_PACKAGE_ADDED 广播,Launcher 刷新桌面

小技巧: 如果你想在源码里快速定位安装流程,直接搜 installPackageTracedLI 这个方法。它是 PMS 里安装逻辑的真正入口,几乎所有安装路径最后都会汇聚到这里。

2.4 我踩过的坑

我曾经在项目里遇到一个诡异的问题:APK 安装成功后,桌面图标死活不显示。查了两天才发现,原来是 PackageManagerService 在安装完成后发送广播时,Launcher 还没注册完广播接收器。说白了就是时序问题。

后来怎么解决的?在 commit() 之后加了一个 500ms 的延迟重试机制。虽然不优雅,但确实管用。

2.5 关键数据结构

安装过程中有几个核心数据结构,我建议你记住:

  • PackageSetting:记录每个已安装应用的元信息,比如 uid、安装路径、权限列表
  • InstallArgs:封装安装参数,包括 APK 路径、安装标志、用户 ID
  • PackageParser.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 机制而不是直接安装。嗯,这里面的设计思想很有意思,值得好好琢磨。

记住这张链路图,后面每一章我们都会沿着这条线往下挖。等你学完整个课程,再回头看这张图,会发现每个节点背后都是一片源码的海洋。