最近在做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. Linux-Rhel6 恢复误删文件

    需要工具extundelete(可通过xshell上传下载到linux)知识点:ifconifig eth0             查看ipfdisk /dev/sda          管理磁盘m ...

  2. SSD框架训练自己的数据集

    SSD demo中详细介绍了如何在VOC数据集上使用SSD进行物体检测的训练和验证.本文介绍如何使用SSD实现对自己数据集的训练和验证过程,内容包括: 1 数据集的标注2 数据集的转换3 使用SSD如 ...

  3. CacheManager:–个通用缓存接口抽象类库

    CacheManager是–个缓存通用接口抽象类库,它支持各种高速缓存提供者,例如Memcache,Redis,并且有许多先进的功能特性.具体可以访问官方网站  http://cachemanager ...

  4. 【腾讯Bugly干货分享】H5 视频直播那些事

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57a42ee6503dfcb22007ede8 Dev Club 是一个交流移动 ...

  5. Linux3 在VMware中搭建CentOS6.5虚拟机

    前言:      本文主要是我在大家hadoop集群之前 ,需啊先安装CentOS虚拟机,记录在此,作为参考.如果能帮助到其他人,自然是更好啦. =========================== ...

  6. Entity Framework 6 Recipes 2nd Edition(12-8)译 -> 重新获取一个属性的原始值

    12-8. 重新获取一个属性的原始值 问题 在实体保存到数据库之前,你想重新获取属性的原始值 解决方案 假设你有一个模型 (见 Figure 12-11) 表示一个员工( Employee),包含工资 ...

  7. python的拷贝(深拷贝和浅拷贝)

    今天看了几篇关于python拷贝的博文,感觉不太清楚,所以我就自己做实验试一下,特此记录. 拷贝是针对组合对象说的,比如列表,类等,而数字,字符串这样的变量是没有拷贝这一说的. 实现拷贝有: 1.工厂 ...

  8. [翻译]AKKA笔记 - 有限状态机 -1

    原文地址:http://rerun.me/2016/05/21/akka-notes-finite-state-machines-1/ 我最近有个机会在工作上使用了Akka FSM,是个非常有趣的例子 ...

  9. EMC与电容(二)-电容参数意义、各电容的特点及应用

    上次的问题,看到很多回答里都有关于X电容,Y电容,NPO之类,这些很奇怪的参数到底代表什么意义呢?以前很多次都在BOM表里看到这些参数,一直都无视过去,正好这次的EMC课程里也提到这方面的知识,正好跟 ...

  10. HTML5移动开发学习笔记之CSS3基础学习

    CSS回顾 在学CSS3之前首先巩固下CSS的基础知识. 1.CSS框模型 举例子: #box { width: 70px; margin: 10px; padding: 5px; } 这个代码将出现 ...