App静默安装(升级)和卸载

Posted Ang_qq_252390816

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了App静默安装(升级)和卸载相关的知识,希望对你有一定的参考价值。

安装或升级

普通安装或升级

调用系统API,通过Intent启动com.android.packageinstaller(PackageInstaller.apk)系统app进行安装或升级;需要用户同意,并且有前台界面;

查看PackageInstaller在系统的存放位置:adb shell pm list packages -f com.android.packageinstaller或者adb shell pm list package -f | grep package(通过grep 过滤)

public void normal(String apkFilePath) 
    Intent intent = new Intent(Intent.ACTION_VIEW);
    File uriFile = new File(apkFilePath);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) 
        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        Uri contentUri =         FileProvider.getUriForFile(MyApplication.getApplication().getApplicationContext(),         BuildConfig.APPLICATION_ID + ".fileprovider", uriFile);
        intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
     else 
        intent.setDataAndType(Uri.fromFile(uriFile), "application/vnd.android.package-archive");
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    
            if(MyApplication.getApplication().getApplicationContext().getPackageManager().queryIntentAc    tivities(intent, 0).size() > 0) 
    MyApplication.getApplication().getApplicationContext().startActivity(intent);

    

静默升级

这里说的安装或升级可以是app自己对自己升级,也可以对其他app 升级或安装;静默升级或者安装,不同Android设备支持的方法不一样,需要自己测试,但是方法就这么几种;

第一种方法:利用ProcessBuilder

应用程序运行命令获取 Root权限,Android系统必须已经Root(获得ROOT权限)

如果没有没有获取root权限,会出现异常:SecurityException: Neither user 10058 nor current process has android.permission.INSTALL_PACKAGES.

条件:需要root权限

public String installSilently(String path) 
    Log.d(TAG, "path" + path);
    // 通过命令行来安装APK
    String[] args = "pm", "install", "-r", path;
    String result = "";
    // 创建一个操作系统进程并执行命令行操作
    ProcessBuilder processBuilder = new ProcessBuilder(args);
    Process process = null;
    InputStream errIs = null;
    InputStream inIs = null;
    try 
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int read = -1;
        process = processBuilder.start();
        errIs = process.getErrorStream();
        while ((read = errIs.read()) != -1) 
            baos.write(read);
        
        baos.write('\\n');
        inIs = process.getInputStream();
        while ((read = inIs.read()) != -1) 
             baos.write(read);
        
        byte[] data = baos.toByteArray();
        result = new String(data);
        Log.d(TAG, "result" + result);
     catch (IOException e) 
        e.printStackTrace();
 catch (Exception e) 
    e.printStackTrace();
 finally 
    try 
        if (errIs != null) 
            errIs.close();
        
        if (inIs != null) 
            inIs.close();
        
     catch (IOException e) 
        e.printStackTrace();
    
    if (process != null) 
        process.destroy();
    

return result;

第二种方法:

利用Runtime.getRuntime().exec() 执行pm 安装命令

条件:需要系统已经root

public boolean silenceInstall(String path) 
    // 进行资源的转移 将assets下的文件转移到可读写文件目录下
    File file = new File(path);
    boolean result = false;
    Process process = null;
    OutputStream out = null;
    Log.i(TAG, "file.getPath():" + file.getPath());
    if (file.exists()) 
        System.out.println(file.getPath() + "==");
        try 
        process = Runtime.getRuntime().exec("su");
        out = process.getOutputStream();
        DataOutputStream dataOutputStream = new DataOutputStream(out);
        // 获取文件所有权限
        dataOutputStream.writeBytes("chmod 777 " + file.getPath()
        + "\\n");
        // 进行静默安装命令
        dataOutputStream
        .writeBytes("LD_LIBRARY_PATH=/vendor/lib:/system/lib pm install -r "
        + file.getPath());
        dataOutputStream.flush();
        // 关闭流操作
        dataOutputStream.close();
        out.close();
        int value = process.waitFor();
        // 代表成功
        if (value == 0) 
            Log.i(TAG, "安装成功!");
            result = true;
         // 失败
         else if (value == 1) 
            Log.i(TAG, "安装失败!");
            result = false;
            // 未知情况
         else 
            Log.i(TAG, "未知情况!");
            result = false;
        
       catch (IOException e) 
         e.printStackTrace();
       catch (InterruptedException e) 
        e.printStackTrace();
      
      if (!result) 
        Log.i(TAG, "root权限获取失败,将进行普通安装");
        normal(path);
        result = true;
      
    
    return result;

第三种方法:

