Android内核解读-应用的安装过程
前言
我们知道,在android手机上安装一个apk很简单,只要打开apk文件,默认就会弹出安装界面,然后点击确定,经过若干秒后,apk就安装成功了,可是你知道apk的安装过程是什么吗?你知道android系统在安装一个apk的时候都干了什么吗?在本文中,将一一解答这个问题。简单来说,apk的安装过程分两步:第一步,将apk文件复制到程序目录下(/data/app/);第二步,为应用创建数据目录(/data/data/package name/)、提取dex文件到指定目录(/data/dalvik-cache/)、修改系统包管理信息。注意,本文的分析基于Android
4.3源码。
apk的复制过程
apk的安装从PackageManager的installApk方法开始,由于PackageManager所对应的binder服务为PackageManagerService(PMS),所以,真正的安装过程都在PackageManagerService中完成。PackageManagerService的installApk方法最终调用了installPackageWithVerificationAndEncryption方法,该方法的核心就是在最后发送了一个INIT_COPY的消息,这个消息的含义是完成apk的拷贝过程。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
public IPackageInstallObserverint VerificationParams mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null); final if try observer.packageInstalled(, }catch } return; } UserHandle if0) user }else usernew } final if0) if Slog.v(TAG, } filteredFlags }else filteredFlags } verificationParams.setInstallerUid(uid); final msg.objnew verificationParams, mHandler.sendMessage(msg);} |
通过分析代码可以发现,真正实现apk拷贝的方法是InstallParams的handleStartCopy方法,InstallParams中有重试机制,拷贝如果失败的话会重试,最多重试4次。在拷贝之前,还必须做一件事情,那就是绑定media container service,安装过程中一些状态的检查会用到这个服务,代码如下所示:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
classextends private false; final new private if DefaultContainerService); Intentnew Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); if Context.BIND_AUTO_CREATE, Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); mBoundtrue; return; } Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); return; } ...}</handlerparams></handlerparams> |
现在分析一下InstallParams的handleStartCopy方法,这个方法很长,代码就不帖出来了,大家可以自己去看看,这里主要分析下它的工作流程:
1. 检查安装位置标记位是否有冲突,如果有冲突,则安装失败,这里的有冲突是指“一个apk同时要求被安装到内部存储和sd卡”
2. 调用MCS服务的getMinimalPackageInfo方法来得到apk的推荐安装位置,并检查是否能够进行正常的安装。在这一步,有可能抛出一些无法安装的状态位:存储空间不足、程序已经安装、无效的apk文件等,这个时候安装过程终止
3. 到这一步,表示程序可以正常安装,同时MCS服务服务可能会根据需要调整安装位置,在InstallParams的installLocationPolicy中完成
4. 文件的复制过程,PMS针对内部存储和sd卡分别提供了一个类:FileInstallArgs和AsecInstallArgs,并分别调用二者的copyApk方法来完成apk的复制过程
经过了上面4步,待安装apk已经被复制到了/data/app/目录了。
apk的解析过程
上面,apk已经被复制到了/data/app/目录,安装的第一步已经完成,那么系统是什么时候对apk进行dex提取和解析的呢,这还要从PMS说起,在PMS内部有一个AppDirObserver类,顾名思义,它的作用是应用目录观察者,它时刻观察着应用目录/data/app/,当目录内部结构改变的时候(创建文件和删除文件)它会做出相应行为,下面看下它的代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
private extends publicintboolean super(path, mRootDir mIsRom } //在/data/app/目录下添加或删除apk的时候,此方法会被调用 public int Stringnull; int1; int[]null; Stringnull; int1; int[]null; // synchronized Stringnull; Filenull; ifnull) fullPathnew fullPathStr } if Log.v(TAG, if if Log.v(TAG,package return; } // // if return; } PackageParser.Packagenull; PackageSettingnull; // synchronized p ifnull) ps ifnull) removedUserstrue); }else removedUsers } } addedUsers } //当apk被删除的时候,往往意味着这个apk被卸载 if0) ifnull) if //removePackageLI方法完成卸载apk的主要功能 removePackageLI(ps,true); removedPackage removedAppId } } //新添加了一个apk,往往意味着一个新的apk被安装 if0) ifnull) if //scanPackageLI方法完成了apk安装的第二个步骤 p (mIsRom |0) PackageParser.PARSE_CHATTY PackageParser.PARSE_MUST_BE_APK, SCAN_MONITOR System.currentTimeMillis(), ifnull) /* * * * */ // synchronized updatePermissionsLPw(p.packageName, p.permissions.size()00); } addedPackage addedAppId } } } // synchronized mSettings.writeLPr(); } } //下面两个if语句块大家应用不陌生吧,在我们的应用中想监听应用的安装和卸载, //就是通过收听ACTION_PACKAGE_ADDED和ACTION_PACKAGE_REMOVED这两个广播来实现的 ifnull) Bundlenew1); extras.putInt(Intent.EXTRA_UID, extras.putBoolean(Intent.EXTRA_DATA_REMOVED,false); sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, extras,null,null, } ifnull) Bundlenew1); extras.putInt(Intent.EXTRA_UID, sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, extras,null,null, } } private private } |
下面,我们主要分析一下scanPackageLI方法,还是仅仅分析,不帖代码,因为代码太长了,帖出来没法看了,这个方法不仅仅是完成apk包的扫描,还解析AndroidManifest.xml文件并提取出所有的intent-filter和permission信息,apk安装的主要功能都由它来完成的,当apk包扫描完成后,系统会调用updatePermissionsLPw方法更新系统所具有的权限。
scanPackageLI方法有两个,其第一个参数分别接受File和PackageParser.Package类型,第一个方法会从File中提取出package信息然后再调用第二个方法,下面分析第二个scanPackageLI方法,其完成的事情如下:
1. 如果包名是android,则会做一些特殊处理,这个包名为android的应用是系统内部应用的,其他应用的包名如果叫android则安装会有问题,大家可以试一下
2. 解析常见的use-feature、shared-userId、use-library标签并保存到成员变量中
3. 进行签名验证,对应的方法是verifySignaturesLP,验证失败则应用无法安装
4. 创建应用程序目录/data/data/包名,同时将apk中提取出dex文件并保存到/data/dalvik-cache,把apk当做zip解压就能得到dex文件
5. 解析AndroidManifest.xml文件,提取出所需信息,包括具有intent-filter的四大组件信息(Activity、Service、BroadcastReceiver、ContentProvider)和声明的系统权限等
到此为止,scanPackageLI方法结束了。而updatePermissionsLPw的作用是对系统中所有的权限进行更新,大家可以查看下/system/etc/permissons目录,下面定义了android系统中所有的权限,开发中最常用的权限定义在目录下的platform.xml里面,大家可以打开看看,可以看到常见的访问网络、读写外部存储等权限等都是在这里定义的。权限更新完毕以后,系统就会发送ACTION_PACKAGE_ADDED广播,告知所有应用有新应用安装了。另外,大家可以查看下data/system/目录,里面有两个文件packages.list和packages.xml,在packages.list里面放的是手机上安装的所有应用列表,而packages.xml中存放的是所有应用的设置应用,比如一个应用声明了哪些系统权限就定义在这里面。关于应用的卸载,我们可以想到是应用安装过程的逆过程,大致要做的是:停止应用、删除各种文件,更新系统设置、权限等,大家感兴趣自己看一下,完全是安装过程的逆过程,这里不介绍了。
Android内核解读-应用的安装过程的更多相关文章
- 一,我的Android Studio 3.0.1 安装过程
安装成功于20171231的0:46分. 简要记录我的安装过程如下: 一,安装JDK1.8.X 二,安装ANDROID STUDIO.ZIP 三,运行AS,后按提示下载SDK,NDK,必要时设置一下J ...
- Android内核驱动程序的编写和编译过程
注意:涉及的代码为android内核代码而不是android源码. 在智能手机时代,每个品牌的手机都有自己的个性特点.正是依靠这种与众不同的个性来吸引用户,营造品牌凝聚力和用户忠城度,典型的代表非ip ...
- Android Activity启动流程, app启动流程,APK打包流程, APK安装过程
1.Activity启动流程 (7.0版本之前) 从startActivity()开始,最终都会调用startActivityForResult() 在该方法里面会调用Instrumentation. ...
- android APK应用安装过程以及默认安装路径[转]
一:安装过程 APK是类似Symbian Sis或Sisx的文件格式.通过将APK文件直接传到Android模拟器或Android手机中执行即可安装. Android应用安装有如下四种方式 1. ...
- Android apk 的安装过程
Android应用安装有如下四种方式 1.系统应用安装――开机时完成,没有安装界面 2.网络下载应用安装――通过market应用完成,没有安装界面 3.ADB工具安装――没有安装界面. 4.第三方应用 ...
- Android APK安装过程介绍
课题路径:从Myfile中点击应用进行安装,到安装完成,过程分析 思想方法:在研究PreloadInstaller的时候我们直接从整个apk的文件结构入手,由整体到部分的分析:但现在整个PMS非常庞大 ...
- Android 安装过程中的问题
Android 安装过程中的问题 上一篇我说到配置android环境,但是在具体的安装过程中,因为下载的软件或者方法不同,导致没有正确的结果,如果有一些错误的时候,可以试一试关闭eclipse软件, ...
- Android应用打包安装过程具体解释
Android应用打包安装过程(Run as Android Application ): 1,过程:Android Project --> Compilation and Packaging ...
- Android应用程序安装过程源代码分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6766010 Android系统在启动的过程中, ...
随机推荐
- 模块(module)
1.模块加载 import math //import后面跟模块名 from module1 import module11 //module1是一个大模块,里边有子模块module11,调用这个 ...
- [DeeplearningAI笔记]改善深层神经网络_深度学习的实用层面1.10_1.12/梯度消失/梯度爆炸/权重初始化
觉得有用的话,欢迎一起讨论相互学习~Follow Me 1.10 梯度消失和梯度爆炸 当训练神经网络,尤其是深度神经网络时,经常会出现的问题是梯度消失或者梯度爆炸,也就是说当你训练深度网络时,导数或坡 ...
- Django的admin.py注册流程
通常创建一个Django项目的时候,在Django的配置文件settings.py中,都会有下面的这段配置: INSTALLED_APPS = [ 'django.contrib.admin', 'd ...
- VUE2.0增删改查附编辑添加model(弹框)组件共用
Vue实战篇(增删改查附编辑添加model(弹框)组件共用) 前言 最近一直在学习Vue,发现一份crud不错的源码 预览链接 https://taylorchen709.github.io/vue- ...
- 代理(Proxy)模式
代理模式的类图如下所示: 客户端想调用的是RealSubject,由于某种考虑或原因,只能直接访问到ProxySubject,再由ProxySubject去调用RealSubject,这就完成了一次代 ...
- 洛谷 [P2766] 最长不下降子序列问题
啊啊啊,再把MAXN和MAXM搞反我就退役 层次图求不相交路径数 第一问简单DP 第二问想办法把每一个不上升子序列转化成DAG上的一条路径,就转换成了求不相交路径数 因为每一个数只能用一次,所以要拆点 ...
- CF 455D. Serega and Fun [分块 deque]
Serega and Fun 题意: [l,r]循环右移一位,查询区间内某个数出现次数 为什么好多人用链表?反正我是不会写双向链表 完全可以分块然后模拟啊...中间的块只会插入删除一个元素呀....用 ...
- python并发编程之线程(一):线程&守护线程&全局解释器锁
一 threading模块介绍 multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性,因而不再详细介绍 官网链接:https://docs.pyth ...
- 微信开发系列——微信订阅号前端开发利器:WeUI
前言:年前的两个星期,学习了下微信公众号的开发.后端基本能够基于盛派的第三方sdk能搞定大部分事宜.剩下的就是前端了,关于手机端的浏览器的兼容性,一直是博主的一块心病,因为博主一直专注于bootstr ...
- css中的关于margin-top,position和z-index的一些bug解决方案
这两天在写一个demo的时候,就碰到一些css的问题,不知道能不能算bug,很有可能是因为我写的代码太少,孤陋寡闻了_(:зゝ∠)_.记录一下,以防下次遇到同样问题. 进入正题: 1.问题描述:div ...