Android 命令行执行工具类
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 命令行执行工具类相关的知识,希望对你有一定的参考价值。
最近在做android项目的时候,需要执行命令行命令,之前在网上找的不仅杂乱而且错误多,于是自己写了一份。
话不多说,直接上代码
import android.util.Log; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.InputStreamReader; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import static java.lang.Runtime.getRuntime; /** * 执行命令的类 * Created by Kappa */ public class ExeCommand { //shell进程 private Process process; //对应进程的3个流 private BufferedReader successResult; private BufferedReader errorResult; private DataOutputStream os; //是否同步,true:run会一直阻塞至完成或超时。false:run会立刻返回 private boolean bSynchronous; //表示shell进程是否还在运行 private boolean bRunning = false; //同步锁 ReadWriteLock lock = new ReentrantReadWriteLock(); //保存执行结果 private StringBuffer result = new StringBuffer(); /** * 构造函数 * * @param synchronous true:同步,false:异步 */ public ExeCommand(boolean synchronous) { bSynchronous = synchronous; } /** * 默认构造函数,默认是同步执行 */ public ExeCommand() { bSynchronous = true; } /** * 还没开始执行,和已经执行完成 这两种情况都返回false * * @return 是否正在执行 */ public boolean isRunning() { return bRunning; } /** * @return 返回执行结果 */ public String getResult() { Lock readLock = lock.readLock(); readLock.lock(); try { return new String(result); } finally { readLock.unlock(); } } /** * 执行命令 * * @param command eg: cat /sdcard/test.txt * @param maxTime 最大等待时间 (ms) * @return this */ public ExeCommand run(String command, final int maxTime) { Log.i("auto", "run command:" + command + ",maxtime:" + maxTime); if (command == null || command.length() == 0) { return this; } try { process = getRuntime().exec("sh"); } catch (Exception e) { return this; } bRunning = true; successResult = new BufferedReader(new InputStreamReader(process.getInputStream())); errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream())); os = new DataOutputStream(process.getOutputStream()); try { //向sh写入要执行的命令 os.write(command.getBytes()); os.writeBytes("\n"); os.flush(); os.writeBytes("exit\n"); os.flush(); os.close(); //如果等待时间设置为非正,就不开启超时关闭功能 if (maxTime > 0) { //超时就关闭进程 new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(maxTime); } catch (Exception e) { } try { int ret = process.exitValue(); } catch (IllegalThreadStateException e) { Log.i("auto", "take maxTime,forced to destroy process"); process.destroy(); } } }).start(); } //开一个线程来处理input流 final Thread t1 = new Thread(new Runnable() { @Override public void run() { String line; Lock writeLock = lock.writeLock(); try { while ((line = successResult.readLine()) != null) { line += "\n"; writeLock.lock(); result.append(line); writeLock.unlock(); } } catch (Exception e) { Log.i("auto", "read InputStream exception:" + e.toString()); } finally { try { successResult.close(); } catch (Exception e) { Log.i("auto", "close InputStream exception:" + e.toString()); } } } }); t1.start(); //开一个线程来处理error流 final Thread t2 = new Thread(new Runnable() { @Override public void run() { String line; Lock writeLock = lock.writeLock(); try { while ((line = errorResult.readLine()) != null) { line += "\n"; writeLock.lock(); result.append(line); writeLock.unlock(); } } catch (Exception e) { Log.i("auto", "read ErrorStream exception:" + e.toString()); } finally { try { errorResult.close(); } catch (Exception e) { Log.i("auto", "read ErrorStream exception:" + e.toString()); } } } }); t2.start(); Thread t3 = new Thread(new Runnable() { @Override public void run() { try { //等待执行完毕 t1.join(); t2.join(); process.waitFor(); } catch (Exception e) { } finally { bRunning = false; Log.i("auto", "run command process end"); } } }); t3.start(); if (bSynchronous) { t3.join(); } } catch (Exception e) { Log.i("auto", "run command process exception:" + e.toString()); } return this; } }
讲解一下关键点,首先是启动一个sh进程,当然如果你用的是root的设备,可以使用su。
这个进程包含 input、output、error 三个流,这三个流要处理好,否则可能不能正常结束进程,
另外也存在执行的命令已经结束,但是依然还有input流的情况,也需要处理。
其他请参考代码
使用方式为2种。首先是阻塞方式,这种调用方式会一直阻塞至命令执行完成,返回命令行的输出结果
String str = new ExeCommand().run(cmd, 10000).getResult();
还有一种是异步方式,这种调用方式会直接返回,之后可以使用 getResult() 获取结果,使用 isRunning() 来判断是否完成,比如
ExeCommand cmd = new ExeCommand(false).run("your cmd", 60000); while(cmd.isRunning()) { try { sleep(1000); } catch (Exception e) { } String buf = cmd.getResult(); //do something }
以上是关于Android 命令行执行工具类的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向Android 逆向通用工具开发 ( Android 平台运行的 cmd 程序类型 | Android 平台运行的 cmd 程序编译选项 | 编译 cmd 可执行程序 )(代码片段
sql [SQL查询片段]用于在命令行或通过R和其他工具使用SQL的快速代码段#tags:sql,R,text processing,命令li
Android android.view.InflateException Binary XML 文件第 16 行:膨胀类片段时出错