likes
comments
collection
share

二十二、App的安装过程全解

作者站长头像
站长
· 阅读数 4

概述

前面几篇,通过分析View的绘制过程以及Activity的启动过程,了解了 Android系统中两个比较重要的系统服务 ActivityManagerServiceWindowManagerService,简称 AMSWMS

本文将详解负责App安装的另一个重要服务 PackageManagerService

本文涉及的代码都基于android-28

apk的打包过程

二十二、App的安装过程全解

一个完整的安卓项目是由多个module构成,每个module中的内容大致可以分为两大类

  • Resources 资源
  • java/kotlin 代码

所以打包过程也基本上围绕这两个部分。

资源部分

资源文件包含 res目录下的 各种XML文件,动画,drawable ,音视频等。

负责打包资源文件的工具叫做 AAPT,它是安卓SDK的一个部分。

XML文件会被编译成二进制。

drawable 和 mipmap 中的 JPG ,PNG 等 图片会保留。这也是我们可以解压别人的apk,取得其中图片资源的原因。

assets 和 raw 中的文件会保留原样,打包到apk内部。

我们最需要关注的是,XML文件中的各种 资源ID 和 它对应的资源 的配对关系。比如,color,string,layout,他们都通过以下两个文件进行管理:

  • resource.arsc 文件 (资源索引表)
  • R.java 文件

比如这个R.java文件 二十二、App的安装过程全解 其中记录了很多资源ID,应用程序运行时,系统会通过这些id,去 resource.arsc 资源索引表中去查找对应的资源来加载。

代码部分

源代码文件会先通过javac编译成 .class文件,然后这些class,会连同第三方库中的class,一同被 dx命令打包成dex文件,如果有分包,那么也有可能生成多个dex。 源代码部分也包含 AIDL 生成的 java文件,AIDL会先生成java文件然后生成class,最后一同进入到 dex

打包阶段

当 资源和代码都被打包好了之后,APK Builder 会将经过编译的 resource.arsc 和 dex一起打包到 apk中。

除了代码和资源之外,还有清单文件 AndroidManifest.xml 和 第三方库中使用的so文件。

apk文件创建好了之后,还要使用签名工具 jarsigner 对其进行签名。

签名之后,会生成MEAT_INF目录,其中包含了 签名相关的各个文件。(这里只针对了v1签名,v2,v3签名是对整个apk字节码进行签名,所以没有明显产物)

MEAT_INF 中内容如下:

  • CERT.SF 每个文件的相对密钥
  • MANIFEST.MF 每个文件的数字签名信息
  • XXX.SF JAR文件的签名文件
  • XXX.RSA 对输出文件的签名和公钥

实际的打包后可能还有一个优化阶段,那就是使用 apk对齐工具,对未压缩的图片视频等资源进行对齐操作。

让资源按照4个字节的边界进行对齐,可以加快 资源的访问速度。

如果每个资源的开始位置都是上个资源之后的4n个字节,那么访问下一个资源就不用遍历,直接跳到4n字节处判断是不是新的资源即可。

到这里,一个完整的apk就打包完毕。

完整内容如下:

二十二、App的安装过程全解

apk的安装过程

当我们在安卓系统上发起某个apk的安装流程时,首先会先看到一个系统的应用安装界面。 这个界面其实是,AndroidFramework层的 PackageInstallerActivity.java

点击安装之后,PackageInstallerActivity 会先把所安装的apk信息 通过 PackageInstallerSession 交给 PackageManagerService 处理。源代码如下所示,mPm就是 PackageManagerService的实例 :

二十二、App的安装过程全解

整个安装过程分为两个步骤:

  • 拷贝安装包
  • 装载代码

拷贝安装包

下面将追踪 PackageManagerService 的 源代码来分析 拷贝过程。

二十二、App的安装过程全解

图中1处,创建了一个Handler体系中的 Message 并指定了INIT_COPY这个行为,

图中2处,用安装包的相关数据构建了一个 InstallParams.

最后通过 mHandler将 消息发送出去。

消息的执行如下:

二十二、App的安装过程全解 图中1处,获取了刚才构建的 InstallParams

图中2处,尝试连接安装apk的Service服务。

二十二、App的安装过程全解 实际绑定的Servic就是上图中的DEFAULT_CONTAINER_COMPNENT,

当绑定成功之后,将通过handler发送一个MCS_BOUND消息,

二十二、App的安装过程全解

消息的执行如下: 其中,从 mPnedingInstalls这个等待队列中取出刚才创建的 InstallParams 对象,并且一旦这个InstallParams开始拷贝,就从等待队列中移除它。 二十二、App的安装过程全解

startCopy的源码如下,这是apk拷贝的核心方法:

二十二、App的安装过程全解

图中1处,决定 安装的位置,是在手机内部存储空间,还是外部存储SD卡。

图中2处,判断apk安装位置,如果安装位置合法,则执行3处逻辑。

图中3处,创建出一个 InstallArgs,并执行它的copyApk方法。实际执行的代码在 FileInstallArgs 中。 并实际执行到了 doCopyApk。 二十二、App的安装过程全解 doCopyApk 主要做了3件事。

1处,创建存储apk的目标路径。实际上是 data/app/[包名]/ 这个目录 2处,将原始文件拷贝到目标路径下 3处,将apk的动态库 也拷贝到目标路径下。

继续跟踪上图中的 copyPacakge 方法,就走到了 刚才 connectToService连接到的 DefaultContainerService

二十二、App的安装过程全解 可以看出,拷贝的过程就是很简单的IO操作。并且写死的 apk文件的存储名称为base.apk .

装载代码

apk拷贝完成之后,马上就进入到了 装载代码的流程。

回到 HandlerParams的 startCopy方法。 二十二、App的安装过程全解 装载的过程其实就是 processPendingInstall方法。

方法内容如下: 二十二、App的安装过程全解

图中1处,执行 预安装操作,主要是检查安装包的状态,确保安装环境正常。如果安装环境异常,则会清理拷贝文件。

图中2处,是真正的安装阶段。

图中3处,处理安装完成之后的操作。

下面详细关注 真正的安装阶段:

二十二、App的安装过程全解 图中1处,解析 manifest清单文件。我们在清单文件中声明的四大组件,就是在这阶段注册到 系统中。注册之后,就可以通过 startActivity或者 startService的方式来启动相应的服务。

图中2处,对apk中的签名信息进行验证操作。如果相同的包名,我们已经安装了一个debug签名的,然后又安装一个release签名,两个签名不一样,就会中止安装。

图中3处,执行 DEX TO OAT操作,将dex转化成oat文件。 图中4处,执行新apk的安装操作。具体代码如下:

二十二、App的安装过程全解

图中 scanPackageLi 继续扫描apk中的文件,保存 apk相关信息到 pms中。并创建apk的data目录。

图中 updateSettingsLI 如果安装成功,更新系统中的应用信息,比如 应用的权限信息。

图中 deletePackageLi, 则是安装失败时,清空各种缓存文件,以及安装包。

安装完成之后,还会发送一个 App 安装成功的广播,ACTION_PACAKGE_ADDED , Launcher(手机桌面)注册了这个广播,当它收到这个广播之后,就会创建一个icon显示在桌面上。

总结

本篇主要介绍了 App的打包以及安装过程。

打包的主要内容是 资源和代码。生成apk之后还要签名,对齐优化。

apk的安装则分为 拷贝安装包,以及 代码装载两个过程。

转载自:https://juejin.cn/post/7301569815827152907
评论
请登录