java apk安装路径_android apk安装过程源码解析

前言:

前一篇博客分析了一下PackageManagerService是如何解析apk的以及我们如何解析未安装apk中的androidManifest.xml文件。解析完肯定要安装的,索性写一篇关于android系统是如何安装我们apk的流程分析。不过这里仅仅只分析java层面的代码,C层方面的就跳过了。

apk安装起始点-Pm.java run()

apk安装java层的起始位置是在Pm.java的run()中。

AAffA0nNPuCLAAAAAElFTkSuQmCC

这里有2个重点,第一个红框可以看到与我们的PackageManagerService有关,获取PackageManagerService的binder对象,与PackageManagerService进行通信。并且如果这个对象为null 则输出异常信息直接返回,其实也不难理解,PackageManagerService把我们的apk给扫描了,那安装应该也会在其中。所以这里可以肯定的是apk的安装实现就在我们的PackageManagerService中;第二点就是根据这个install标识来执行安装的方法了。那我们就进入到runInstall()中来看下,它的内部是调用了PackageManagerService的什么方法来进行apk安装的。

runInstall()

AAffA0nNPuCLAAAAAElFTkSuQmCC

从上面的runInstall()方法的代码可以看到 有3个标红框的地方需要了解,第一个obs对象,用于接收PackageManagerService安装结果,其实从第三个红框就一目了然的了解INSTALL_SUCCEEDED,安装成功!就输出Success;第二个红框就是通过binder来调起PackageManagerService中的installPackageWithVerificationAndEncryption()方法。

那接下来看下PackageManagerService中的installPackageWithVerificationAndEncryption()方法是如何操作的

AAffA0nNPuCLAAAAAElFTkSuQmCC

这个方法代码并不是很多,重点在最后一部分,通过handler发送一个INIT_COPY的消息,消息的内容是一个InstallParams对象。(这里要注意下InstallParams,等下会说下这个)

那我们就只要找到handleMessage中处理这个INIT_COPY的消息代码就行了

AAffA0nNPuCLAAAAAElFTkSuQmCC

这里值得一提的是,安装apk的操作还需要一个服务,只有这个服务被bind了,才行进行下一步的工作,也就是通过handler继续发送一个消息。(这个服务是com.android.defcontainer.DefaultContainerService这里就不深层次分析了,它的作用就是用来解析APK,以及获取推荐安装路径的,安装的路径与内存情况以及一些标识来决定)

绕来绕去,开启服务之后又发送了一个消息,那只好继续看下这个MCS_BOUND消息是如何处理的。

MCS_BOUND:

AAffA0nNPuCLAAAAAElFTkSuQmCC

从代码中就能明显看到,这里又对服务进行了一次判断,是否已经连接,所以这个服务于我们的apk安装是共存的,其中mPendingInstalls就是用于存储需要安装的请求,只有当这个队列为空时才断开连接。(在INIT_COPY消息处理中被添加到mPendingInstalls中的),然后又调用了HandlerParams的startCopy()方法执行安装。

AAffA0nNPuCLAAAAAElFTkSuQmCC

可以看到以下几个重点

1.HandlerParams是个抽象类

2.箭头那可以知道,这个安装会尝试4次,超过4次就GG了

3.执行handleStartCopy()方法

4.执行handleReturnCode()方法

在这之前值得一提的是前面installPackageWithVerificationAndEncryption()方法中通过handler发送消息,消息的内容是InstallParams,而InstallParams又是继承自HandlerParams这个抽象类,所以具体执行的是handleStartCopy()与handleReturnCode()的是InstallParams。

不过InstallParams这个方法的代码很长,这里大致说下,InstallParams的handleStartCopy()的主要内容是通过com.android.defcontainer.DefaultContainerService来获取apk的推荐安装路径,通过这个路径来确定是内部安装还是SD卡安装,并且在这个方法的末尾,根据路径来创建不同的InstallArgs,分别是FileInstallArgs/SdInstallArgs执行各自的copyApk()方法!

