赞
踩
Android提供了两种执行shell命令的方法。
1.Runtime.getRuntime().exec(cmds)
2.ProcessBuilder(cmds)
两种方法背后的逻辑相同。都是创建一个新的进程,执行shell命令。本文以第一种方法为例。代码如下:
- public class RuntimeExcUtil {
-
- public static int run(String[] fCmds){
- int tCode=0;
- mLogger.i("APP_SHELL", "start run");
- try {
- Process tProcess = Runtime.getRuntime().exec(fCmds);
- printError(tProcess);
- tCode = tProcess.waitFor();
- mLogger.i("APP_SHELL", "Code Result= "+tCode);
- } catch (Exception e) {
- mLogger.e("APP_SHELL", "run Failed, Error Message :"+e.getMessage());
- }
- return tCode;
- }
-
- public static int runWithSu(String[] fCmds){
- int tCode=0;
- mLogger.i("APP_SHELL", "start run");
- try {
- Process tProcess = Runtime.getRuntime().exec("su");
- runShellScript(tProcess,fCmds);
- printError(tProcess);
- tCode = tProcess.waitFor();
- mLogger.i("APP_SHELL", "Code Result= "+tCode);
- } catch (Exception e) {
- mLogger.e("APP_SHELL", "runWithSu Failed, Error Message :"+e.getMessage());
- }
- return tCode;
- }
-
- private static void printError(Process fProcess){
- StringBuilder output = new StringBuilder();
- String line;
- try(BufferedReader tReader = new BufferedReader(
- new InputStreamReader(fProcess.getErrorStream()))) {
- while ((line = tReader.readLine()) != null) {
- output.append(line).append("\n");
- }
- if (output.toString().length()>0){
- mLogger.e("APP_SHELL", "Error Output = "+output);
- }
- }catch (Exception e){
- mLogger.e("APP_SHELL", "Print Error Output Failed, Error Message :"+e.getMessage());
- }
- }
-
- private static void runShellScript(Process fProcess, String[] fCmds){
- try(DataOutputStream outputStream = new DataOutputStream(fProcess.getOutputStream())) {
- for (String tCmd :
- fCmds) {
- Log.i("APP_SHELL", "Cmd :" + tCmd);
- outputStream.writeBytes(tCmd + "\n");
- }
- outputStream.flush();
- outputStream.writeBytes("exit\n");
- outputStream.flush();
- } catch (Exception e) {
- Log.e("APP_SHELL", "Run Shell Script Failed, Error Message :"+e.getMessage());
- }
- }
- }
测试代码如下:
- //case 1
- RuntimeExcUtil.runWithSu(new String[]{"cp -a -p "+tJavaCrashLogFolderPath+" "+ tCollectFolder});
- //case 2
- RuntimeExcUtil.runWithSu(new String[]{"cd "+tJavaCrashLogFolderPath,"rm -f crash*"});
- //case 3
- RuntimeExcUtil.run(new String[]{"cd /sdcard/Download"});
- //case 4
- RuntimeExcUtil.run(new String[]{"cd", "/sdcard/Download"});
- //case 5
- RuntimeExcUtil.run(new String[]{"cp -a -p "+tJavaCrashLogFolderPath+" "+ tCollectFolder});
- //case 6
- RuntimeExcUtil.run(new String[]{"cp", "-a", "-p", tJavaCrashLogFolderPath,tCollectFolder});
- //case 7
- RuntimeExcUtil.run(new String[]{"rm -f /sdcard/crash/crash*"});
- //case 8
- RuntimeExcUtil.run(new String[]{"rm", "-f", "/sdcard/crash/crash*"});
Case | 结果分析 |
1 | 结果:执行成功。 原因:创建su窗口,并获取上下文,将后续指令写入 DataOutputStream。不会有权限问题,不会有指令解析问题。 |
2 | 结果:同1 原因:同1 |
3 | 结果:执行失败。返回Cannot run program "cd /sdcard/Download": error=2, No such file or directory。 原因:将整个命令字符串作为一个参数传递给 |
4 | 结果:执行失败。返回Cannot run program "cd": error=13, Permission denied。 原因:“cd”是用来改变当前工作目录的 shell 命令,并不是一个可执行程序。所以会得到 "Permission denied" 的错误,这是因为 Android 不允许直接执行这种命令。 |
5 | 结果:同3 原因:同3 |
6 | 结果:执行成功 原因:将指令与参数分开,方便解析。 |
7 | 结果:同3 原因:同3 |
8 | 结果:执行成功 原因:将指令与参数分开,方便解析。 |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。