美文网首页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