android如何在定制系统上实现静默安装

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android如何在定制系统上实现静默安装相关的知识,希望对你有一定的参考价值。

目前的要求是在ACER-Z120手机上(该手机应该是基于android 4.1.1的定制系统)实现软件的静默安装。就是我要写一个控制软件来下载被控制软件,下载完了静默安装被控制软件。我的控制软件要执行 pm install 命令是不是要先得到该操作系统的platform..pk8 platform.x509.pem signapk.jar三个文件,用命令来对我的控制软件进行签名,在安装进入该手机?整个过程这样对吗?我现在把签名好的apk文件放到与adb.exe同一目录下,在cmd下执行adb install signed.apk(我要装到真机里)会报错,Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES],能包我分析下吗?

电脑通过usb调试模式控制静默安装是可以的。
手机自己控制静默安装需要获得ROOT权限。追问

感谢您的回答,我问一下,只能root吗?目前的要求是手机不能root。有办法实现吗?

追答

只能ROOT了。

追问

那先不管静默安装,我的控制软件用厂商提供的platform.pk8 platform.x509.pem signapk.jar三个文件签好名,为什么无法安装进手机?

参考技术A 不懂啊,不好意思啊

Android 如何静默安装app

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

本文假设你的app是系统应用(有系统签名,或者放在系统/system/app 或 /system/priv-app分区),则可以进行以下安装:

注意:静默安装还需要在你的AndroidManifest.xml中添加权限声明。该权限默认赋予系统应用,第三方应用即使声明了,也拿不到该权限! [html] view plain copy
  1. <!-- 静默安装 -->  
  2. <uses-permission android:name="android.permission.INSTALL_PACKAGES" /> 

1. 有提示的安装(所有第三方应用都可以)

[java] view plain copy
  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);  
这是调用系统的AppInstaller,提示用户安装升级。

2. 静默安装:利用ProcessBuilder

[java] view plain copy
  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<String> envList = new ArrayList<String>();  
  110.     Map<String, String> environment = System.getenv();  
  111.     if (environment != null)   
  112.         for (Map.Entry<String, String> 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.classint.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反射调用相关的类的定义。

以上是关于android如何在定制系统上实现静默安装的主要内容,如果未能解决你的问题,请参考以下文章

Android构建系统级应用静默授权,静默安装

Android构建系统级应用静默授权,静默安装

如何实现android静默安装

android如何实现静默安装哦

Android 如何静默安装app

Android APK 签名打包原理分析静默安装的实现方案