概述

前面几篇,经过剖析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的装置则分为 复制装置包,以及 代码装载两个进程。