您的位置:首页 > 移动开发 > Android开发

Android通过Runtime.getRuntime().exec实现Ping和Traceroute命令时readLine阻塞问题解决

2014-05-05 18:56 876 查看
在PC上调用cmd,进行一些常用的命令操作,在Android上的是通过Runtime.getRuntime().exec来执行底层Linux下的程序或脚本(bat)。

首先连接上真机,电脑打开CMD,输入adb-shell,确保你要进行的脚本语言是可以执行的。(比如常见的ping命令)

但是深入一下,发现使用ping命令,并附加一些参数,我们设置 -w 5 了,希望5秒钟如果没有ping通,可以有返回,可是像如下常规的操作,貌似ping下的附加参数是不会起作用的,也就是说在cmd下,我希望ping后5秒没有收到包就返回,但是在android下执行就不会有效果:

Process process = null;
InputStream instream = null;
BufferedReader bufferReader = null;

try {
process = Runtime.getRuntime().exec(command);

instream = process.getInputStream();
bufferReader = new BufferedReader(new InputStreamReader(instream, "GBK"));

String readline;
while ((readline = bufferReader.readLine()) != null) {
results.add(readline);
//					Log.i(TAG, "execute command result : " + readline);
}

int status = process.waitFor();
Log.i(TAG, "execute command :" + command + ", status : " + status);

} catch (IOException e) {
Log.e(TAG, e.getMessage());
} catch (InterruptedException e) {
Log.e(TAG, e.getMessage());
}
这种常规的操作,如果执行一条Ping命令,当在某个ip下卡住ping不通时,就有问题了,会发现代码一直会阻塞在br.readLine()的地方,任何办法都不好解决,网上说的把操作放在另外一个Thread里进行,只是解决了process.waiFor()的阻塞问题。其实也解决不了当进行ping不通时readline阻塞的问题,在ping命令的操作下使用readline并不像读取一个文件,当遇到换行时会结束,ping不通,只能一直阻塞着,除非在外部进行close等操作。

结合国内外论坛,终于找到一个办法,我写成了一个方法类,供大家参考(可直接调用):

package com.vixtel.netvista.gdcmcc.utils;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import android.util.Log;

/***
* 执行命令行工具类
*
* @author yangxiaolong 2014-04-30
*
*/
public class CommandUtil {

public static final String TAG = CommandUtil.class.getSimpleName();
public static final String COMMAND_SH = "sh";
public static final String COMMAND_LINE_END = "\n";
public static final String COMMAND_EXIT = "exit\n";
private static final boolean ISDEBUG = true;

/**
* 执行单条命令
*
* @param command
* @return
*/
public static List<String> execute(String command) {
return execute(new String[] { command });
}

/**
* 可执行多行命令(bat)
*
* @param commands
* @return
*/
public static List<String> execute(String[] commands) {
List<String> results = new ArrayList<String>();
int status = -1;
if (commands == null || commands.length == 0) {
return null;
}
debug("execute command start : " + commands);
Process process = null;
BufferedReader successReader = null;
BufferedReader errorReader = null;
StringBuilder errorMsg = null;

DataOutputStream dos = null;
try {
// TODO
process = Runtime.getRuntime().exec(COMMAND_SH);
dos = new DataOutputStream(process.getOutputStream());
for (String command : commands) {
if (command == null) {
continue;
}
dos.write(command.getBytes());
dos.writeBytes(COMMAND_LINE_END);
dos.flush();
}
dos.writeBytes(COMMAND_EXIT);
dos.flush();

status = process.waitFor();

errorMsg = new StringBuilder();
successReader = new BufferedReader(new InputStreamReader(
process.getInputStream()));
errorReader = new BufferedReader(new InputStreamReader(
process.getErrorStream()));
String lineStr;
while ((lineStr = successReader.readLine()) != null) {
results.add(lineStr);
debug(" command line item : " + lineStr);
}
while ((lineStr = errorReader.readLine()) != null) {
errorMsg.append(lineStr);
}

} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (dos != null) {
dos.close();
}
if (successReader != null) {
successReader.close();
}
if (errorReader != null) {
errorReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}

if (process != null) {
process.destroy();
}
}
debug(String.format(Locale.CHINA,
"execute command end,errorMsg:%s,and status %d: ", errorMsg,
status));
return results;
}

/**
* DEBUG LOG
*
* @param message
*/
private static void debug(String message) {
if (ISDEBUG) {
Log.d(TAG, message);
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: