文档章节

Android程序包管理(2)--使用adb install执行安装过程

shzwork
 shzwork
发布于 07/04 23:00
字数 2275
阅读 2
收藏 0

二、程序安装过程
1.使用adb install执行安装过程
使用adb install执行安装过程整体流程图如下:

一、使用adb install命令安装apk

1.adb指令对应源文件system/core/adb/commandline.c。

2.指令参数解析:根据传入参数install判断是安装指令,直接调用到install_app();

3.执行文件拷贝:在install_app()中:

首先定义两个拷贝位置:分别对应拷贝到内部或者外部存储。这里需要根据传入参数确定拷贝位置。默认是拷贝到内部存储中。

执行拷贝:将制定的apk文件从电脑端拷贝到制定的目录处。

执行安装:调用pm_command()函数开始去安装。

删除文件:当安装结束时删除该apk文件。

4.开始去安装:在pm_command()中:

构造shell指令:将参数凭借成为shell指令。

去执行shell:使用send_shellcommand()去执行pm脚本,使用app_process运行pm.jar。

二、跨进程去执行安装

1.执行前准备:

获取Binder:首先获取PKMS对应的Binde对象。

解析传入参数:判断是install指令确定是安装指令。调用runinstall()。

2.准备跨进程安装:在runinstall()中:

解析参数:while循环依次解析参数确定installFlags,接着获取apk文件路径构造apkURI通过它读取文件。

跨进程调用:首先新建PackageInstallObserver回调接收PKMS安装结果,然后使用mPm.installPackageWithVerificationAndEncryption()跨进程调用到PKMS该函数执行。

等待安装结果:循环判断PackageInstallObserver.finished状态,等待安装结果根据结果提示用户信息。

三、PKMS执行具体安装

1.执行安装准备工作:在installPackageWithVerificationAndEncryption()中:

检查权限:首先检查调用者进程是否存在安装应用的权限。

获取uid,设置filteredFlags:获取调用者uid根据uid做后续判断。如果uid是SHELL_UID为filteredFlags设置INSTALL_FROM_ADB表示否则取消该表示,这里是需要设置该标识。

发生异步消息:获取INIT_COPY标识的Message对象,设置obj为新建对象InstallParams,该对象分装了安装需要的参数及信息。然后发送该Message。

InstallParams类图关系如下: 


2.执行异步消息:在PackageHandler中:

处理消息:异步消息都会调用doHandleMessage()处理具体逻辑。

判断在INIT_COPY标识下:

首先获取安装请求对象:obj即HandlerParams的子类InstallParams。

判断是否启动服务:mBound表示是否启动DefaultContainerService服务,该服务由DefaultContainerService.apk提供,主要作用是拷贝文件到应用程序目录。如果已启动则将该安装请求对象添加到队列mPendingInstalls中该队列如果为空则发生消息MCS_BOUND执行安装。如果未启动调用connectToService()启动该服务。

判断在MCS_BOUND标识下:该标识在DefaultContainerService启动成功后也会回调。

获取mContainerService对象:如果是DefaultContainerService启动成功后的回调,直接获取obj即为该对象。判断mContainerService是否为空,如果为空代表DefaultContainerService服务未启动不能执行安装操作,不为空判断如果mPendingInstalls队列存在请求则开始执行。

获取安装请求:使用mPendingInstalls.get(0)获取一个待安装请求HandlerParams。

执行安装请求:调用该HandlerParams.startCopy()函数,判断函数返回结果,返回为true代表处理成功。

请求处理成功:请求处理成功时,首先从mPendingInstalls队列中移除该请求,如果mPendingInstalls队列此时大小为0代表所有请求已完成则回调MCS_UNBIND断开服务。如果还存在请求则继续回调MCS_BOUND消息执行安装请求。

3.执行安装请求逻辑:HandlerParams.startCopy()中:

尝试次数判断:安装请求执行失败后有重试机制。判断mRetries是否大于最大尝试次数,超过最大次数发生异步消息MCS_GIVE_UP放弃执行返回false。未超过则执行安装行为。

