Android 静默安装的几种方式

 Android 要想静默安装app,必须是系统应用或者具有Root权限,否则根本不可能实现静默安装

1.系统API 。不是静默安装

  1. Intent intent = new Intent(Intent.ACTION_VIEW);  
  2. intent.setDataAndType(Uri.parse("file://" + apkFilePath), "application/vnd.android.package-archive");  
  3. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  4. mContext.startActivity(intent);  

 

2. 静默安装:利用ProcessBuilder

  1. /** 
  2.  * install slient 
  3.  * 
  4.  * @param filePath 
  5.  * @return 0 means normal, 1 means file not exist, 2 means other exception error 
  6.  */  
  7. public static int installSilent(String filePath) {  
  8.     File file = new File(filePath);  
  9.     if (filePath == null || filePath.length() == 0 || file == null || file.length() <= 0 || !file.exists() || !file.isFile()) {  
  10.         return 1;  
  11.     }  
  12.   
  13.     String[] args = { "pm", "install", "-r", filePath };  
  14.     ProcessBuilder processBuilder = new ProcessBuilder(args);  
  15.     Process process = null;  
  16.     BufferedReader successResult = null;  
  17.     BufferedReader errorResult = null;  
  18.     StringBuilder successMsg = new StringBuilder();  
  19.     StringBuilder errorMsg = new StringBuilder();  
  20.     int result;  
  21.     try {  
  22.         process = processBuilder.start();  
  23.         successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));  
  24.         errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));  
  25.         String s;  
  26.         while ((s = successResult.readLine()) != null) {  
  27.             successMsg.append(s);  
  28.         }  
  29.         while ((s = errorResult.readLine()) != null) {  
  30.             errorMsg.append(s);  
  31.         }  
  32.     } catch (IOException e) {  
  33.         e.printStackTrace();  
  34.     } catch (Exception e) {  
  35.         e.printStackTrace();  
  36.     } finally {  
  37.         try {  
  38.             if (successResult != null) {  
  39.                 successResult.close();  
  40.             }  
  41.             if (errorResult != null) {  
  42.                 errorResult.close();  
  43.             }  
  44.         } catch (IOException e) {  
  45.             e.printStackTrace();  
  46.         }  
  47.         if (process != null) {  
  48.             process.destroy();  
  49.         }  
  50.     }  
  51.   
  52.     // TODO should add memory is not enough here  
  53.     if (successMsg.toString().contains("Success") || successMsg.toString().contains("success")) {  
  54.         result = 0;  
  55.     } else {  
  56.         result = 2;  
  57.     }  
  58.     Log.d("test-test", "successMsg:" + successMsg + ", ErrorMsg:" + errorMsg);  
  59.     return result;  
  60. }  

3. 静默安装:利用Runtime.getRuntime().exec()

 

 

