Android(安卓)静默安装的几种方式
16lz
2021-01-24
Android 要想静默安装app,必须是系统应用或者具有Root权限,否则根本不可能实现静默安装
1.系统API 。不是静默安装
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(Uri.parse("file://" + apkFilePath), "application/vnd.android.package-archive");
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
2. 静默安装:利用ProcessBuilder
- /**
- * install slient
- *
- * @param filePath
- * @return 0 means normal, 1 means file not exist, 2 means other exception error
- */
- public static int installSilent(String filePath) {
- File file = new File(filePath);
- if (filePath == null || filePath.length() == 0 || file == null || file.length() <= 0 || !file.exists() || !file.isFile()) {
- return 1;
- }
- String[] args = { "pm", "install", "-r", filePath };
- ProcessBuilder processBuilder = new ProcessBuilder(args);
- Process process = null;
- BufferedReader successResult = null;
- BufferedReader errorResult = null;
- StringBuilder successMsg = new StringBuilder();
- StringBuilder errorMsg = new StringBuilder();
- int result;
- try {
- process = processBuilder.start();
- successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
- errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
- String s;
- while ((s = successResult.readLine()) != null) {
- successMsg.append(s);
- }
- while ((s = errorResult.readLine()) != null) {
- errorMsg.append(s);
- }
- } catch (IOException e) {
- e.printStackTrace();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- if (successResult != null) {
- successResult.close();
- }
- if (errorResult != null) {
- errorResult.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- if (process != null) {
- process.destroy();
- }
- }
- // TODO should add memory is not enough here
- if (successMsg.toString().contains("Success") || successMsg.toString().contains("success")) {
- result = 0;
- } else {
- result = 2;
- }
- Log.d("test-test", "successMsg:" + successMsg + ", ErrorMsg:" + errorMsg);
- return result;
- }
3. 静默安装:利用Runtime.getRuntime().exec()
[java] view plain copy
- private static final String TAG = "test-test";
- private static final int TIME_OUT = 60 * 1000;
- private static String[] SH_PATH = {
- "/system/bin/sh",
- "/system/xbin/sh",
- "/system/sbin/sh"
- };
- public static boolean executeInstallCommand(String filePath) {
- String command = “pm install -r ” + filePath;
- Process process = null;
- DataOutputStream os = null;
- StringBuilder successMsg = new StringBuilder();
- StringBuilder errorMsg = new StringBuilder();
- BufferedReader successResult = null;
- BufferedReader errorResult = null;
- try {
- process = runWithEnv(getSuPath(), null);
- if (process == null) {
- return false;
- }
- successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
- errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
- os = new DataOutputStream(process.getOutputStream());
- os.writeBytes(command + "\n");
- os.writeBytes("echo \"rc:\" $?\n");
- os.writeBytes("exit\n");
- os.flush();
- String s;
- while ((s = successResult.readLine()) != null) {
- successMsg.append(s);
- }
- while ((s = errorResult.readLine()) != null) {
- errorMsg.append(s);
- }
- // Handle a requested timeout, or just use waitFor() otherwise.
- if (TIME_OUT > 0) {
- long finish = System.currentTimeMillis() + TIME_OUT;
- while (true) {
- Thread.sleep(300);
- if (!isProcessAlive(process)) {
- break;
- }
- if (System.currentTimeMillis() > finish) {
- Log.w(TAG, "Process doesn't seem to stop on it's own, assuming it's hanging");
- // Note: 'finally' will call destroy(), but you might still see zombies.
- return true;
- }
- }
- } else {
- process.waitFor();
- }
- // In order to consider this a success, we require to things: a) a proper exit value, and ...
- if (process.exitValue() != 0) {
- return false;
- }
- return true;
- } catch (FileNotFoundException e) {
- Log.w(TAG, "Failed to run command, " + e.getMessage());
- return false;
- } catch (IOException e) {
- Log.w(TAG, "Failed to run command, " + e.getMessage());
- return false;
- } catch (InterruptedException e) {
- Log.w(TAG, "Failed to run command, " + e.getMessage());
- return false;
- } finally {
- if (os != null) {
- try {
- os.close();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- try {
- if (successResult != null) {
- successResult.close();
- }
- if (errorResult != null) {
- errorResult.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- if (process != null) {
- try {
- // Yes, this really is the way to check if the process is still running.
- process.exitValue();
- } catch (IllegalThreadStateException e) {
- process.destroy();
- }
- }
- }
- }
- private static Process runWithEnv(String command, String[] customEnv) throws IOException {
- List
envList = new ArrayList (); - Map
environment = System.getenv(); - if (environment != null) {
- for (Map.Entry
entry : environment.entrySet()) { - envList.add(entry.getKey() + "=" + entry.getValue());
- }
- }
- if (customEnv != null) {
- for (String value : customEnv) {
- envList.add(value);
- }
- }
- String[] arrayEnv = null;
- if (envList.size() > 0) {
- arrayEnv = new String[envList.size()];
- for (int i = 0; i < envList.size(); i++) {
- arrayEnv[i] = envList.get(i);
- }
- }
- Process process = Runtime.getRuntime().exec(command, arrayEnv);
- return process;
- }
- /**
- * Check whether a process is still alive. We use this as a naive way to implement timeouts.
- */
- private static boolean isProcessAlive(Process p) {
- try {
- p.exitValue();
- return false;
- } catch (IllegalThreadStateException e) {
- return true;
- }
- }
- /** Get the SU file path if it exist */
- private static String getSuPath() {
- for (String p : SH_PATH) {
- File sh = new File(p);
- if (sh.exists()) {
- return p;
- }
- }
- return "su";
- }
4. 静默安装:利用反射调用API-PackageManager.installPackage()
[java] view plain copy
- public static void installSilentWithReflection(Context context, String filePath) {
- try {
- PackageManager packageManager = context.getPackageManager();
- Method method = packageManager.getClass().getDeclaredMethod("installPackage",
- new Class[] {Uri.class, IPackageInstallObserver.class, int.class, String.class} );
- method.setAccessible(true);
- File apkFile = new File(filePath);
- Uri apkUri = Uri.fromFile(apkFile);
- method.invoke(packageManager, new Object[] {apkUri, new IPackageInstallObserver.Stub() {
- @Override
- public void packageInstalled(String pkgName, int resultCode) throws RemoteException {
- Log.d(TAG, "packageInstalled = " + pkgName + "; resultCode = " + resultCode) ;
- }
- }, Integer.valueOf(2), "com.ali.babasecurity.yunos"});
- //PackageManager.INSTALL_REPLACE_EXISTING = 2;
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
上面用到了反射调用,IPackageInstallObserver.class这个类在android sdk里面是没有的,您需要下载android_dependency.jar放到你工程的libs目录,这个jar提供了与PackageManager反射调用相关的类的定义。
注意:静默安装还需要在你的AndroidManifest.xml中添加权限声明。该权限默认赋予系统应用,第三方应用即使声明了,也拿不到该权限!
[html] view plain copy
/** * 执行具体的静默安装逻辑,需要手机ROOT。 * @param apkPath * 要安装的apk文件的路径 * @return 安装成功返回true,安装失败返回false。 */public boolean install(String apkPath) { boolean result = false; DataOutputStream dataOutputStream = null; BufferedReader errorStream = null; try { // 申请su权限 Process process = Runtime.getRuntime().exec("su"); dataOutputStream = new DataOutputStream(process.getOutputStream()); // 执行pm install命令 String command = "pm install -r " + apkPath + "\n"; dataOutputStream.write(command.getBytes(Charset.forName("utf-8"))); dataOutputStream.flush(); dataOutputStream.writeBytes("exit\n"); dataOutputStream.flush(); process.waitFor(); errorStream = new BufferedReader(new InputStreamReader(process.getErrorStream())); String msg = ""; String line; // 读取命令的执行结果 while ((line = errorStream.readLine()) != null) { msg += line; } Log.d("TAG", "install msg is " + msg); // 如果执行结果中包含Failure字样就认为是安装失败,否则就认为安装成功 if (!msg.contains("Failure")) { result = true; } } catch (Exception e) { Log.e("TAG", e.getMessage(), e); } finally { try { if (dataOutputStream != null) { dataOutputStream.close(); } if (errorStream != null) { errorStream.close(); } } catch (IOException e) { Log.e("TAG", e.getMessage(), e); } } return result;}
更多相关文章
- 自定义 Theme 改变 系统全局样式
- Android实现学生管理系统
- Android(安卓)权限管理 EasyPermissions使用记录
- android系统移植琐碎知识整理:
- 通过Camera进行拍照
- 超简单实现Android(安卓)屏幕截屏(需要系统级权限)
- android 调用系统打电话和发短,懒得记
- windows 使用QUME跑Android系统
- 如何搭建android环境---windows系统环境里。