执行拷贝操作:调用handleStartCopy()执行拷贝请求,具体是实现在InstallParams中。

执行安装操作:调用handleReturnCode()执行安装请求,具体是实现在InstallParams中。

4.执行apk的拷贝:在HandlerParams.handleStartCopy()中:

获取指定的安装位置:首先从flags中获取指定的安装位置,这里的flags来自于之前解析参数传入的filteredFlags。判断如果同时指定既在sd卡安装又在内部存储安装则赋值ret安装失败。

获取手机存储状况:通过dsm服务调用getMemoryLowThreshold()获取当前内部存储最小余量。小于这个值就是空间不足。

授予apk读取权限:授予DefContainerService URI读权限,使其可以执行apk的拷贝操作。

获取PackageInfoLite对象并判断:首先获取待安装apk的packageFile对象,根据该对象调用mContainerService.getMinimalPackageInfo()获取其对应的PackageInfoLite对象,该对象描述apk的包名、版本、推荐安装位置、签名等信息。然后判断该apk的安装推荐位置是RECOMMEND_FAILED_INSUFFICIENT_STORAGE代表当前存储空间不足需要释放空间,计算该apk安装需要的空间然后使用mInstaller.freeCache()释放空间,之后在尝试获取一次PackageInfoLite对象。

撤销apk读取权限:撤销对uri的读取权限mContext.revokeUriPermission()。

确定最终安装的位置:根据pkgLite.recommendedInstallLocation确定ret值,并且最终确定安装位置sd卡或者是内部存储,并设置flags值。

新建安装参数对象InstallArgs:调用createInstallArgs(this)创建一个安装参数对象,根据flag对安装位置区别处理。这里如果是安装在sd卡上返回AsecInstallArgs对象,反之是FileInstallArgs对象。它们都继承自InstallArgs。注意这里构造的时候传入的是当前的安装请求对象HandlerParams,该对象分装了这次请求需要的所有信息参数。

判断一系列验证检查:如果设置了包验证开启,则收集信息发送广播给包校验器检查,检查通过才能接着进行安装。如果未设置则直接调用安装参数对象InstallArgs.copyApk()执行拷贝apk。

5.具体开始执行apk的拷贝操作:在InstallArgs.copyApk()中,假设安装位置在内部存储则该方法具体实现在FileInstallArgs中:

判断temp:temp代表拷贝到/data/app下的文件名是否需要随机,这里我们传入的true是要随机,因为如果不随机以apk结尾,PKMS会监听到该文件之后直接执行安装操作,我们不需要直接进行该安装操作,所以设置随机名。

执行apk拷贝操作:首先获取创建apk对应File对象codeFile,为DCM服务授权读取权限。接着使用imcs.copyResource()拷贝资源到codeFile文件。同时为该apk创建native目录并且拷贝native库到该位置。最后返回安装结果ret。

至此安装操作完成HandlerParams.handleStartCopy()执行完毕赋值安装结果给mRet变量。

6.拷贝完成执行安装操作:在HandlerParams.handleReturnCode()中:

判断安装参数对象InstallArgs:首先判断InstallArgs对象如果不为null则开始执行安装流程,调用processPendingInstall()。安装结束之后删除临时文件,如果未开启包验证则该文件不存在不需要删除。

执行安装操作:使用Hanlder发布异步任务,新建安装结果对象PackageInstalledInfo,接着调用installPackageLI()执行安装操作,传入安装参数对象InstallArgs及PackageInstalledInfo获取安装结果。安装完成之后新建对象PostInstallData分装InstallArgs及PackageInstalledInfo然后放入mRunningInstalls这个map中,新建一个token为索引。最后发生一个异步消息POST_INSTALL并携带索引token,通知安装结果。

7.安装完成执行通知操作:在PackageHandler中:

判断在POST_INSTALL标识下:

获取安装结果对象:在mRunningInstalls中根据token获取安装结果PostInstallData。如果存在则分别取出对应的InstallArgs和PackageInstalledInfo。

