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设备厂家提供对用的系统版本的系统签名文件;有关系统签名的详细介绍在文章末尾;

申请权限

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,执行命令

你可能感兴趣的:(Tool)