1、Api介绍
以下是ShellUtils中最终执行命令的方法execCommand:
public CommandResult execCommand(String[] commands, boolean isRoot, boolean isNeedResultMsg)
其中
- commands:表示依次执行的shell命令数组
- isRoot:表示是否以su用户执行(需要手机已经root)
- isNeedResultMsg:表示是否存储命令执行成功及失败后的信息。
/** * result of command * * @author <a href="http://www.trinea.cn" target="_blank">Trinea</a> 2013-5-16 */ public static class CommandResult { /** result of command **/ public int result; /** success message of command result **/ public String successMsg; /** error message of command result **/ public String errorMsg; public CommandResult(int result){ this.result = result; } public CommandResult(int result, String successMsg, String errorMsg){ this.result = result; this.successMsg = successMsg; this.errorMsg = errorMsg; } }
- CommandResult:为返回的数据结构,如下其中result表示执行的结果,根据Linux命令执行规则,0表示成功,其他为相应错误码。
- successMsg:存储执行成功后的输出信息,errorMsg存储执行失败后的输出信息。
- 如果isNeedResultMsg为false,successMsg和errorMsg会始终为空,而result依然为正常结果。
其他接口,Shell命令支持执行String(单个命令), List(多个命令),String[](多个命令)
ShellUtil.java
package cn.trinea.android.common.util; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.List; /** * ShellUtils * <ul> * <strong>Check root</strong> * <li>{@link ShellUtils#checkRootPermission()}</li> * </ul> * <ul> * <strong>Execte command</strong> * <li>{@link ShellUtils#execCommand(String, boolean)}</li> * <li>{@link ShellUtils#execCommand(String, boolean, boolean)}</li> * <li>{@link ShellUtils#execCommand(List, boolean)}</li> * <li>{@link ShellUtils#execCommand(List, boolean, boolean)}</li> * <li>{@link ShellUtils#execCommand(String[], boolean)}</li> * <li>{@link ShellUtils#execCommand(String[], boolean, boolean)}</li> * </ul> * * @author <a href="http://www.trinea.cn" target="_blank">Trinea</a> 2013-5-16 */ public class ShellUtils { 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"; private ShellUtils() { throw new AssertionError(); } /** * check whether has root permission * * @return */ public static boolean checkRootPermission() { return execCommand("echo root", true, false).result == 0; } /** * execute shell command, default return result msg * * @param command command * @param isRoot whether need to run with root * @return * @see ShellUtils#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(String command, boolean isRoot) { return execCommand(new String[] {command}, isRoot, true); } /** * execute shell commands, default return result msg * * @param commands command list * @param isRoot whether need to run with root * @return * @see ShellUtils#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(List<String> commands, boolean isRoot) { return execCommand(commands == null ? null : commands.toArray(new String[] {}), isRoot, true); } /** * execute shell commands, default return result msg * * @param commands command array * @param isRoot whether need to run with root * @return * @see ShellUtils#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(String[] commands, boolean isRoot) { return execCommand(commands, isRoot, true); } /** * execute shell command * * @param command command * @param isRoot whether need to run with root * @param isNeedResultMsg whether need result msg * @return * @see ShellUtils#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(String command, boolean isRoot, boolean isNeedResultMsg) { return execCommand(new String[] {command}, isRoot, isNeedResultMsg); } /** * execute shell commands * * @param commands command list * @param isRoot whether need to run with root * @param isNeedResultMsg whether need result msg * @return * @see ShellUtils#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(List<String> commands, boolean isRoot, boolean isNeedResultMsg) { return execCommand(commands == null ? null : commands.toArray(new String[] {}), isRoot, isNeedResultMsg); } /** * execute shell commands * * @param commands command array * @param isRoot whether need to run with root * @param isNeedResultMsg whether need result msg * @return <ul> * <li>if isNeedResultMsg is false, {@link CommandResult#successMsg} is null and * {@link CommandResult#errorMsg} is null.</li> * <li>if {@link CommandResult#result} is -1, there maybe some excepiton.</li> * </ul> */ 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()); } /** * result of command * <ul> * <li>{@link CommandResult#result} means result of command, 0 means normal, else means error, same to excute in * linux shell</li> * <li>{@link CommandResult#successMsg} means success message of command result</li> * <li>{@link CommandResult#errorMsg} means error message of command result</li> * </ul> * * @author <a href="http://www.trinea.cn" target="_blank">Trinea</a> 2013-5-16 */ public static class CommandResult { /** result of command **/ public int result; /** success message of command result **/ public String successMsg; /** error message of command result **/ public String errorMsg; public CommandResult(int result) { this.result = result; } public CommandResult(int result, String successMsg, String errorMsg) { this.result = result; this.successMsg = successMsg; this.errorMsg = errorMsg; } } }
2、使用场景
以目前自己的几个场景举下例子
(1) 静默安装和卸载
这个很多朋友已经用过了Android root权限静默安装或卸载应用,原理是执行命令:pm install apkFilePath及pm uninstall packageName
具体代码可见:PackageUtils installSilent(Context context, String filePath, String pmParams)
(2) 获取系统设置->存储->首选安装位置
原理是执行命令:pm get-install-location
具体代码可见:PackageUtils getInstallLocation()
(3) Android修改hosts文件
原理是执行命令:
mount -o rw,remount /system echo “127.0.0.1 localhost” > /etc/hosts echo “185.31.17.184 github.global.ssl.fastly.net” >> /etc/hosts chmod 644 /etc/hosts
代码如下:
List<String> commnandList = new ArrayList<String>(); commnandList.add("mount -o rw,remount /system"); commnandList.add("echo \"127.0.0.1 localhost\" > /etc/hosts"); commnandList.add("echo \"185.31.17.184 github.global.ssl.fastly.net\" >> /etc/hosts"); commnandList.add("chmod 644 /etc/hosts"); CommandResult result = ShellUtils.execCommand(commnandList, true);
用echo命令改hosts文件很牛逼哦,不用重启可以直接生效的哦。
(4) 拷贝文件
原理是执行命令:
mount -o rw,remount /system cp /mnt/sdcard/xx.apk /system/app/
代码如下:
String[] commands = new String[] { "mount -o rw,remount /system", "cp /mnt/sdcard/xx.apk /system/app/" }; CommandResult result = ShellUtils.execCommand(commands, true);
注意一般拷贝文件是不需要root的,上面用root是因为需要拷贝到/system/app/下面
摘自:
https://blog.csdn.net/yubang3223111/article/details/76635528
工作中,Java后端把它改为了一个 “Linux命令行工具”助手类
package com.wanma.framework_web.helper; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; /** * Linux命令行工具 助手类 * 参考:/2160.html */ public class ShellHelper { 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"; private ShellHelper() { throw new AssertionError(); } /** * 检测是否有root权限 */ public static boolean checkRootPermission() throws Exception { return exec("echo root", true, false).code == 0; } /** * 执行Shell命令 * * @param command 单个命令行 * @param isRoot 是否切换至root用户 * @return CommandResult */ public static CommandResult exec(String command, boolean isRoot) throws Exception { return exec(new String[]{command}, isRoot, true); } /** * 执行Shell命令 * * @param commands 命令行列表 * @param isRoot 是否切换至root用户 * @return CommandResult */ public static CommandResult exec(ArrayList<String> commands, boolean isRoot) throws Exception { return exec(commands == null ? null : commands.toArray(new String[]{}), isRoot, true); } public static CommandResult exec(ArrayList<String> commands) throws Exception { return exec(commands == null ? null : commands.toArray(new String[]{}), false, true); } /** * 执行Shell命令 * * @param commands 命令行数组 * @param isRoot 是否切换至root用户 * @return CommandResult */ public static CommandResult exec(String[] commands, boolean isRoot) throws Exception { return exec(commands, isRoot, true); } public static CommandResult exec(String[] commands) throws Exception { return exec(commands, false, true); } /** * 执行Shell命令 * * @param command 单个命令行 * @param isRoot 是否切换至root用户 * @param isNeedResultMsg 是否需要返回结果信息 * @return CommandResult */ public static CommandResult exec(String command, boolean isRoot, boolean isNeedResultMsg) throws Exception { return exec(new String[]{command}, isRoot, isNeedResultMsg); } /** * 执行Shell命令 * * @param commands 命令行列表 * @param isRoot 是否切换至root用户 * @param isNeedResultMsg 是否需要返回结果信息 * @return CommandResult */ public static CommandResult exec(List<String> commands, boolean isRoot, boolean isNeedResultMsg) throws Exception { return exec(commands == null ? null : commands.toArray(new String[]{}), isRoot, isNeedResultMsg); } /** * execute shell commands * * @param commands 命令行数组 * @param isRoot 是否切换至root用户 * @param isNeedResultMsg 是否需要返回结果信息 * @return CommandResult * 假如isNeedResultMsg等于false,CommandResult.successMsg为null,CommandResult.errorMsg为null, * 假如CommandResult.code等于-1,可能发生了异常 */ public static CommandResult exec(String[] commands, boolean isRoot, boolean isNeedResultMsg) throws Exception { int code = -1; if (commands == null || commands.length == 0) { return new CommandResult(code, 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(); code = process.waitFor(); // get command code 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).append(COMMAND_LINE_END); } while ((s = errorResult.readLine()) != null) { errorMsg.append(s).append(COMMAND_LINE_END); } } } 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(code, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null : errorMsg.toString()); } /** * 命令行执行结果类 * CommandResult.code:0为正常,其他为错误 * CommandResult.successMsg:执行结果的成功信息 * CommandResult.errorMsg:执行结果的错误信息 */ public static class CommandResult { /** * 执行结果的状态值 **/ private int code; /** * 执行结果的成功信息 **/ private String successMsg; /** * 执行结果的错误信息 **/ private String errorMsg; public CommandResult(int code) { this.code = code; } public CommandResult(int code, String successMsg, String errorMsg) { this.code = code; this.successMsg = successMsg; this.errorMsg = errorMsg; } public int getCode() { return this.code; } public String getSuccessMsg() { return this.successMsg; } public String getErrorMsg() { return this.errorMsg; } } }
package com.wanma.framework_api.helper; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import java.awt.*; import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; /** * Windows命令行工具 助手类 */ @Slf4j public class CmdWinHelper { /** * 启动进程 */ public static void startProc(String processName) { log.info("启动应用程序:" + processName); if (StrUtil.isEmpty(processName)) { return; } try { Desktop.getDesktop().open(new File(processName)); } catch (Exception e) { e.printStackTrace(); log.error("应用程序:" + processName + "不存在!"); } } /** * 杀死进程 */ public static void killProc(String processName) { log.info("关闭应用程序:" + processName); if (StrUtil.isEmpty(processName)) { return; } try { executeCmd("taskkill /F /IM " + processName); } catch (Exception e) { e.printStackTrace(); } } /** * 执行cmd命令 */ public static String executeCmd(String command) { log.info("Execute command : " + command); try { Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec("cmd /c " + command); BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream(), CharsetUtil.CHARSET_UTF_8)); String line = null; StringBuilder build = new StringBuilder(); while ((line = br.readLine()) != null) { log.info(line); build.append(line); } return build.toString(); } catch (Exception e) { return ""; } } /** * 判断进程是否开启 */ public static boolean findProcess(String processName) { BufferedReader bufferedReader = null; try { Process proc = Runtime.getRuntime().exec("tasklist -fi " + '"' + "imagename eq " + processName + '"'); bufferedReader = new BufferedReader(new InputStreamReader(proc.getInputStream())); String line = null; while ((line = bufferedReader.readLine()) != null) { if (line.contains(processName)) { return true; } } return false; } catch (Exception e) { e.printStackTrace(); return false; } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (Exception e) { e.printStackTrace(); } } } } }