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();
}
}
}
}
}