概述
前面几篇,经过剖析View的绘制进程以及Activity的启动进程,了解了 Android体系中两个比较重要的体系服务 ActivityManagerService
和 WindowManagerService
,简称 AMS
, WMS
。
本文将详解负责App装置的另一个重要服务 PackageManagerService
本文触及的代码都基于android-28
apk的打包进程
一个完好的安卓项目是由多个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文件 其间记录了许多资源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就打包完毕。
完好内容如下:
apk的装置进程
当咱们在安卓体系上发起某个apk的装置流程时,首先会先看到一个体系的使用装置界面。 这个界面其实是,AndroidFramework层的 PackageInstallerActivity.java
点击装置之后,PackageInstallerActivity 会先把所装置的apk信息 经过 PackageInstallerSession 交给 PackageManagerService 处理。源代码如下所示,mPm便是 PackageManagerService的实例 :
整个装置进程分为两个步骤:
- 复制装置包
- 装载代码
复制装置包
下面将追踪 PackageManagerService
的 源代码来剖析 复制进程。
图中1处,创立了一个Handler体系中的 Message
并指定了INIT_COPY
这个行为,
图中2处,用装置包的相关数据构建了一个 InstallParams
.
最终经过 mHandler将 消息发送出去。
消息的履行如下:
图中1处,获取了刚才构建的 InstallParams
图中2处,尝试衔接装置apk的Service服务。
实践绑定的Servic便是上图中的DEFAULT_CONTAINER_COMPNENT
,
当绑定成功之后,将经过handler发送一个MCS_BOUND
消息,
消息的履行如下: 其间,从 mPnedingInstalls这个等待行列中取出刚才创立的 InstallParams 对象,并且一旦这个InstallParams开始复制,就从等待行列中移除它。
startCopy的源码如下,这是apk复制的核心办法:
图中1处,决议 装置的方位,是在手机内部存储空间,仍是外部存储SD卡。
图中2处,判断apk装置方位,假如装置方位合法,则履行3处逻辑。
图中3处,创立出一个 InstallArgs
,并履行它的copyApk
办法。实践履行的代码在 FileInstallArgs
中。
并实践履行到了 doCopyApk。
doCopyApk 首要做了3件事。
1处,创立存储apk的方针途径。实践上是 data/app/[包名]/
这个目录
2处,将原始文件复制到方针途径下
3处,将apk的动态库 也复制到方针途径下。
持续盯梢上图中的 copyPacakge
办法,就走到了 刚才 connectToService
衔接到的 DefaultContainerService
能够看出,复制的进程便是很简单的IO操作。并且写死的 apk文件的存储名称为base.apk
.
装载代码
apk复制完结之后,马上就进入到了 装载代码的流程。
回到 HandlerParams
的 startCopy办法。
装载的进程其实便是 processPendingInstall
办法。
办法内容如下:
图中1处,履行 预装置操作,首要是查看装置包的状况,保证装置环境正常。假如装置环境异常,则会清理复制文件。
图中2处,是真实的装置阶段。
图中3处,处理装置完结之后的操作。
下面具体重视 真实的装置阶段:
图中1处,解析 manifest清单文件。咱们在清单文件中声明的四大组件,便是在这阶段注册到 体系中。注册之后,就能够经过 startActivity或者 startService的方法来启动相应的服务。
图中2处,对apk中的签名信息进行验证操作。假如相同的包名,咱们现已装置了一个debug签名的,然后又装置一个release签名,两个签名不一样,就会间断装置。
图中3处,履行 DEX TO OAT
操作,将dex
转化成oat文件
。
图中4处,履行新apk的装置操作。具体代码如下:
图中 scanPackageLi 持续扫描apk中的文件,保存 apk相关信息到 pms中。并创立apk的data目录。
图中 updateSettingsLI 假如装置成功,更新体系中的使用信息,比方 使用的权限信息。
图中 deletePackageLi, 则是装置失利时,清空各种缓存文件,以及装置包。
装置完结之后,还会发送一个 App 装置成功的播送,ACTION_PACAKGE_ADDED , Launcher(手机桌面)注册了这个播送,当它收到这个播送之后,就会创立一个icon显示在桌面上。
总结
本篇首要介绍了 App的打包以及装置进程。
打包的首要内容是 资源和代码。生成apk之后还要签名,对齐优化。
apk的装置则分为 复制装置包,以及 代码装载两个进程。