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  

即可以得到系统签名文件

  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值