Android Runtime.getRuntime().exec() 使用方法

    技术2022-07-11  133

    Android Runtime.getRuntime().exec() 使用方法

    苍痕 2015-04-08 15:05:01  26143  收藏 5 版权 Android 可以通过Runtime.getRuntime().exec()方法来执行命令或者创建进程。

    1. Runtime.getRuntime().exec共有六个重载方法:

    public Process exec(String command)

    在单独的进程中执行指定的字符串命令。

    public Process exec(String [] cmdArray)

            在单独的进程中执行指定命令和变量

    public Process exec(String command, String [] envp)

    在指定环境的独立进程中执行指定命令和变量

    public Process exec(String [] cmdArray, String [] envp)

    在指定环境的独立进程中执行指定的命令和变量

    public Process exec(String command,String[] envp,File dir)

    在有指定环境和工作目录的独立进程中执行指定的字符串命令

    public Process exec(String[] cmdarray,String[] envp,File dir)

    在指定环境和工作目录的独立进程中执行指定的命令和变量

    我们先来比较exec(String command)与exec(String[] cmdArray)的区别,其实他们是等价的,最终都会调用:

    exec(String[] cmdarray,String[] envp,File dir),我们看看方法exec(String cmdarray,String[] envp,File dir) throws IOException的实现代码:

    public Process exec(String command, String[] envp, File dir) throws IOException {     if (command.length() == 0) throw new IllegalArgumentException("Empty command");     StringTokenizer st = new StringTokenizer(command);     String[] cmdarray = new String[st.countTokens()];     for (int i = 0; st.hasMoreTokens(); i++) {         cmdarray[i] = st.nextToken();     }     return exec(cmdarray, envp, dir); } 从上面的代码,我们可以看出最终调用的代码都是:exec(String[] cmdArray,String envp,File  dir)。exec(String command)相当于exec(command,null,null),exec(String[] cmdArray)相当于exec(cmdArray,null,null)。 2. 参数说明:

    cmdarray- 包含所调用命令及其参数的数组

    envp- 字符串数组,其中每个元素的环境变量的设置格式为 name=value,如果子进程应该继承当前进程的环境,或该参数为 null

    dir- 子进程的工作目录;如果子进程应该继承当前进程的工作目录,则该参数为 null

    3. 关于返回结果类型:Process,它有几个方法:

        (1).destroy():杀掉子进程

        (2).exitValue():返回子进程的出口值,值0表示正常终止

        (3).getErrorStream():获取子进程的错误流

        (4).getInputStream():获取子进程的输入流

        (5).getOutputStream():获取子进程的输出流

        (6).waitFor():导致当前线程等待,如有必要,一直要等到由该Process对象表示的进程已经终止。如果已终止该子进程,此方法立即返回。如果没有终止该子进程,调用的线程将被阻塞,直到退出子进程,根据惯例, 0表示正常终止

    4. 如何获取command 最终执行的结果?     (1) 执行command命令,将命令行输出重定向到一个文件,再读取文件判断执行结果。

            比如命令:javap -l xxx > output.txt  , 调用exec(String[] cmdArray)如下:

    Process p = Runtime.getRuntime().exec(new String[]{"/bin/sh","-c", "javap -l xxx > output.txt"});    (2) 也可以通过InputStream/OutputStream, 获取命令执行的结果。

            下面例子是先利用“su”提权,然后执行command,完整代码:

        private static boolean exeCommand(String command) {         boolean ret = false;         try {             VirtualTerminal vt;             vt = new VirtualTerminal("su");             VTCommandResult r = vt.runCommand(command);             ret = r.success();             vt.shutdown();         } catch (Exception e) {             e.printStackTrace();         }           return ret;     } VirtualTerminal.java

    package com.test.mytest;   import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream;   import android.util.Log;   public class VirtualTerminal {       private static final String TAG = "VirtualTerminal";       private final Object mReadLock = new Object();     private final Object mWriteLock = new Object();     private Process mProcess = null;       private DataOutputStream mOutputStream;     private ByteArrayOutputStream mInputBuffer = new ByteArrayOutputStream();     private ByteArrayOutputStream mErrBuffer = new ByteArrayOutputStream();     private InputReaderThread mInputReaderThread;     private InputReaderThread mErrReaderThread;       public VirtualTerminal(String shell) throws IOException, InterruptedException {                  mProcess = Runtime.getRuntime().exec(shell);                  mOutputStream = new DataOutputStream(mProcess.getOutputStream());           mInputReaderThread = new InputReaderThread(mProcess.getInputStream(), mInputBuffer);         mErrReaderThread = new InputReaderThread(mProcess.getErrorStream(), mErrBuffer);         Thread.sleep(50);         mInputReaderThread.start();         mErrReaderThread.start();     }       public VTCommandResult runCommand(String command) throws Exception {         synchronized (mWriteLock) {             mInputBuffer.reset();             mErrBuffer.reset();         }           // $? 表示最后运行的命令的结束代码(返回值)         mOutputStream.writeBytes(command + "\necho :RET=$?\n");         mOutputStream.flush();                  while (true) {             synchronized (mReadLock) {                 boolean doWait = false;                 synchronized (mWriteLock) {                     byte[] inpbyte = mInputBuffer.toByteArray();                     String inp = new String(inpbyte);                     doWait = !inp.contains(":RET=");                 }                 if (doWait) {                     mReadLock.wait();                 }             }               synchronized (mWriteLock) {                 byte[] inpbyte = mInputBuffer.toByteArray();                 byte[] errbyte = mErrBuffer.toByteArray();                 String inp = new String(inpbyte);                 String err = new String(errbyte);                   //Please keep log statement or else it will dead loop                 if (inp.contains(":RET=")) {                     if (inp.contains(":RET=EOF") || err.contains(":RET=EOF")) {                         Log.w(TAG, "exec:[eof]" + inp);                     }                                          if (inp.contains(":RET=0")) {                         Log.w(TAG, "exec:[ok]" + inp);                         return new VTCommandResult(0, inp, err);                     } else {                         Log.w(TAG, "exec:[err]" + inp);                         return new VTCommandResult(1, inp, err);                     }                 }             }         }     }       public void shutdown() {         mInputReaderThread.interrupt();         mErrReaderThread.interrupt();         mProcess.destroy();     }       /**      * A thread class helps to read/write data      */     public class InputReaderThread extends Thread {         private InputStream mInputStream;         private ByteArrayOutputStream mByteArrayOutputStream;           public InputReaderThread(InputStream in, ByteArrayOutputStream out) {             mInputStream = in;             mByteArrayOutputStream = out;         }           @Override         public void run() {             if (mInputStream != null) {                 try {                     byte[] buffer = new byte[1024];                     while (true) {                         int read = mInputStream.read(buffer);                         if (read < 0) {                             synchronized(mWriteLock) {                                 String eof = ":RET=EOF";                                 mByteArrayOutputStream.write(eof.getBytes());                             }                             synchronized (mReadLock) {                                 mReadLock.notifyAll();                             }                               break;                         } else if (read > 0) {                             synchronized(mWriteLock) {                                 mByteArrayOutputStream.write(buffer, 0, read);                             }                             synchronized (mReadLock) {                                 mReadLock.notifyAll();                             }                         }                     }                 } catch (Exception ex) {                     ex.printStackTrace();                 }             }         }     }       /**      * A result wrapper for exec()      */     public class VTCommandResult {         public final String mStdout;         public final String mStderr;         public final Integer mExitValue;           VTCommandResult(Integer exit_value_in, String stdout_in, String stderr_in) {             mExitValue = exit_value_in;             mStdout = stdout_in;             mStderr = stderr_in;         }           VTCommandResult(Integer exit_value_in) {             this(exit_value_in, null, null);         }           public boolean success() {             return mExitValue != null && mExitValue == 0;         }     } } 5. 如何用Worker thread 实现 exec() 的等待超时机制?

      /**      * 运行一个外部命令,返回状态, 可以设置超时时间      * @param command      * @param timeout, in milliseconds      * @return      */     private int execCommand(final String[] commandArray, final long timeout) {         Worker worker = null;         try {             worker = new Worker(commandArray);             worker.start();             worker.join(timeout);         } catch (Throwable t) {             t.printStackTrace();         } finally {             if (worker.exit != Integer.MAX_VALUE) {                 return worker.exit;             } else {                 worker.interrupt();             }           }         return ErrorCodeDefine.DOROOT_FAIL;     }       /**      * 用Worker thread 可以实现超时机制      */     private static class Worker extends Thread {         private final String[] commandArray;         private int exit = Integer.MAX_VALUE;           private Worker(String[] commandArray) {             this.commandArray = commandArray;         }           public void run() {             Process process = null;             try {                 process = Runtime.getRuntime().exec(commandArray);                 if (process != null) {                     exit = process.waitFor();                 }             } catch (InterruptedException e) {                 e.printStackTrace();             } catch (Throwable t) {                 t.printStackTrace();             } finally {                 if (process != null) {                     killProcess(process);                 }             }         }     }       /**      * 通过Android底层实现进程关闭      */     private static void killProcess(Process process) {         int pid = getProcessId(process.toString());         if (pid != 0) {             try {                 closeAllStream(process);                 android.os.Process.killProcess(pid);             } catch (Exception e) {                 try {                     process.destroy();                 } catch (Exception ex) {                     ex.printStackTrace();                 }             }         }     }       /**      * 获取当前进程的ID      */     private static int getProcessId(String str) {         try {             int i = str.indexOf("=") + 1;             int j = str.indexOf("]");             String cStr = str.substring(i, j).trim();             return Integer.parseInt(cStr);         } catch (Exception e) {             return 0;         }     }       /**      * 关闭进程的所有流      *      * @param process      */     public static void closeAllStream(Process process) {         try {             InputStream in = process.getInputStream();             if (in != null)                 in.close();         } catch (Exception e) {             e.printStackTrace();         }         try {             InputStream in = process.getErrorStream();             if (in != null)                 in.close();         } catch (Exception e) {             e.printStackTrace();         }         try {             OutputStream out = process.getOutputStream();             if (out != null)                 out.close();         } catch (Exception e) {             e.printStackTrace();         }

    ———————————————— 版权声明:本文为博主「苍痕」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/wangbaochu/article/details/44941045

    Processed: 0.011, SQL: 10