AAffA0nNPuCLAAAAAElFTkSuQmCC

这里就从FileInstallArgs的copyApk()这条路线来分析。

FileInstallArgs.copyApk()

AAffA0nNPuCLAAAAAElFTkSuQmCC

这个方法的重点部分就在红框位置,它的作用就是把我们的APK给复制到/data/app下,这个的路径可以通过context.getPackageCodePath()获取到,命名规则一般都是XXX.base.apk,不过这里是个临时文件,在安装的时候会对其进行改名操作。

到这就分析完了InstallParams的handleStartCopy()方法,还有一个重点部分是handleReturnCode方法,所以接着分析handleReturnCode();

handleReturnCode():

AAffA0nNPuCLAAAAAElFTkSuQmCC

这里很简单,调用了processPendingInstall()方法

processPendingInstall():

AAffA0nNPuCLAAAAAElFTkSuQmCC

AAffA0nNPuCLAAAAAElFTkSuQmCC

这里分为两部分:

第一张图可以看到标红框部分执行了doPreInstall()和installPackageLI(),doPostInstall();

doPreInstall和doPostInstall内部很简单,他的作用就是把我们安装过程中的临时文件删除,installPackageLI就是我们的正真安装操作。

第二张图则是安装之后,发送一个POST_INTALL消息,告诉系统是否安装完毕。

一系列的安装流程终于走到最后了,看下最终的install操作的方法

installPackageLI:

AAffA0nNPuCLAAAAAElFTkSuQmCC

下面两个红框可以看到,分别通过两种不同的方式进行安装,具体的判断逻辑是根据包名来判断的,如果存在包名则是覆盖安装,而不存在就是安装一个新的apk。replacePackageLI()和installNewPackageLI()内部就和扫描系统中的package信息一样,  它把APK进行扫描,然后把apk中的信息存储到PackageManagerService中。了解4大组件的启动过程就会知道,有一段流程是在PackageManagerService中获取四大组件信息,这些信息就是通过把我们apk扫描安装然后存储到PackageMangerService中的。这样我们的apk就已经安装完成了。

图中还有一个红框,args.doRename()方法(这个args就是我们的FileInstallArgs),前面提到过我们的apk文件会被复制到/data/app下,当复制进来的时候命名格式不是xx.apk,而这里的doRename()方法就是把这个复制进来的文件改名成XXXbase.apk。所以我们context.getPackageCodePath()获取到的路径就是改名后的信息。

APK安装的源码分析就分析到这,大致的流程就是获取我们的安装位置,然后复制我们的apk文件到特定目录,然后安装我们的apk把apk的信息存储到PackageManagerService中。跟着上面的代码走一遍,相信还是很好理解的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/419739.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

复杂度

一、引言 一个算法是由控制结构(顺序、分支和循环3种)和原操作(指固有数据类型的操作)构成的,则算法时间取决于两者的综合效果。为了便于比较同一问题的不同算法,通常的做法是:从算法中选取一种…

几个不错的素材站

w3cplus : http://www.w3cplus.com/JQUERY插件库 jq22.com 牛客 http://www.nowcoder.com/html/aboutusjQuery之家模板之家 http://www.cssmoban.com/动效不错的:http://www.templatemonster.com/demo/54933.htmlhttp://www.templatemonster.com/demo/54935.htmlht…

x3-02 java_Day13 -- Java流程控制02

