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中配置:

package="xxx.xxx.xxxx"

android:sharedUserId="android.uid.system">

在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

即可以得到系统签名文件


美工培训班一般多少钱?2024最新价目表+避坑指南
泰拉瑞亚黑暗之魂怎么刷-泰拉瑞亚黑暗之魂获取途径攻略