利用反射调用PackageManager.installPackage()

条件:需要app有系统权限,即清单文件AndroidManifest.xml中manifest标签需要添加android:sharedUserId="android.uid.system"属性;然后进行系统签名;有关系统签名需要Android设备厂家提供对用的系统版本的系统签名文件;有关系统签名的详细介绍在文章末尾;

申请权限 <uses-permission android:name="android.permission.INSTALL_PACKAGES" />

public static final int INSTALL_REPLACE_EXISTING = 0x00000002; //如果已经存在的包使用这个flag,例如升级

public static final int INSTALL_ALL_USERS = 0x00000040; //如果系统中没有安装过使用这个flag,例如安装其他的APP

public void installApp(String path) 
    File file = new File(path);
    PackageManager pm = MyApplication.getApplication().getPackageManager();
    Class<?>[] types = new Class[]Uri.class, IPackageInstallObserver.class, int.class,     String.class;
    try 
        Method method = pm.getClass().getMethod("installPackage", types);
        // method.invoke(pm,Uri.fromFile(file), new PackageInstallObserver(), INSTALL_ALL_USERS, null);
        method.invoke(pm, Uri.fromFile(file), new PackageInstallObserver(),         INSTALL_REPLACE_EXISTING, null);
      catch (Exception e) 
        Log.d("安装失败", "");
        e.printStackTrace();
    

静默卸载APP

public void deleteApp(String appPackage) 
    PackageManager pm = MyApplication.getApplication().getPackageManager();
    try 
        Class<?>[] uninstalltypes = new Class[] String.class,         IPackageDeleteObserver.class, int.class;
        Method uninstallmethod = pm.getClass().getMethod("deletePackage", uninstalltypes);
        uninstallmethod.invoke(pm, appPackage, new PackageDeletedObserver(), 0);
     catch (NoSuchMethodException e) 
       e.printStackTrace();
     catch (IllegalAccessException e) 
        e.printStackTrace();
     catch (InvocationTargetException e) 
        e.printStackTrace();
    


private OnPackagedObserver onInstallOrDeleteObserver = new OnPackagedObserver() 
    @Override
    public void onPackageInstalled(String packageName, int returnCode) 
        Log.d("test", "onPackageInstalled");
    

    @Override
    public void onPackageDeleted(String packageName, int returnCode) 
        Log.d("test", "onPackageDeleted");
    
;
public class PackageInstallObserver extends IPackageInstallObserver.Stub 
    @Override
    public void packageInstalled(String s, int i) throws RemoteException 
        if (onInstallOrDeleteObserver != null) 
            onInstallOrDeleteObserver.onPackageInstalled(s, i);
        
    
public class PackageDeletedObserver extends IPackageDeleteObserver.Stub
    @Override
    public void packageDeleted(String s, int i) throws RemoteException 
        if (onInstallOrDeleteObserver != null) 
            onInstallOrDeleteObserver.onPackageDeleted(s, i);
        
    
public interface OnPackagedObserver 
    void onPackageInstalled(String packageName, int returnCode);
    void onPackageDeleted(String packageName, int returnCode);


注意这个是系统提供的API接口,默认是隐藏的;所以在使用的时候,需要自己创建对应的api接口,这样才能通过编译;我这里已经编译成jar包了,需要的可以下载使用;

App 卸载

普通卸载

//传统卸载应用,即系统卸载app的API,需要用户同意,并且有前台界面;

String packageName = getPackageName();
Uri packageURI = Uri.parse("package:" + packageName);
//或者Uri packageURI = Uri.fromParts("package", "com.glapde", null);
Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI);
startActivity(uninstallIntent);

 

静默卸载

利用ProcessBuilder或者Runtime.getRuntime().exec() 执行一条pm卸载命令目前还没尝试成功过;但是通过PackageManager.deletePackage可以卸载成功,具体应用上面已经提供;

系统签名

1,获取系统签名文件,一般需要Android设备厂家提供;

2,执行命令

java -jar signapk.jar platform.x509.pem platform.pk8 old.apk   new.apk

如果自己Android系统源码的话,platform.x509.pem platform.pk8这两个签名文件可以找到的;

以上是关于App静默安装(升级)和卸载的主要内容,如果未能解决你的问题,请参考以下文章

android如何实现静默安装哦

Android静默安装与静默卸载(系统应用)

如何使用 WiX 和 MSI 进行静默安装和卸载?

如何app自动升级 静默安装 android

android在root权限下实现apk的静默卸载,静默安装,重启

静默安装卸载 ORACLE