在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));
2.用Runtime.getRuntime().exec()方法执行:
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 ProcessBuilder与Runtime.getRuntime().exec分别创建进程的区别,布布扣,bubuko.com