Android ().exec() 使用方法
苍痕 2015-04-08 15:05:01 26143 收藏 5
版权
Android 可以通过().exec()方法来执行命令或者创建进程。
1. ().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 (() == 0) throw new IllegalArgumentException("Empty command");
StringTokenizer st = new StringTokenizer(command);
String[] cmdarray = new String[()];
for (int i = 0; (); i++) {
cmdarray[i] = ();
}
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 > , 调用exec(String[] cmdArray)如下:
Process p = ().exec(new String[]{"/bin/sh","-c", "javap -l xxx > "});
(2) 也可以通过InputStream/OutputStream, 获取命令执行的结果。
下面例子是先利用“su”提权,然后执行command,完整代码:
private static boolean exeCommand(String command) {
boolean ret = false;
try {
VirtualTerminal vt;
vt = new VirtualTerminal("su");
VTCommandResult r = (command);
ret = ();
();
} catch (Exception e) {
();
}
return ret;
}
package ;
import ;
import ;
import ;
import ;
import ;
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 = ().exec(shell);
mOutputStream = new DataOutputStream(());
mInputReaderThread = new InputReaderThread((), mInputBuffer);
mErrReaderThread = new InputReaderThread((), mErrBuffer);
(50);
();
();
}
public VTCommandResult runCommand(String command) throws Exception {
synchronized (mWriteLock) {
();
();
}
// $? 表示最后运行的命令的结束代码(返回值)
(command + "\necho :RET=$?\n");
();
while (true) {
synchronized (mReadLock) {
boolean doWait = false;
synchronized (mWriteLock) {
byte[] inpbyte = ();
String inp = new String(inpbyte);
doWait = !(":RET=");
}
if (doWait) {
();
}
}
synchronized (mWriteLock) {
byte[] inpbyte = ();
byte[] errbyte = ();
String inp = new String(inpbyte);
String err = new String(errbyte);
//Please keep log statement or else it will dead loop
if ((":RET=")) {
if ((":RET=EOF") || (":RET=EOF")) {
(TAG, "exec:[eof]" + inp);
}
if ((":RET=0")) {
(TAG, "exec:[ok]" + inp);
return new VTCommandResult(0, inp, err);
} else {
(TAG, "exec:[err]" + inp);
return new VTCommandResult(1, inp, err);
}
}
}
}
}
public void shutdown() {
();
();
();
}
/**
* 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 = (buffer);
if (read < 0) {
synchronized(mWriteLock) {
String eof = ":RET=EOF";
(());
}
synchronized (mReadLock) {
();
}
break;
} else if (read > 0) {
synchronized(mWriteLock) {
(buffer, 0, read);
}
synchronized (mReadLock) {
();
}
}
}
} catch (Exception ex) {
();
}
}
}
}
/**
* 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);
();
(timeout);
} catch (Throwable t) {
();
} finally {
if ( != Integer.MAX_VALUE) {
return ;
} else {
();
}
}
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) {
= commandArray;
}
public void run() {
Process process = null;
try {
process = ().exec(commandArray);
if (process != null) {
exit = ();
}
} catch (InterruptedException e) {
();
} catch (Throwable t) {
();
} finally {
if (process != null) {
killProcess(process);
}
}
}
}
/**
* 通过Android底层实现进程关闭
*/
private static void killProcess(Process process) {
int pid = getProcessId(());
if (pid != 0) {
try {
closeAllStream(process);
(pid);
} catch (Exception e) {
try {
();
} catch (Exception ex) {
();
}
}
}
}
/**
* 获取当前进程的ID
*/
private static int getProcessId(String str) {
try {
int i = ("=") + 1;
int j = ("]");
String cStr = (i, j).trim();
return (cStr);
} catch (Exception e) {
return 0;
}
}
/**
* 关闭进程的所有流
*
* @param process
*/
public static void closeAllStream(Process process) {
try {
InputStream in = ();
if (in != null)
();
} catch (Exception e) {
();
}
try {
InputStream in = ();
if (in != null)
();
} catch (Exception e) {
();
}
try {
OutputStream out = ();
if (out != null)
();
} catch (Exception e) {
();
}
————————————————
版权声明:本文为****博主「苍痕」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:/wangbaochu/article/details/44941045