Android:静默升级的分类与总结

要实现静默升级,首先要准备的

一般需要该应用是系统级别的应用,经过了平台下发的对应签名apk。

即:

1.内置到ROM,即APK包的安装位置是/system/app下。(制成一个系统刷机包)

2.使用APK的目标安装系统同样的签名。(系统签名)

当然不同平台的签名是不一样的,这个需要根据平台业务来具体确认,第三方Rom这样做也是处于保护系统安全的角度来考虑的。

一般静默升级的代码写法,包含两类

一类是该系统是开放了Root权限

二类是系统没有开放Root权限

开放了root权限的系统,支持静默升级的方式比较多

具有Root权限的静默升级,是用mp install -r 这样的方式实现的,类似adb推送的命令进行的安装

开放了Root权限的

开放了Root权限的静默升级就比较简单,但这个代码稍微要改一改,比较容易卡死


    //静默安装
    protected void excutesucmd(String currenttempfilepath) {

        Process process = null;
        OutputStream out = null;
        InputStream in = null;
        try {
            // 请求root
            process = Runtime.getRuntime().exec("sh");
            out = process.getOutputStream();
            // 调用安装
            out.write(("pm install -r " + currenttempfilepath + "\n").getBytes());
            in = process.getInputStream();
            int len = 0;
            byte[] bs = new byte[256];
            while (-1 != (len = in.read(bs))) {
                String state = new String(bs, 0, len);
                if (state.equals("success\n")) {
                    //静态注册自启动广播
                    Intent intent = new Intent();
                    //与清单文件的receiver的anction对应
                    intent.setAction("android.intent.action.PACKAGE_REPLACED");
                    // 发送广播
                    sendBroadcast(intent);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.flush();
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

没有开放Root权限的

根据安卓系统的6.0为界进行版本区分,可以用如下的几个写法

比如安卓系统6.0以上的机型静默安装可以这么写

public static boolean installPackage(Context context, InputStream in, String packageName) throws IOException {
    PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
    PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
    params.setAppPackageName(packageName);
    // set params
    int sessionId = packageInstaller.createSession(params);
    PackageInstaller.Session session = packageInstaller.openSession(sessionId);
    OutputStream out = session.openWrite(packageName, 0, -1);
    byte[] buffer = new byte[65536];
    int c;
    while ((c = in.read(buffer)) != -1) {
       out.write(buffer, 0, c);
   }
    session.fsync(out);
    in.close();
    out.close();
    session.commit(createIntentSender(context, sessionId));
    return true;
}

    private static IntentSender createIntentSender(Context context, int sessionId) {
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context,sessionId,new Intent(Intent.ACTION_PACKAGE_ADDED),PendingIntent.FLAG_UPDATE_CURRENT);
        return pendingIntent.getIntentSender();
}

静默卸载这么写

String appPackage = "net.owlsmart.tv";
Intent intent = new Intent(getActivity(), getActivity().getClass());
PendingIntent sender = PendingIntent.getActivity(getActivity(), 0, intent, 0);
PackageInstaller mPackageInstaller = getActivity().getPackageManager().getPackageInstaller();
mPackageInstaller.uninstall(appPackage, sender.getIntentSender());

参数的转化与补充知识

String --> InputStream
ByteArrayInputStream stream = new ByteArrayInputStream(str.getBytes());
InputStream --> String
String inputStream2String(InputStream is){
   BufferedReader in = new BufferedReader(new InputStreamReader(is));
   StringBuffer buffer = new StringBuffer();
   String line = "";
   while ((line = in.readLine()) != null){
     buffer.append(line);
   }
   return buffer.toString();
}
 
File --> InputStream
InputStream in = new FileInputStream(file);
 
InputStream --> File
public void inputstreamtofile(InputStream ins,File file){
   OutputStream os = new FileOutputStream(file);
   int bytesRead = 0;
   byte[] buffer = new byte[8192];
   while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
      os.write(buffer, 0, bytesRead);
   }
   os.close();
   ins.close();
}

安卓6.0及以下的这么写

低版本Android 6.0以下,大部分app的静默安装都是通过 移植系统源码中的相关AIDL 文件,进行调用pm里面的android方法:

普通情况下肯定是调用不到的。在源码\frameworks\base\core\java\android\content\pm目录下PackageManager.java,应该发现在注释行里有加上@hide声明。调用的安装下载接口如下:

public abstract void installPackage(Uri packageURI,IPackageInstallObserver observer, int flags,String installerPackageName);
public abstract void deletePackage(String packageName,IPackageDeleteObserver observer, int flags);

最简单的就是直接拷贝4个文件即可:

PackageManager.java

IPackageDeleteObserver.aidl

IPackagerInstallObserver.aidl

IPackageMoveObserver.aidl

然后把PackageManager.java中报的异常的接口都注释掉即可,然后直接调用pm里面的方法。

/*** 静默安装* */
public static void autoInstallApk(Context context, String fileName,String packageName, String APPName) {
       Log.d(TAG, “jing mo an zhuang:” + packageName + “,fileName:” + fileName);File file = new File(fileName);
       int installFlags = 0;
       if (!file.exists())
                return;
           installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
       if (hasSdcard()) {
           installFlags |= PackageManager.INSTALL_EXTERNAL;
       }
       PackageManager pm = context.getPackageManager();
       try {
            IPackageInstallObserver observer = new MyPakcageInstallObserver(context, APPName, appId, fileName,packageName,type_name);
            Log.i(TAG, “########installFlags:” + installFlags+”packagename:”+packageName);
            pm.installPackage(Uri.fromFile(file), observer, installFlags,packageName);
           } catch (Exception e) {
                

          }
}

静默安装实现的接口,这样写

class MyPakcageInstallObserver extends IPackageInstallObserver.Stub {
Context cxt;
String appName;
String filename;
String pkname;

 public MyPakcageInstallObserver(Context c, String appName, String filename, String packagename) {
  this.cxt = c;
  this.appName = appName;
  this.filename = filename;
  this.pkname = packagename;
}

    @Override
    public void packageInstalled(String packageName, int returnCode) {
        Log.i(TAG, “returnCode = ” + returnCode);// 返回1代表安装成功
        if (returnCode == 1) {
             //TODO
        }
        Intent it = new Intent();
        it.setAction(CustomAction.INSTALL_ACTION);
        it.putExtra(“install_returnCode”, returnCode);
        it.putExtra(“install_packageName”, packageName);
        it.putExtra(“install_appName”, appName); cxt.sendBroadcast(it);
    }
}

apk卸载

@Override
public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
    try {
        mPM.deletePackageAsUser(packageName, observer, UserHandle.myUserId(), flags);
    } catch (RemoteException e) {
    // Should never happen!
  }
}

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wenlong Yang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值