一文看懂Android APK安装的原理

2023-11-01

一文看懂Android APK安装的原理

前言

大家有没有想过一个应用的APK是怎么被安装到安卓手机上的,安装的本质是什么?我们知道,Windows应用程序的安装包是一个可执行的压缩包,安装的过程是把压缩包中的数据和依赖库拷贝到安装目录,再在桌面或启动栏创建快捷方式,那么安卓的APK安装过程是不是也是这样的呢?本文将为大家解答这些问题。

APK包的构成

首先,我看一下APK包的构成,Android的APK包和Windows应用程序安装包是不同的,它只是个简单的压缩包,没有可执行的能力,我们还可以用zip工具直接解压它。

一个APK包含以下这些文件:

  • META-INF目录:包含两个签名文件(CERT.SF和CERT.RSA),以及一个manifest文件(MANIFEST.MF)
  • assets目录:包含工程中的asset目录下的文件,可以使用AssetManager获取
  • res目录:包含那些没有被编译到resources.arsc的资源
  • lib目录:包含适用于不同处理器的第三方依赖库,这里边可以有多个子目录,比如armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, 以及mips
  • resources.arsc文件:存储编译好的资源,包括项目工程中的res/values目录里的xml文件,它们都被编译成二进制格式,也包括一些路径,指向那些没有被编译的资源,比如layout文件和图片
  • classes.dex文件:项目中的java类都被编译到该dex文件,这个文件可以被Android的Dalvik/ART虚拟机解析。
  • AndroidManifest.xml:二进制格式的manifest文件,这个文件是必须的。

这些文件是Android系统运行一个应用程序时会用到的数据和代码,下面介绍系统如何安装一个APK包。

安装APK

我们安装应用程序,最常用的方法就是在PC上运行命令adb install 加APK的文件路径,回车等待Android设备安装完成,安装成功命令行会显示Success。那么其内部是怎样的一个过程呢?

1. 将APK包push到手机
首先,adb会将PC端的APK文件push到Android设备的/data/local/tmp目录下,一些手机会将拷贝的进度反馈给adb客户端,于是PC上的命令行会展示拷贝的进度。

2. 执行pm命令
PC端的adb程序会向Android端的adbd发送shell:pm命令,于是adbd会向系统的PackageManagerService(PMS)进程发送消息,通知其安装apk包。这里我有两个理解:
**理解一:**我们平常也可以在adb shell上执行pm命令与PMS交互,那么pm应该是个独立的进程,adbd执行pm命令,是启动了pm这个进程,这个进程再向PMS进程发送消息,通知其安装APK。
**理解二:**adbd直接向PMS进程发送消息,通知其安装APK。
不知哪个正确,这个有待继续研究,如果有童鞋了解这个,希望能不吝赐教。

3. 触发安装过程
PMS首先将APK包拷贝到另外一个目录/data/app,这个目录是非系统应用的apk存放的目录,与之相对应的,系统应用的apk存放的目录是/system/frameworks、/system/app和/vendor/app。
PMS内部有个AppDirObserver类,其监听着/data/app目录的变化,当apk被复制到/data/app目录之后,该类随即触发PMS对APK进行解析。

4. APK的解析
我们可以先想想,Android系统是如何启动一个APP的?比如点击屏幕上的应用图标,然后一个Activity就被启动了。这个过程中,桌面程序Launcher先是向ActivityManagerService(AMS)进程发送了一个Intent,AMS随即会将这个Intent扔给PMS,PMS则解析这个Intent得到Activity的信息给到AMS,然后AMS会启动一个空进程,并通知该进程创建该Activity。那么PMS为什么会有这个Activity的信息呢?

这就是PMS解析APK要做的事情了,而解析APK的时机又要分成两种场景:

1. 系统启动时解析APK
Android系统在启动的时候,会启动一个system_server进程,这个进程驻留着系统多个重要的服务,其中便包含了与APK最相关的PackageManagerService服务,这个服务在启动的时候,会扫描Android系统中几个目标文件夹中的APK,对每个APK进行解析。
2. 安装过程中解析APK
安装一个apk的过程,PMS也会对这个APK进行解析,其调用的是PackageManagerService.java的scanPackageLI()方法,其实在系统启动时扫描全部apk的过程也是调用该方法。

可以这样理解,系统启动的时候,是解析已经安装的所有APK,而安装单个APK时,则是用同样的方法解析这个APK,过程是一样的。

