Android采用pm实现静默安装(降级安装)的解决方案
最近在做一个apk分析器,里面可以解析系统中所有安装app的信息,并提供组内开发的apk文件下载、静默安装(包括降级安装),其中在降级安装中难度较大,在Android4.4与Android 8的解决方案不同,其他版本没有做测试。在此之前,打算聊聊adb的安装方式
目前暂时支持已经签过系统签名文件的apk,非系统签名暂时不支持。
##一、adb安装apk
adb安装apk常用命令如下:
adb install G:\demo.apk
即install后面接包在电脑上的路径,这里要确保已经通过adb连接到设备,常用以下命令连接,确保电脑与设备处于同一个局域网:
adb connect 设备ip
如果需要替换原来的应用,上面的安装命令是行不通的,需要加上“-r”,即替换原来的应用:
adb install -r G:\demo.apk
那如果是降级安装呢?再加“-d”:
adb install -r -d G:\demo.apk
这里的“r”指的是“replace”,替换原来的应用;“-d”指的是“downgrade”,降级安装
这不是成了吗?不对,这是通过adb命令,在Android应用中无法使用该命令,那么该如何解决呢?这里要引出另一个概念“pm”
##二、pm安装apk
“pm” 是指 “packageManager”,Android自带的PackageInstaller是通过pm来执行具体的安装工作,具体流程这里就不做分析了。我们来看如何直接通过pm来安装apk,首先进入shell模式,然后就可以使用pm命令:
adb shell
pm install /data/data/demo.apk
这里的apk路径是在设备中的路径,同理如果要实现降级安装:
pm install -r -d /data/data/demo.apk
哈哈,是不是感觉在Android应用端实现该命令就很简单了?如下:
String cmd = "pm install -r -d /data/data/demo.apk"
Runtime run = Runtime.getRuntime();
Process process = run.exec(cmd);
然后就failure了~~
该命令不是每一个应用都可以执行的,需要系统签名,将应用声明为系统应用。在Androidmanifest中配置:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="xxx.xxx.xxxx" android:sharedUserId="android.uid.system"><uses-permission android:name="android.permission.INSTALL_PACKAGES" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
</manifest>
在run一次,ok,在Android4.4以及之前的版本没问题,但是在更高的版本,例如Android 7 就不行了,这里需要稍微修改一下:
pm install -r -d -i packageName --user 0 /data/data/demo.apk
这里的packageName是指调用这行命令的应用的包名
需要注意的是,runtime执行命令行会阻塞线程,因此需要在子线程中执行
那么,我们应该如何判断是否安装成功呢?很简单了,通过runtime执行返回的process就可以拿到输出的结果,完整代码如下:
public void install(File apkFile) {String cmd = "";if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {cmd = "pm install -r -d " + apkFile.getAbsolutePath();} else {cmd = "pm install -r -d -i packageName --user 0 " + apkFile.getAbsolutePath();}Runtime runtime = Runtime.getRuntime();try {Process process = runtime.exec(cmd);InputStream errorInput = process.getErrorStream();InputStream inputStream = process.getInputStream();BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));String error = "";String result = "";String line = "";while ((line = bufferedReader.readLine()) != null) {result += line;}bufferedReader = new BufferedReader(new InputStreamReader(errorInput));while ((line = bufferedReader.readLine()) != null) {error += line;}if(result.equals("Success")){Log.i(TAG, "install: Success");}else{Log.i(TAG, "install: error"+error);}} catch (IOException e) {e.printStackTrace();}}
##三、总结
该方案需要获取系统权限,进行系统签名。当然,大家也可以在模拟器上试一试,拿到模拟器系统版本对应的源码,找到这3个文件
SignApk.jar 目录:/out/host/linux-x86/framework/signapk.jar
platform.x509.pem 目录:/build/target/product/security/platform.x509.pem
platform.pk8 目录:/build/target/product/security/platform.pk8
将这三个文件copy到同一个目录下,在该目录下执行:
java -jar SignApk.jar platform.x509.pem platform.pk8 旧的apk.apk 生成的apk.apk
即可以得到系统签名文件
Android采用pm实现静默安装(降级安装)的解决方案相关推荐
- Android P 9 实现静默安装静默卸载
大家有没有发现现在的手机 只要是在自家应用市场下载安装的应用都不会弹出安装界面直接就装好了,今天我们就来实现这种功能 之前在网上查了资料好多都是很早之前的版本了 通过命令 调用系统接口 这些我都去验证 ...
- Android使用Bugly实现静默安装/自动安装app
前言 针对门禁.闸机.广告机等无人值守的Android终端app,如何自动升级一直是一个比较麻烦的事情:现在给出一个相对比较成熟的方案供大家参考: 以前你的升级方案可能是这样的: 集成bugly,发布 ...
- Android系统Root与静默安装
Android系统Root与静默安装 静默安装,指的是安装时无需任何用户干预,直接按默认设置安装应用.因为,它的无需用户干预,很多情况下变成了用户压根不知道,应用不知不觉就安装上了.是在推广上极为流氓 ...
- Android 8.1实现静默安装、卸载功能
网上有很多相关的资料,也有很多不同的方法去实现,本文是我选取的一个方法,已实现静默安装和卸载功能,本文主要目的记录一下关键点. 主要是用PackageManagerService.java里面的 in ...
- Android 安装应用的两种方式--外部应用安装器安装和静默安装(系统应用)
1.调用外部安装器安装 /*** 外部应用安装器安装apk(原生接口)* @param context* @param path apk的路径* @return*/public static bool ...
- Android PackageManagerService 总结(一)应用市场下载安装apk流程
前言: 本篇文章是对系统包安装流程的总结,基于Android12 上 com.android.packageinstaller 源码的分析,第三方应用商城(华为商城,小米商城,应用宝,豌豆荚,酷安等) ...
- 使用Android Accessibility实现免Root自动批量安装功能
对于国内Android设备,应用的自动批量安装/更新一直是一个痛点,在之前,第三方应用商店通常要求设备Root,然后调用系统的PackageManagerService命令行来实现后台安装.最近,豌豆 ...
- Android Bug分析系列:第三方平台安装app启动后,home键回到桌面后点击app启动时会再次启动入口类bug的原因剖析...
前言 前些天,测试MM发现了一个比较奇怪的bug. 具体表现是: 1.将app包通过电脑QQ传送到手机QQ上面,点击安装,安装后选择打开app (此间的应用逻辑应该是要触发 [闪屏页Activity] ...
- 小米电视2+android,真实体验小米电视2方便安装第三方软件
智能电视的普及让我们的客厅变得丰富多彩,2014年推出的小米电视2凭借强劲的硬件以及优秀的体验成为目前市面最为火热的智能电视,基于Android深度定制的MIUI TV在扩展性方面同样表现不俗,通过第 ...
最新文章
- 编译器架构Compiler Architecture(上)
- Nginx源码分析--数据对齐posix_memalign和memalign函数
- 中英文最大AI模型世界纪录产生,大模型竞赛新阶段来了
- python爬虫实战-python爬虫实战一:分析豆瓣中最新电影的影评
- 数据结构与算法学习-开篇
- 6.Python标准库_子进程 (subprocess包)
- ASP.NET 2.0:如何让DropDownList同时拥有数据来源项目与自订项目 (转自章立民CnBlogs)...
- VS Tools for AI全攻略
- 前端学习(1958)vue之电商管理系统电商系统之参数管理
- 小程序统一服务消息_微信团队发布小程序模板消息能力调整通知:小程序订阅消息接口正式上线...
- mac下nvm_【干货分享】Mac最全用法指导,学不会学费全退!!!(反正我也没收你们学费)...
- 中国最让人脸红的节目:爆火14年的湿身诱惑,为何还没被叫停?
- mac bochs 调试linux,Mac OS X下编译安装带debugger的bochs
- qml 时间控件_Qt6官方最新消息:桌面样式Qt quick Controls 2支持大多控件,委托更少,运行更流畅...
- vs2015 mysql edmx_VS2015+MySql EF的配置问题
- git获取特定的commit
- 2018校招笔试真题汇总
- 函数 单片机glint_为什么用单片机写的自锁开关程序,把开关放到P0.0脚后LED就开始闪烁?...
- 色温,色阶,色调,色调
- Word2Vec中的gensim报错from gensim.models.word2vec import Vocab报错问题
热门文章
- sqlalchemy exists 子查询_学好ORM框架SQLAlchemy面试必问
- 网闸与防火墙的区别_网关和网闸、防火墙的区别?
- python中sys用法_python中os和sys模块的区别与常用方法总结
- Angular学习个人遇见的问题分享
- E0144“const char *“ 类型的值不能用于初始化 “char *“ 类型的实体
- jsr223 java_JSR223 Java使用脚本引擎动态修改业务逻辑
- oracle 一致性读数量,ORACLE 一致性读原理记录
- 关于邮件服务器的原理
- 【阿里云总监课第四期】时髦的云原生应用怎么写?
- 自定义控件详解(六):Paint 画笔MaskFilter过滤