編輯:關於Android編程
在Android中想要進行Ping,在不Root機器的情況下似乎還只能進行底層命調用才能實現。
因為在Java中要進行ICMP包發送需要Root權限。
於是只能通過創建進程來解決了,創建進程在Java中有兩種方式,分別為:
1. 調用ProcessBuilder的構造函數後執行start()
2. 用Runtime.getRuntime().exec()方法執行
經過使用後發現兩者有區別但是也並不是很大,兩個例子說明:
1.調用ProcessBuilder的構造函數後執行start():
Process process = new ProcessBuilder("/system/bin/ping").redirectErrorStream(true).start();
OutputStream stdout = process.getOutputStream();
InputStream stdin = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdin));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdout));Process process = Runtime.getRuntime().exec("/system/bin/ping");
OutputStream stdout = process.getOutputStream();
InputStream stderr = process.getErrorStream();
InputStream stdin = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdin));
BufferedReader err= new BufferedReader(new InputStreamReader(stderr));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdout));使用ProcessBuilder,可以通過redirectErrorStream(true)將錯誤輸出流轉移到標准輸出流中,這樣使用一次process.getInputStreamReader()就能讀出該進程的所有輸出。
而使用Runtime.getRuntime().exec()方法時,錯誤的輸出流還需通過process.getErrorStream()來獲得。
分享一個自己集合的一個進程執行後銷毀的類:
import java.io.InputStream;
import java.io.OutputStream;
public class ProcessModel {
/**
* 通過Android底層實現進程關閉
*
* @param process
*/
public static void killProcess(Process process) {
int pid = getProcessId(process.toString());
if (pid != 0) {
try {
android.os.Process.killProcess(pid);
} catch (Exception e) {
try {
process.destroy();
} catch (Exception ex) {
}
}
}
}
/**
* 獲取當前進程的ID
*
* @param str
* @return
*/
public static int getProcessId(String str) {
try {
int i = str.indexOf("=") + 1;
int j = str.indexOf("]");
String cStr = str.substring(i, j).trim();
return Integer.parseInt(cStr);
} catch (Exception e) {
return 0;
}
}
/**
* 關閉進程的所有流
*
* @param process
*/
public static void closeAllStream(Process process) {
try {
InputStream in = process.getInputStream();
if (in != null)
in.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
InputStream in = process.getErrorStream();
if (in != null)
in.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
OutputStream out = process.getOutputStream();
if (out != null)
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 銷毀一個進程
*
* @param process
*/
public static void processDestroy(Process process) {
if (process != null) {
try {
if (process.exitValue() != 0) {
closeAllStream(process);
killProcess(process);
}
} catch (IllegalThreadStateException e) {
closeAllStream(process);
killProcess(process);
}
}
}
/**
* 通過線程進行異步銷毀
*
* @param process
*/
public static void asyncProcessDestroy(final Process process) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
processDestroy(process);
}
});
thread.setDaemon(true);
thread.start();
}
}
奇怪的是,當使用線程進行大量的進程創建,最後達到一定數量(大約為1000個左右)的時候將會出現無法創建進程的情況;
此情況我不知怎麼解決,自己想的是弄一個線程池裡邊放20個已經創建的進程,而外部的線程重復利用以及創建的進程,不知這樣是否可行?
望大家探討一下解決方法,謝謝了。
Android Activity的啟動過程
每天看郭神的公眾號文章已經成了我的一個習慣,前段時間看到一篇文章,ActivityThread的main()方法究竟做了什麼工作?main方法代碼並不長,但行行珠玑。我也
Android FM模塊學習之一 FM啟動流程
最近在學習FM模塊,FM是一個值得學習的模塊,可以從上層看到底層。上層就是FM的按扭操作和界面顯示,從而調用到FM底層驅動來實現廣播收聽的功能。 看看
Android好奇寶寶_05_PopupWindow與懸浮窗
之所以把PopupWindow與懸浮窗這兩個放到一起講,是因為這兩個的實現原理基本是一致的,只是有點不同而已。 原理: 使用系統服務(WindowManag
安卓開發與分析者的利器--安卓右鍵工具
安卓右鍵工具,集成dex轉jar,二進制xml查看,apk相關信息查詢,apk圖標提取,apk優化,手機屏幕截圖,安裝卸載,簽名,反編譯和回編譯等功能,方便快捷,開發者們