最近在做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 命令行执行工具类的更多相关文章

  1. TortoiseSVN 命令 (命令行执行工具)

    TortoiseSVN是一个GUI客户端,这个自动化指导为你展示了让TortoiseSVN对话框显示并收集客户输入,如果你希望编写不需要输入的脚本,你应该使用官方的Subversion命令行客户端. ...

  2. android程序中使用命令行及获得命令行执行后的内容

    在开发android项目中,需要在程序中使用命令行执行,获得命令行执行后的结果并做处理. 下面是自己写的一个小例子,供以后参考使用: public String android_command(){ ...

  3. libvirt 命令行交互工具之virsh

    libvirt是当前主流VM最低层库.IBM PowerVM也不例外,libvirt是深入玩虚拟化必须玩转的东西; 简单测试玩玩libvirt 的virsh命令行交互工具, 你我都知libvirt大体 ...

  4. php 运行linux命令 与 linux下命令行执行php

    1.php运行linux命令 exec函数:string exec(string command, string [array], int [return_var]);  执行函数后不输出结果,返回最 ...

  5. Python中最好用的命令行解析工具:argparse

    Python 做为一个脚本语言,可以很方便地写各种工具.当你在服务端要运行一个工具或服务时,输入参数似乎是一种硬需(当然你也可以通过配置文件来实现). 如果要以命令行执行,那你需要解析一个命令行参数解 ...

  6. 远程shell脚本执行工具类

    /** * 远程shell脚本执行工具类 */public class RemoteShellExecutorUtils { private static final Logger logger = ...

  7. 使用命令行执行jmeter的方法

    1. 简介 使用非 GUI 模式,即命令行模式运行 JMeter 测试脚本能够大大缩减所需要的系统资 本文介绍windows下以命令行模式运行的方法. 1.1. 命令介绍 jmeter -n -t & ...

  8. android 命令行安装apk

    有两种方式可以在android模拟器或真机上使用命令行安装apk 一种是使用adb install命令,网上通常是这种方式 另一种是通过android提供的命令,pm install. 需要先进入an ...

  9. django源码(2.0.2)粗解之命令行执行

    前言 django的命令行在整个的django web开发中都会经常用到,而且是必须得用到.所以,能够了解下django的命令行实现其实是非常有帮助的. 如果大家比较关心django命令的详细说明和使 ...

随机推荐

  1. Java中的进程与线程(总结篇)

    详细文档: Java中的进程与线程.rar 474KB 1/7/2017 6:21:15 PM 概述: 几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进 ...

  2. 跨域问题,前端主动向后台发送cookie

    跨域是什么? 从一个域名的网页访问另一个域名的资源,就会出现跨域.只要协议.端口.域名有一个不同就会出现跨域 例如: 1.协议不同  http://www.baidu.com:80 和 https:/ ...

  3. MEF学习

    一.   什么是MEF MEF(Managed Extensibility Framework)是一个用于创建可扩展的轻型应用程序的库. 应用程序开发人员可利用该库发现并使用扩展,而无需进行配置. 扩 ...

  4. 从零开始,DIY一个jQuery(2)

    在上篇文章我们简单实现了一个 jQuery 的基础结构,不过为了顺应潮流,这次咱把它改为模块化的写法,此举得以有效提升项目的可维护性,因此在后续也将以模块化形式进行持续开发. 模块化开发和编译需要用上 ...

  5. EasyPR--开发详解(4)形态学操作、尺寸验证、旋转等操作

    在上一篇深度分析与调优讨论中,我们介绍了高斯模糊,灰度化和Sobel算子.在本文中,会分析剩余的定位步骤. 根据前文的内容,车牌定位的功能还剩下如下的步骤,见下图中未涂灰的部分. 图1 车牌定位步骤 ...

  6. Jvm --- 常用工具

    jps:虚拟机进程状况工具 JVM Process Status Tool. 可以列出所有目前正在运行虚拟机的进程. jps -l 详细参数: -q 输出LVMID,省略主类名称 -m 输出虚拟机进程 ...

  7. 小丁带你走进git世界五-远程仓库

    一.文件,指令讲解 首先讲一下远程仓库和本地仓库在文件上面的区别,首先我们来看下对比图(当然这里说的区别是在于.git文件下面的文件内容,至于里面内容我们不会关注)這裡我们进行了相同的操作就是本地仓库 ...

  8. Atitit opencv版本新特性attilax总结

    Atitit opencv版本新特性attilax总结 1.1. :OpenCV 3.0 发布,史上功能最全,速度最快的版1 1.2. 应用领域2 1.3. OPENCV2.4.3改进 2.4.2就有 ...

  9. Vue1.0 的技术栈

    vuejs概述 Vue.js是用于构建交互式的Web界面的库.它提供了MVVM数据绑定和一个可组合的组件系统,具有简单.灵活的API. 结合node.js 可以实现前后端开发从物理上的分离.使前端负责 ...

  10. MySql常用数据类型分析

    整数类型 TINYINT.SMALLINT.MEDIUMINT.INT.BIGINT 分别使用8,16,24,32,64位存储空间,值得范围-2的(N-1)方到2的(N-1)方-1.根据需要存储的范围 ...