最近项目中有一个网络判断的需求,因为终端只能连接wifi,wifi即使连接上也可能会出现不能连接网络的问题,所以需要进行网络连接的判断。
ping的相关知识
使用ping检验网络是否可以连接
ping就是检测客户端是否可以上网。
那么我们就上代码
该段代码来自http://blankj.com
导入常用工具包compile 'com.blankj:utilcode:1.9.8'
这个里边有各种各样的常用的工具类,下边的代码是NetworkUtils
的一个方法;
/**
* 判断网络是否可用
* <p>需添加权限 {@code <uses-permission android:name="android.permission.INTERNET"/>}</p>
* <p>需要异步ping,如果ping不通就说明网络不可用</p>
*
* @param ip ip地址(自己服务器ip),如果为空,ip为阿里巴巴公共ip
* @return {@code true}: 可用<br>{@code false}: 不可用
*/
public static boolean isAvailableByPing(String ip) {
if (ip == null || ip.length() <= 0) {
ip = "223.5.5.5";// 阿里巴巴公共ip
}
ShellUtils.CommandResult result = ShellUtils.execCmd(String.format("ping -c 1 %s", ip), false);
boolean ret = result.result == 0;
if (result.errorMsg != null) {
Log.d("NetworkUtils", "isAvailableByPing() called" + result.errorMsg);
}
if (result.successMsg != null) {
Log.d("NetworkUtils", "isAvailableByPing() called" + result.successMsg);
}
return ret;
}
这段代码完全可以作为网络检测的使用,可是我在使用这段代码的时候偶尔会遇到anr的问题。出现anr就说明在主线程做了耗时操作,这是我没有将这段代码放到子线程造成的问题。其实ping也就相当于去请求网络,跟普通的接口请求差不多,当网络比较慢的时候就会消耗时间,放在主线程就会造成anr。
在修改bug的时候我对这段代码进行了一些修改:
* 判断网络是否可用
* <p>需添加权限 {@code <uses-permission android:name="android.permission.INTERNET"/>}</p>
* <p>需要异步ping,如果ping不通就说明网络不可用</p>
*
* @param ip ip地址(自己服务器ip),如果为空,ip为阿里巴巴公共ip
* @return {@code true}: 可用<br>{@code false}: 不可用
*/
public static boolean isAvailableByPing(String ip) {
if (ip == null || ip.length() <= 0) {
ip = "223.5.5.5";// 阿里巴巴公共ip
}
Runtime runtime = Runtime.getRuntime();
Process ipProcess = null;
try {
//-c 后边跟随的是重复的次数,-w后边跟随的是超时的时间,单位是秒,不是毫秒,要不然也不会anr了
ipProcess = runtime.exec("ping -c 3 -w 3 "+ip);
int exitValue = ipProcess.waitFor();
Log.i("Avalible", "Process:" + exitValue);
return (exitValue == 0);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
} finally {
//在结束的时候应该对资源进行回收
if (ipProcess != null) {
ipProcess.destroy();
}
runtime.gc();
}
return false;
}
只需要把这个方法引用到子线程中就行了,其实不引用也可以,因为在这里设定了超时时间为3秒。但是最好是放到子线程里边。
问题补充
上边的代码在Android 7.1.2中出现了问题,好好的WIFI连接上之后,ping不通,每次waitfor都返回1,返回一表示WiFi连接,但是没有网络。其实是有网络的,很奇怪。
解决方法:
这里我获取了ping时抓包的信息,判断是否丢包为100%。如果为100%,就说明网络有问题。不是100%说明网络连接没问题。
废话不多说,直接上代码!老铁双击666,,哈哈😄
public boolean isNetworkOnline() {
Runtime runtime = Runtime.getRuntime();
Process ipProcess = null;
try {
ipProcess = runtime.exec("ping -c 5 -w 4 223.5.5.5");
InputStream input = ipProcess.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(input));
StringBuffer stringBuffer = new StringBuffer();
String content = "";
while ((content = in.readLine()) != null) {
stringBuffer.append(content);
}
int exitValue = ipProcess.waitFor();
if (exitValue == 0) {
//WiFi连接,网络正常
return true;
} else {
if (stringBuffer.indexOf("100% packet loss") != -1) {
//网络丢包严重,判断为网络未连接
return false;
} else {
//网络未丢包,判断为网络连接
return true;
}
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
} finally {
if (ipProcess != null) {
ipProcess.destroy();
}
runtime.gc();
}
return false;
}