本文主要介绍程序如何利用root权限静默安装(卸载)APK,如何自动选择普通安装(卸载)还是静默安装(卸载)。
1、root权限静默安装(卸载)调用
引入TrineaAndroidCommon@Github(欢迎star和fork^_^)作为你项目的library(如何拉取代码及添加公共库),或自己抽取PackageUtils.installSlient(PackageUtils.uninstallSilent)函数进行调用,系统授权管理会弹出对话框让用户选择是否允许应用获得root权限。允许的话即可静默安装。
该函数返回PackageUtils.INSTALL_SUCCEEDED表示安装成功,失败则返回相应错误码,可以得到失败的详细原因,包括文件不存在,apk无效,系统内存不足,签名不正确,缺少公共库,share user错误等等判断。
注意对于较大apk安装过程非常耗时,所以最好新启线程去调用PackageUtils.installSlient。
2、root权限静默安装实现
PackageUtils.installSlient的实现实际使用的是su pm install -r filePath命令。核心代码如下:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75  | 
						    public static final String COMMAND_SU       = "su";     public static final String COMMAND_SH       = "sh";     public static final String COMMAND_EXIT     = "exit\n";     public static final String COMMAND_LINE_END = "\n";     public static CommandResult execCommand(String[] commands, boolean isRoot, boolean isNeedResultMsg) {         int result = -1;         if (commands == null || commands.length == 0) {             return new CommandResult(result, null, null);         }         Process process = null;         BufferedReader successResult = null;         BufferedReader errorResult = null;         StringBuilder successMsg = null;         StringBuilder errorMsg = null;         DataOutputStream os = null;         try {             process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);             os = new DataOutputStream(process.getOutputStream());             for (String command : commands) {                 if (command == null) {                     continue;                 }                 // donnot use os.writeBytes(commmand), avoid chinese charset error                 os.write(command.getBytes());                 os.writeBytes(COMMAND_LINE_END);                 os.flush();             }             os.writeBytes(COMMAND_EXIT);             os.flush();             result = process.waitFor();             // get command result             if (isNeedResultMsg) {                 successMsg = new StringBuilder();                 errorMsg = new StringBuilder();                 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 (os != null) {                     os.close();                 }                 if (successResult != null) {                     successResult.close();                 }                 if (errorResult != null) {                     errorResult.close();                 }             } catch (IOException e) {                 e.printStackTrace();             }             if (process != null) {                 process.destroy();             }         }         return new CommandResult(result, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null             : errorMsg.toString());     }  | 
					
其中commands为pm install -r . 从中可以看出主要就是使用su切换到root环境下,再调用pm install -r进行安装。
3、普通安装,系统权限静默安装,root权限静默安装的自动选择
查看PackageUtils源码会发现我还提供了其他几个安装函数,其中PackageUtils.install(PackageUtils.uninstall)函数会根据是否是系统应用以及是否拥有root权限,从而确定调用哪种安装方式(普通安装方式、root静默安装方式还是系统权限静默安装),源码如下:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18  | 
						/**  * install according conditions  * <ul>  * <li>if system application or rooted, see {@link #installSilent(Context, String)}</li>  * <li>else see {@link #installNormal(Context, String)}</li>  * </ul>  *   * @param context  * @param filePath  * @return  */ public static final int install(Context context, String filePath) { 	if (!PackageUtils.isSystemApplication(context) && !ShellUtils.checkRootPermission()) { 		return installNormal(context, filePath) ? INSTALL_SUCCEEDED : INSTALL_FAILED_INVALID_URI; 	} 	return installSilent(context, filePath); }  | 
					
如果是系统应用记得添加<uses-permission android:name=”android.permission.INSTALL_PACKAGES” />权限,从而走普通安装方式,不用申请root权限进行静默安装。
4、PackageUtils 实现静默卸载应用
1252791199
1234
我是小天才电话手表,怎么安装
Hi,你好。
我初学Android,目前公司需要一个静默安装的小程序,问下如何调用installSilent。并且能否推荐一些学习书籍。
hi,你好!执行到result = process.waitFor();后退到了桌面接下来的代码也不会执行,安装是成功的,有遇到过吗?期待你的回答,谢谢!
这种情况到没有遇到过,可能你需要设置下执行线程的超时时间,超时后判断是否安装成功
你好,我也遇到了这个问题。不知道有没有解决的方法,可以请教下么?