文档章节

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

shzwork
 shzwork
发布于 07/05 18:25
字数 2275
阅读 10
收藏 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
博文 800
码字总数 10675
作品 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

没有更多内容

加载失败,请刷新页面

加载更多

教你玩转Linux—添加批量用户

添加和删除用户对每位Linux系统管理员都是轻而易举的事,比较棘手的是如果要添加几十个、上百个甚至上千个用户时,我们不太可能还使用useradd一个一个地添加,必然要找一种简便的创建大量用户...

xiangyunyan
31分钟前
6
0
返回提示信息,如:xxx创建成功!

【服务端】在输出的方法块中,加入要输出的字段(qcm_batch_id) QCMUserType.cs: public struct QCM_Custom_Create_Batch_Out_Tag { public BASCoreType.Cmn_Out_T......

_Somuns
31分钟前
6
0
Aliyun Serverless VSCode Extension v1.12.0 发布

Aliyun Serverless VSCode Extension 是阿里云 Serverless 产品 函数计算 Function Compute 的 VSCode 插件,该插件结合了函数计算 Fun 工具以及函数计算 SDK ,是一款 VSCode 图形化开发调试...

阿里云官方博客
31分钟前
6
0
程序员如何培养解决复杂问题的能力?

今天在上网时候,突然看到了这篇文章,感觉非常的适合现在的自己去思考下,可能也适用在座的读者。程序员不仅仅是敲代码,更是一个复合能力的结合体,也不仅仅停留在技术和代码阶段。你想要成...

哥本哈根的小哥
35分钟前
8
0
市场变化驱动产品思维升级

宜信科技中心财富管理产品部负责人Bob,与大家一起聊聊个性化推荐产品功能的设计和B端产品的功能策划方式。 拓展阅读:回归架构本质,重新理解微服务 智慧金融时代,大数据和AI如何为业务赋能...

宜信技术学院
35分钟前
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部