处理安装成功情况:判断PackageInstalledInfo.returnCode是安装成功,首先发送安装成功广播ACTION_PACKAGE_ADDED,如果是应用更新操作还要发送ACTION_PACKAGE_REPLACED广播。然后进行资源清理,接着取出InstallArgs.observer不为空代表存在安装结果回调对象,则回调其对应结果。

至此adb install安装程序流程完成。

简单总结流程:

将电脑端apk资源拷贝到制定的临时文件夹下。

将apk拷贝到/data/app目录下,但是文件名需要随机处理。

调用PKMS函数执行apk安装。

回调安装结果给监听器。
--------------------- 
作者:leif_123 
来源:CSDN 
原文:https://blog.csdn.net/leif_/article/details/79494795 
版权声明:本文为博主原创文章,转载请附上博文链接!

本文转载自:https://blog.csdn.net/leif_/article/details/79494795

shzwork
粉丝 15
博文 826
码字总数 11168
作品 0
厦门
私信 提问
[RK3288][Android7.1] 调试笔记 --- APK代码中无法通过pm install自我升级

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kris_fei/article/details/90171912 Platform: RK3288 OS: Android 7.1 Kernel: v4.4.83 现象: APK中使用命令...

KrisFei
05/13
0
0
Android包管理机制(五)APK是如何被解析的

本文首发于微信公众号「刘望舒」 原文链接:APK是如何被解析的? 相关文章 包管理机制系列 前言 在本系列的前面文章中,我介绍了PackageInstaller的初始化和安装APK过程、PMS处理APK的安装和...

刘望舒
2018/10/18
0
0
Android包管理机制(一)PackageInstaller的初始化

前言 包管理机制是Android中的重要机制,是应用开发和系统开发需要掌握的知识点之一。 包指的是Apk、jar和so文件等等,它们被加载到Android内存中,由一个包转变成可执行的代码,这就需要一个...

刘望舒
2018/06/19
0
0
xmake v2.2.2 发布, 让C/C++拥有包依赖自动构建

历经四个多月,xmake终于更新了新版本v2.2.2,并且上线了重量级功能:原生支持的远程依赖包管理。 而这个特性,其实我陆陆续续写了将近一年的时间,才初步完成,对于此特性的开发进展和历史,...

ruki
2018/10/17
1K
11
android studio problems

1 在android studio 下新建android project ,编译没有问题。 而导入已经存在的项目时,一直报错:Connection refused。 这个时候就要考虑是配置哪里跟自己android studio 本地的不一样,果然...

CamilleIT
2018/06/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

JavaScript权威指南笔记3-2

第三章、类型、值和变量 2、文本 I-1 字符串 是一组由16位值组成的不可变的有序序列。 每一个字符来自Unicode字符集 用来表示文本 长度是其所含16位值的个数。 和数组一样,索引从0开始。 JS...

_Somuns
24分钟前
5
0
Spring StateMahcine State 配置详解

状态机包含一系列各种关系的状态,最简单的关系,就是经过状态A事件E直接到状态B,当然还有选择关系,层级关系等等。该篇介绍Spring 状态机 状态的配置。我们知道可以通过方法configure(Sta...

microservice
25分钟前
5
0
基于 HTML5 Canvas 实现的文字动画特效

前言 文字是网页中最基本的元素,一般我们在网页上都是展示的静态文字,但是就效果来说,还是比较枯燥的。文字淡入淡出的动画效果在项目中非常实用,如果有某些关键的文字,可以通过这种动态...

htdaydayup
32分钟前
4
0
2019 年 Java 开发者生态报告!

数据来源自国外的一个调查,在过去的几周,这份调查一共采访了6707名开发人员。数据来源:https://www.baeldung.com/java-in-2019。 1.JDK 版本使用情况 即使在今天 Java 13 都已经发布了,J...

SnailClimb
32分钟前
4
0
支撑微博亿级社交平台,小白也能玩转Redis集群(原理篇)

Redis作为一款性能优异的内存数据库,支撑着微博亿级社交平台,也成为很多互联网公司的标配。这里将以Redis Cluster集群为核心,基于最新的Redis5版本,从原理再到实战,玩转Redis集群 常见R...

分布式系统架构
40分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部