美文网首页Android深入
Android 使用ping判断网络/WIFI连接是否可用

Android 使用ping判断网络/WIFI连接是否可用

作者: 光羽隼 | 来源:发表于2018-09-04 17:32 被阅读0次

最近项目中有一个网络判断的需求,因为终端只能连接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;
    }

相关文章

网友评论

    本文标题:Android 使用ping判断网络/WIFI连接是否可用

    本文链接:https://www.haomeiwen.com/subject/mafnwftx.html