[java] view plain copy  

  1. private static final String TAG = "test-test";  
  2.   
  3. private static final int TIME_OUT = 60 * 1000;  
  4.   
  5. private static String[] SH_PATH = {  
  6.         "/system/bin/sh",  
  7.         "/system/xbin/sh",  
  8.         "/system/sbin/sh"  
  9. };  
  10.   
  11. public static boolean executeInstallCommand(String filePath) {  
  12.     String command = “pm install -r ” + filePath;  
  13.     Process process = null;  
  14.     DataOutputStream os = null;  
  15.     StringBuilder successMsg = new StringBuilder();  
  16.     StringBuilder errorMsg = new StringBuilder();  
  17.     BufferedReader successResult = null;  
  18.     BufferedReader errorResult = null;  
  19.     try {  
  20.         process = runWithEnv(getSuPath(), null);  
  21.         if (process == null) {  
  22.             return false;  
  23.         }  
  24.   
  25.         successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));  
  26.         errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));  
  27.   
  28.         os = new DataOutputStream(process.getOutputStream());  
  29.         os.writeBytes(command + "\n");  
  30.         os.writeBytes("echo \"rc:\" $?\n");  
  31.         os.writeBytes("exit\n");  
  32.         os.flush();  
  33.   
  34.         String s;  
  35.         while ((s = successResult.readLine()) != null) {  
  36.             successMsg.append(s);  
  37.         }  
  38.         while ((s = errorResult.readLine()) != null) {  
  39.             errorMsg.append(s);  
  40.         }  
  41.   
  42.         // Handle a requested timeout, or just use waitFor() otherwise.  
  43.         if (TIME_OUT > 0) {  
  44.             long finish = System.currentTimeMillis() + TIME_OUT;  
  45.             while (true) {  
  46.                 Thread.sleep(300);  
  47.                 if (!isProcessAlive(process)) {  
  48.                     break;  
  49.                 }  
  50.   
  51.                 if (System.currentTimeMillis() > finish) {  
  52.                     Log.w(TAG, "Process doesn't seem to stop on it's own, assuming it's hanging");  
  53.                     // Note: 'finally' will call destroy(), but you might still see zombies.  
  54.                     return true;  
  55.                 }  
  56.             }  
  57.         } else {  
  58.             process.waitFor();  
  59.         }  
  60.   
  61.         // In order to consider this a success, we require to things: a) a proper exit value, and ...  
  62.         if (process.exitValue() != 0) {  
  63.             return false;  
  64.         }  
  65.   
  66.         return true;  
  67.   
  68.     } catch (FileNotFoundException e) {  
  69.         Log.w(TAG, "Failed to run command, " + e.getMessage());  
  70.         return false;  
  71.     } catch (IOException e) {  
  72.         Log.w(TAG, "Failed to run command, " + e.getMessage());  
  73.         return false;  
  74.     } catch (InterruptedException e) {  
  75.         Log.w(TAG, "Failed to run command, " + e.getMessage());  
  76.         return false;  
  77.     } finally {  
  78.         if (os != null) {  
  79.             try {  
  80.                 os.close();  
  81.             } catch (IOException e) {  
  82.                 throw new RuntimeException(e);  
  83.             }  
  84.         }  
  85.   
  86.         try {  
  87.             if (successResult != null) {  
  88.                 successResult.close();  
  89.             }  
  90.             if (errorResult != null) {  
  91.                 errorResult.close();  
  92.             }  
  93.         } catch (IOException e) {  
  94.             e.printStackTrace();  
  95.         }  
  96.   
  97.         if (process != null) {  
  98.             try {  
  99.                 // Yes, this really is the way to check if the process is still running.  
  100.                 process.exitValue();  
  101.             } catch (IllegalThreadStateException e) {  
  102.                 process.destroy();  
  103.             }  
  104.         }  
  105.     }  
  106. }  
  107.   
  108. private static Process runWithEnv(String command, String[] customEnv) throws IOException {  
  109.     List envList = new ArrayList();  
  110.     Map environment = System.getenv();  
  111.     if (environment != null) {  
  112.         for (Map.Entry entry : environment.entrySet()) {  
  113.             envList.add(entry.getKey() + "=" + entry.getValue());  
  114.         }  
  115.     }  
  116.   
  117.     if (customEnv != null) {  
  118.         for (String value : customEnv) {  
  119.             envList.add(value);  
  120.         }  
  121.     }  
  122.   
  123.     String[] arrayEnv = null;  
  124.     if (envList.size() > 0) {  
  125.         arrayEnv = new String[envList.size()];  
  126.         for (int i = 0; i < envList.size(); i++) {  
  127.             arrayEnv[i] = envList.get(i);  
  128.         }  
  129.     }  
  130.   
  131.     Process process = Runtime.getRuntime().exec(command, arrayEnv);  
  132.     return process;  
  133. }  
  134.   
  135. /** 
  136.  * Check whether a process is still alive. We use this as a naive way to implement timeouts. 
  137.  */  
  138. private static boolean isProcessAlive(Process p) {  
  139.     try {  
  140.         p.exitValue();  
  141.         return false;  
  142.     } catch (IllegalThreadStateException e) {  
  143.         return true;  
  144.     }  
  145. }  
  146.   
  147. /** Get the SU file path if it exist */  
  148. private static String getSuPath() {  
  149.     for (String p : SH_PATH) {  
  150.         File sh = new File(p);  
  151.         if (sh.exists()) {  
  152.             return p;  
  153.         }  
  154.     }  
  155.     return "su";  
  156. }  

4. 静默安装:利用反射调用API-PackageManager.installPackage()

 

 

[java] view plain copy  

  1. public static void installSilentWithReflection(Context context, String filePath) {  
  2.     try {  
  3.         PackageManager packageManager = context.getPackageManager();  
  4.         Method method = packageManager.getClass().getDeclaredMethod("installPackage",  
  5.                 new Class[] {Uri.class, IPackageInstallObserver.class, int.class, String.class} );  
  6.         method.setAccessible(true);  
  7.         File apkFile = new File(filePath);  
  8.         Uri apkUri = Uri.fromFile(apkFile);  
  9.   
  10.         method.invoke(packageManager, new Object[] {apkUri, new IPackageInstallObserver.Stub() {  
  11.             @Override  
  12.             public void packageInstalled(String pkgName, int resultCode) throws RemoteException {  
  13.                 Log.d(TAG, "packageInstalled = " + pkgName + "; resultCode = " + resultCode) ;  
  14.             }  
  15.         }, Integer.valueOf(2), "com.ali.babasecurity.yunos"});  
  16.         //PackageManager.INSTALL_REPLACE_EXISTING = 2;  
  17.     } catch (NoSuchMethodException e) {  
  18.         e.printStackTrace();  
  19.     } catch (Exception e) {  
  20.         e.printStackTrace();  
  21.     }  
  22. }  

上面用到了反射调用,IPackageInstallObserver.class这个类在android sdk里面是没有的,您需要下载android_dependency.jar放到你工程的libs目录,这个jar提供了与PackageManager反射调用相关的类的定义。

 

注意:静默安装还需要在你的AndroidManifest.xml中添加权限声明。该权限默认赋予系统应用,第三方应用即使声明了,也拿不到该权限!

 

 

[html] view plain copy  

  1.   
  2.   
/**
 * 执行具体的静默安装逻辑,需要手机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;
}

你可能感兴趣的:(Android 静默安装的几种方式)