1. 程式人生 > >Android通過Runtime.getRuntime().exec實現Ping和Traceroute命令時readLine阻塞問題解決

Android通過Runtime.getRuntime().exec實現Ping和Traceroute命令時readLine阻塞問題解決

在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);
		}
	}

}

相關推薦

Android通過Runtime.getRuntime().exec實現PingTraceroute命令readLine阻塞問題解決

在PC上呼叫cmd,進行一些常用的命令操作,在Android上的是通過Runtime.getRuntime().exec來執行底層Linux下的程式或指令碼(bat)。 首先連線上真機,電腦開啟CMD,輸入adb-shell,確保你要進行的指令碼語言是可以執行的。(比如

Android: 通過Runtime.getRuntime().exec呼叫底層Linux下的程式或指令碼

Android Runtime使得直接呼叫底層Linux下的可執行程式或指令碼成為可能 比如Linux下寫個測試工具,直接編譯後apk中通過Runtime來呼叫 或者寫個指令碼,apk中直接呼叫,省去中間層或者JNI 這個至少效率應該比較高吧   程式碼:

java調Python指令碼(五):java通過 Runtime.getRuntime().exec()調Python指令碼一直沒有返回值,卡住了,資料太大

1、背景: 當我們呼叫系統外部的某個程式,此時就可以用Runtime.getRuntime().exec()來呼叫。這次java調Python演算法程式碼時,一直沒有返回值,卡住了,而用pycharm跑Python程式碼是正常的,說明是java這邊的問題。去看了後臺的java程序一直都在,掛

Runtime.getRuntime().exec()實現Java呼叫python程式

使用Runtime.getRuntime().exec()來實現Java呼叫python,呼叫程式碼如下所示: import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;

Runtime.getRuntime().exec(cmd,envp,dir)執行命令cmd中目錄含連續空格執行出錯

.get 導致 strong 問題 多少 cmd 缺失 就會 成了 場景:因cmd中含有jre路徑,而jre路徑因測試創建的目錄中含(haha)- -(haha) ,其中含有兩個空格,導致後續底層在截取,重組命令後缺失了一個空格,目錄中(haha)- -(haha)變成

Android Runtime.getRuntime().exec

exe runt amr stringbu clas ring tdi -s put try { // Executes the command. Process process = Runtime.getRunt

android Runtime.getRuntime().exec使用

1.read value: public String readRegister(String path){ try { Process process = Runtime.getRuntime().exec("/system/bin/cat

Android Runtime.getRuntime().exec() 使用方法

Android 可以通過Runtime.getRuntime().exec()方法來執行命令或者建立程序。 1. Runtime.getRuntime().exec共有六個過載方法: public Process exec(String command) 在單獨的程序

android 通過原生api(不需要opencv第三方sdk)實現Camera人臉檢測

浪費了“黃金五年”的Java程式設計師,還有救嗎? >>>   

Runtime.getRuntime().exec(cmd)執行adb shell腳本可能出現的問題

執行 eve (()) 十六進制 解決辦法 /dev/ dev exec 進制 例如:adb shell sendevent /dev/input/event3 1 $((0xca)) 1上面語句中含有$((0xca)) ,執行Runtime.getRuntime().ex

android 通過監聽edittext實現button的點擊事件

監聽 edittext 如果你沒有接第三方的輸入設備,那麽點擊按鈕只需找到你的button然後:button.performClick();就可以了那麽如果你用到第三方輸入法,有些時候監聽就沒有這麽好使了:以下場景為:外接輸入服務,直接給我丟一串字符,我拿到字符後執行按鈕事件代碼如下: editTe

Runtime.getRuntime().exec()需要註意的地方

window dsta 進程 明顯 trac get win 方法 mes 文章出處http://www.cnblogs.com/fclbky/p/6112180.html 有時候我們可能需要調用系統外部的某個程序,此時就可以用Runtime.getRuntime().e

在solaris上慎用Runtime.getRuntime().exec()

Java程序執行在Solaris上,如果程式碼中用了Runtime.getRuntime().exec(),啟動一個子程序執行一些命令,可能出現子程序掛住,導致父程序退出時,父程序所佔用的資源仍然沒有釋放,如埠等資訊,用ps -ef仍然可以看到父程序的資訊。用pstack可以看到fork資訊,在Ru

Android用SharedPreferences儲存資料實現註冊登入功能(首次安裝預設開啟註冊,記住密碼)

註冊介面xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

Android listView item側滑實現刪除置頂功能

         第一次寫部落格,先說下大概思路吧~         要顯示item側滑顯示刪除,置頂。首先要隱藏一部分item的佈局(自定義隱藏佈局寬度,在adapter裡設定LayoutParams)。然後重寫listview的onInterceptTouchEvent()和onTouchEvent(

Java執行Windows Dos bat指令碼:Runtime.getRuntime().exec

用Java編寫應用時,有時需要在程式中呼叫另一個現成的可執行程式或系統命令,這時可以通過組合使用Java提供的Runtime類和Process類的方法實現。下面是一種比較典型的程式模式:    ...   Process   process   =   Runtime.

【區塊鏈】Android通過Geth RPC介面實現接入以太坊私有鏈

Android通過Geth RPC介面實現接入以太坊私有鏈 環境:mac os & android studio 一、啟動私有鏈 搭建方法見 here 啟動並設定RPC埠: geth --identity "linoy" --rpc -

Runtime.getRuntime().exec() 輸出流阻塞解決方法

Java中用Runtime.getRuntime().exec() 呼叫外部程式, 獲取"標準輸出流", 老是阻塞. 在網上找了找, 覺得應該是"錯誤輸出流"的問題. 果然, 為"錯誤輸出流"單開一個執行緒讀取之, "標準輸出流"就不再阻塞了. 原始碼如下: /**

java Runtime.getRuntime().exec 呼叫系統指令碼/命令注意事項

錯誤的方法: //CPUID private static final String cpuid="dmidecode -t processor | grep 'ID' | head -1"; Process p = Runtime.getRuntime().exec

Runtime.getRuntime().exec執行阻塞問題解決

有時候我們可能需要呼叫系統外部的某個程式,此時就可以用Runtime.getRuntime().exec()來呼叫,他會生成一個新的程序去執行呼叫的程式。 此方法返回一個java.lang.Process物件,該物件可以得到之前開啟的程序的執行結果,還可以操作程序的輸入