1. 顺序结构Java的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行。是任何一个算法都离不开的一种基本算法结构。2. 选择结构if单选择结构if双选择结构if多选择结构嵌套的if结构switch多选择结构1) if单选择结构语法:if(布尔…

css3 多列布局使用

css3的出现,解决了不少前端的问题,比如动画,圆角等; 这里总结一下css3 的多列布局; w3c上给出了很多属性; 我们一般用到column-count、column-gap、column-width这三个属性, 其中column-count和…

string容量JAVA_java的StringBuilder类的长度和容量有什么区别呢?

StringBuilder是使用char[] value;存储数据的Overridepublic int length() {return count;}AbstractStringBuilder(int capacity) {value new char[capacity];}长度表示的是字符的个数,容量表示的是可用于最新插入字符的存储量。例如:StringBuilder sbn…

一个TextView使用不同的颜色

一个TextView使用不同的颜色: textview中首先需要已经有内容了 public static void ColorFormatTextView(TextView tv,int color,String textStr){if (TextUtils.isEmpty(textStr) || tv null|| TextUtils.isEmpty(tv.getText())) {return;}String showString tv.…

java集合的某项相加_java8实现list集合中按照某一个值相加求和,平均值等操作代码...

集合: List user = new User(); user .stream().collect(Collectors.summingInt(User::getAge)) 参数类型: summarizingDouble 统计数据(double)状态, 其中包括count min max sum和平均值 summarizingInt 统计数据(int)状态, 其中包括count min max sum和平均值 summarizingLo…

SAP RFC 获取BDC 消息文本的实现

SAP RFC 获取BDC 消息文本的实现 最近做RFC时 ,有调用一个BDC 用于 信息录入 调试程序时,单纯的处理正确、处理异常不能满足,希望获取具体的类似GUI上的提示消息 消息文本该如何获取呢? messtab内容: 初步猜测 可能是…

java script数据类型_javascript 六种数据类型

js的数据类型和常见隐式转化逻辑。一、六种数据类型原始类型(基本类型):按值访问,可以操作保存在变量中实际的值。原始类型汇总中null和undefined比较特殊。引用类型:引用类型的值是保存在内存中的对象。* 与其他语言不同的是,Jav…

RatingBar的自定义

RatingBar的实现其实是很简单的&#xff0c;只要在xml布局文件中写就行了 范例&#xff1a; 在主布局文件中&#xff0c;只需要写<RatingBar/>即可 main.xml 1 <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"2 xmlns:tools&q…

python中什么最重要_Python 3中被忽视了的三大重要功能

全文共2201字&#xff0c;预计学习时长6分钟图源&#xff1a;unsplashPython 3上线已有一段时间&#xff0c;大多数开发人员(特别是那些首次编程的人)已经在使用它了。不过&#xff0c;你确定已经对Python 3研究透彻了吗&#xff1f;事实上&#xff0c;其中还有许多新功能对大多…

Java基础总结(一)

1. 面向对象的特征面向对象的特征包括抽象、封装、继承和多态。 抽象就是忽略一个主题中与当前目标无关的某些方面&#xff0c;以便更加充分的注意到与当前目标有关的方面。抽象并不打算了解全部的问题&#xff0c;而只是其中的一部分&#xff0c;暂时不用考虑细节。抽象包括两…

java 2分代复制垃圾回收_Java对象的后事处理——垃圾回收(二)

1 先谈Finalize()finalize()能做的所有工作&#xff0c;使用try-finally或者其他方式都可以做得更好、更及时&#xff0c;所以笔者建议大家完全可以忘掉Java语言中有这个方法的存在。——《深入理解JVM》finalize()方法确实可以实现一次对象的自救&#xff0c;但是其不确定性和…

前端学习(1555):ng-app指令

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>ng-app指令</title> </head> <!-- 需…

前端学习(1556):ng-blnd指令

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>ng-app指令</title> </head> <!-- 需…

标准输入输出重定向

程序会在运行中输出日志&#xff0c;并是通过java的日志类进行输出的。而如果关掉SSH运行程序&#xff0c;就会丢失这些信息。直观的解决办法是将输出到控制台的日志重定向到文件中&#xff0c;于是我将命令改为&#xff1a;sh auto.sh > console.txt &。不过事实并没像…