那么解析APK具体做的是什么事情呢?

其中主要的过程就是解析APK中的AndroidManifest.xml文件,将APK的关键信息四大组件信息、权限信息等存储在内存中的PackageParser对象中,PackageParser对象的结构如图所示:

来源:https://blog.csdn.net/Innost/article/details/47253179

这个PackageParser包含了IntentFilter的信息,使得PMS可以根据Intent来获取一个Activity的信息。那么,PMS在得到PackageParser对象之后,接着会将这个APK的信息加入到PMS自身管理中去,比如将Activity的数据保存在mActivities对象中,将Provider的数据保存在mProviders对象中等,PKMS提供了好几个重要数据结构来保存这些数据,这些数据结构的相关信息如图所示:

来源:https://blog.csdn.net/Innost/article/details/47253179

除了解析和保存APK的核心数据,PMS还会创建应用程序目录:/data/data/包名,同时提取apk中的dex文件并保存到/data/dalvik-cache中,如果该APK包含了native动态库,则需要将它们从APK文件中解压并复制到对应目录中,以及对APK进行dex优化,还有其它一些细节比如APK签名的校验,杀死APK所在进程(覆盖安装的情况)等,安装过程的最后,会发送ACTION_PACKAGE_ADDED广播,通知所有其它应用有新应用安装了。

总结

至此,APK安装过程就结束了。纵观整个过程,apk安装的关键就是解析AndroidManifest.xml,将重要的信息保存在PMS进程的内存中,以保证后续启动这个应用程序的组件时,可以在PMS中找到这个组件的信息。我们本来认为的更重要的代码只是进行dex优化后简单地提取到一个目录中而已,另外,APK中的资源并没有被处理,而是在启动应用进程的时候,动态去从APK包中加载而已。

本文完。


简书:https://www.jianshu.com/p/79e963715d1d
版权声明:本文为博主原创文章,转载请附上博文链接!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

一文看懂Android APK安装的原理 的相关文章

  • Python项目代码结构详解

    目录结构组织方式 简要解释一下 bin 存放项目的一些可执行文件 当然你可以起名script 之类的也行 luffy 存放项目的所有源代码 1 源代码中的所有模块 包都应该放在此目录 不要置于顶层目录 2 其子目录tests 存放单元测试代

随机推荐

  • QML 中播放PPT文件

    效果 一 思路 MFC 操作PPT 然年将MFC封装成dll 供Qt使用 案例分享 Qt的PPT播放器 长沙红胖子Qt的博客 CSDN博客 qt 打开ppt Qt将mfc中的句柄 加载到QWidget中 QML 通过 QQuickWidge
  • 用户态和内核态的区别

    1 操作系统需要两种CPU状态 内核态 Kernel Mode 运行操作系统程序 操作硬件 用户态 User Mode 运行用户程序 2 指令划分 特权指令 只能由操作系统使用 用户程序不能使用的指令 举例 启动I O 内存清零 修改程序状
  • 计网

    实验目的和要求 熟悉交换机各种命令模式和基本命令 学习交换机的基本配置 制作网络拓扑图 1台交换机 2台PC 2台PC能够ping通 截图 截图网络拓扑图 2台PC 2台pc机分别用连通线和交叉线连接 然后测试其连通性 学习交换机VLAN的
  • 【crypto】基于crypto.js的web前端加解密系统实现

    文章目录 一 概念介绍 1 1 crypto js介绍 1 2 加密 哈希 编码 1 2 1 加密 解密 1 2 2 散列 哈希 1 2 3 BASE64编解码 二 加解密思想 以md5为例 三 前端加密系统实现代码 3 1 加解密 3 2
  • C++称硬币(枚举)

    有12枚硬币 其中有11枚真币和1枚假币 假币和真币重量不同 但不知道假币比真币轻还是重 现在 用一架天平称了这些币三次 告诉你称的结果 请你找出假币并且确定假币是轻是重 数据保证一定能找出来 输入 第一行是测试数据组数 每组数据有三行 每
  • java.sql.SQLException: Access denied for user ‘root‘@‘localhost‘ (using password: YES)报错原因

    1 第一个 用户名和密码不匹配 或者是在连接池里多打了空格之类的 就是配置文件的问题 2 第二个 可能是用户的权限不够 给他添加权限 授予权限 grant all privileges on databasename tablename t
  • 关于键盘盲打的一些小技巧

    当然也是很久以前在某个网站搜索一下 然后保存的 个人觉得比较有用 具体的也不太清了 电脑键盘指法作为使用电脑的基本功 在初期养成正确的键盘指法十分重要 很多朋友由于初期没有养成正确键盘指法的习惯 导致后期习惯了错误的键盘指法 要更正已经相当
  • No module named ‘tensorflow.contrib‘问题解析以及tensorflow的卸载安装和向下兼容

    0 问题原因 TensorFlow 2 0中contrib被弃用 1 卸载原Tensorflow 重新安装 卸载 在开始安装前 如果你的电脑装过tensorflow 请先把他们卸载干净 包括依赖的包 tensorflow estimator
  • Github Fork 使用详解

    Fork 是对一个仓库的克隆 克隆一个仓库允许你自由试验各种改变 而不影响原始的项目 一般来说 forks 被用于去更改别人的项目 贡献代码给已经开源的项目 或者使用别人的项目作为你自己想法的初始开发点 提出更改别人的项目 使用 forks
  • 【React】函数组件 hooks-useState

    React 函数组件 hooks useState 使用hooks理由 useState 保存组件状态 切换数值 实现todolist增加和删除 最终结果 使用hooks理由 高阶组件为了复用 导致代码层级复杂 生命周期的复杂 写成func
  • angular4 通过httpclient调http接口,出现access-control-allow-origin跨域问题解决办法

    最近项目中在用angular4 在调试后台http接口时 会出现跨域问题 在chrom浏览器控制台报错如下 在浏览器属性中增加几行命令 即可解决该问题 具体做法如下 右击浏览器 选择属性 目标那一栏中增加如下命令 args disable
  • MQTT异步使用

    目录 1 结构体 1 1 MQTTAsync 1 2 MQTTAsync connectOptions 1 3 MQTTAsync disconnectOptions 1 4 MQTTAsync responseOptions 1 5 MQ
  • Nginx 基本优化

    一 一般来说nginx 配置文件中对优化比较有作用的为以下几项 1 worker processes 8 nginx 进程数 建议按照cpu 数目来指定 一般为它的倍数 如 2个四核的cpu计为8 2 worker cpu affinity
  • Linux常用的命令

    Linux常用的命令 1 常用的系统工作命令 1 1 执行查看帮助命令 man 命令 man 命令用来查看man命令自身的帮助信息 MAN 1 Manual pager utils MAN 1 NAME man an interface t
  • 浅谈unsigned与signed的区别

    在我们写c语言的程序中 总是能看见unsigned的关键字 unsigned的作用是声明无符号的整形类型 与signed对应 这个关键字是挺常见的 unsigned 用来声明无符号的整形变量 signed 用来声明有符号的整形变量 我们以
  • 毕业设计 2023-2024年最新计算机专业毕设选题题目推荐汇总

    文章目录 0 前言 1 java web 管理系统 毕设选题 2 java web 平台 业务系统 毕设选题 3 游戏设计 动画设计类 毕设选题 适合数媒的同学 4 算法开发 5 数据挖掘 毕设选题 6 大数据处理 云计算 区块链 毕设选题
  • AdaBoost算法讲解以及MATLAB实现

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 一 算法描述 二 算法步骤是什么 三 数据集说明 可以自己增加数据集 四 算法实现MATLAB 1 主函数 2 找到误差率最小的弱函数 3 分别计算弱分类函数 并计
  • 数据清洗(一):拉勾网数据分析案例

    1 导入数据 导入相应的包 import pandas as pd import numpy as np import matplotlib pyplot as plt matplotlib inline matplotlib inline
  • 20190417-Leetcode-409.最长回文数

    Leetcode 409 最长回文数 给定一个包含大写字母和小写字母的字符串 找到通过这些字母构造成的最长的回文串 在构造过程中 请注意区分大小写 比如 Aa 不能当做一个回文字符串 注意 假设字符串的长度不会超过 1010 示例 1 输入
  • 一文看懂Android APK安装的原理

    一文看懂Android APK安装的原理 前言 APK包的构成 安装APK 总结 前言 大家有没有想过一个应用的APK是怎么被安装到安卓手机上的 安装的本质是什么 我们知道 Windows应用程序的安装包是一个可执行的压缩包 安装的过程是把