安卓如何检查WiFi是否连接但无网络连接

17

我的安卓设备已连接到WiFi,但如果WiFi已连接但没有互联网连接,该怎么办?

以下是我尝试检查无互联网连接的代码:

public static boolean isConnectedWifi(Context context) {
        NetworkInfo info=null;
        if(context!=null){
            info= IsNetConnectionAvailable.getNetworkInfo(context);
        }
        return (info != null && info.isConnected() && info.getType() == ConnectivityManager.TYPE_WIFI);
    }

没有网络连接时,它总是返回 true。


嘿,你解决了这个问题吗? - benzabill
5个回答

17

NetworInfo.isAvailableNetworkInfo.isConnected只能表明网络连接是否可能或存在,它们无法表明连接情况是否可以访问公共互联网,简而言之,它们不能告诉我们设备确实在线。

要检查设备是否在线,请尝试以下方法:

第一种方法:

@TargetApi(Build.VERSION_CODES.M)
public static boolean isNetworkOnline1(Context context) {
    boolean isOnline = false;
    try {
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkCapabilities capabilities = manager.getNetworkCapabilities(manager.getActiveNetwork());  // need ACCESS_NETWORK_STATE permission
        isOnline = capabilities != null && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
    } catch (Exception e) {
        e.printStackTrace();
    }

    return isOnline;
}

强项:1.可以在UI线程上运行;2.快速且准确。

弱项:需要API>=23,且存在兼容性问题。

第二点:

public static boolean isNetworkOnline2() {
    boolean isOnline = false;
    try {
        Runtime runtime = Runtime.getRuntime();
        Process p = runtime.exec("ping -c 1 8.8.8.8");
        int waitFor = p.waitFor();
        isOnline = waitFor == 0;    // only when the waitFor value is zero, the network is online indeed

        // BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
        // String str;
        // while ((str = br.readLine()) != null) {
        //     System.out.println(str);     // you can get the ping detail info from Process.getInputStream()
        // }
    } catch (IOException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    return isOnline;
}

优点:1. 可以在UI线程上运行;2. 您可以多次ping并统计最小/平均/最大延迟时间和丢包率。

缺点:兼容性问题

第三点:

public static boolean isNetworkOnline3() {
    boolean isOnline = false;
    try {
        URL url = new URL("http://www.google.com"); // or your server address
        // URL url = new URL("http://www.baidu.com");
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestProperty("Connection", "close");
        conn.setConnectTimeout(3000);
        isOnline = conn.getResponseCode() == 200;
    } catch (IOException e) {
        e.printStackTrace();
    }

    return isOnline;
}

优点:可在所有设备和API上使用。

缺点:操作耗时,不能在UI线程上运行。

第四:

public static boolean isNetworkOnline4() {
    boolean isOnline = false;
    try {
        Socket socket = new Socket();
        socket.connect(new InetSocketAddress("8.8.8.8", 53), 3000);
        // socket.connect(new InetSocketAddress("114.114.114.114", 53), 3000);
        isOnline = true;
    } catch (IOException e) {
        e.printStackTrace();
    }

    return isOnline;
}

优点:1. 可在所有设备和API上使用;2. 相对快速且准确。

缺点:操作耗时,不能在UI线程上运行。


4

请查看以下代码集合。

public boolean isNetworkAvailable(Context context) {
        boolean isOnline = false;
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        try {
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
                NetworkCapabilities capabilities = manager.getNetworkCapabilities(manager.getActiveNetwork());
                isOnline = capabilities != null && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
            } else {
                NetworkInfo activeNetworkInfo = manager.getActiveNetworkInfo();
                isOnline = activeNetworkInfo != null && activeNetworkInfo.isConnectedOrConnecting();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return isOnline;
    }

完美解决方案 - Vishal Yadav
我不知道为什么,但它只在特定情况下工作,而不是每次都有效。 - PRANAV SINGH

2

在搜索了几天并尝试了各种解决方案后,有些不完美,有些太长,以下是LEVIT提出的使用SOCKETS的解决方案,对我来说非常完美。任何搜索此解决方案的人都可以参考此帖子。 如何在Android上检查互联网访问? InetAddress永远不会超时

以下是AsyncTask中任务示例的代码部分

class InternetCheck extends AsyncTask<Void,Void,Boolean> {

    private Consumer mConsumer;
    public  interface Consumer { void accept(Boolean internet); }

    public  InternetCheck(Consumer consumer) { mConsumer = consumer; execute(); }

    @Override protected Boolean doInBackground(Void... voids) { try {
        Socket sock = new Socket();
        sock.connect(new InetSocketAddress("8.8.8.8", 53), 1500);
        sock.close();
        return true;
    } catch (IOException e) { return false; } }

    @Override protected void onPostExecute(Boolean internet) { mConsumer.accept(internet); }
}
///////////////////////////////////////////////////////////////////////////////////
// Usage

    new InternetCheck(internet -> { /* do something with boolean response */ });

以下是与解决方案相关的摘要 可能的问题 它真的足够快吗?
是的,非常快 ;-)
除了在互联网上测试某些内容之外,还有没有可靠的检查互联网的方法?
据我所知没有,但如果您知道,请告诉我,我会编辑我的答案。
如果DNS出现故障怎么办?
Google DNS(例如8.8.8.8)是世界上最大的公共DNS。截至2013年,它每天提供1300亿个请求。让我们这样说,您的应用程序可能不会成为当天的热门话题。
需要哪些权限?
<uses-permission android:name="android.permission.INTERNET" />

如果这个答案有一些技术上的缺陷,请在投票之前详细说明,因为对我来说,这个答案是有效的,我将其发布在这里,以便其他搜索相同问题的人可以在这里或给定的链接中找到答案。谢谢。 - Waqas Haider
如果我需要检查设备中特定网络的互联网连接怎么办?这个解决方案能否使用特定的Network对象进行翻译? - Ivan Garza
完美运作 - PRANAV SINGH

1
你现在使用的代码只是用来检查你是否连接到wifi,但它并不能检查wifi的速度是否慢。(没有网络就意味着连接速度慢)
我尝试使用了这段代码。在这里,我试图访问google.com并设置了一个连接超时值。如果这里的网络速度很好,那么返回的结果是200。所以我检查结果代码是否为200。如果不是,我会弹出一个警告,提示有慢速的互联网连接。将其用在asyntask中,并在onPostExecute()中检查返回结果的值。
HttpURLConnection urlc = null;
    try {
        urlc = (HttpURLConnection) (new URL("http://www.google.com")
                .openConnection());
    } catch (MalformedURLException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    urlc.setRequestProperty("User-Agent", "Test");
    urlc.setRequestProperty("Connection", "close");
    urlc.setConnectTimeout(1000); // choose your own timeframe
    urlc.setReadTimeout(2000); // choose your own timeframe
    try {
        urlc.connect();

        // returning connection code.
        return (urlc.getResponseCode());
    } catch (IOException e1) {
        e1.printStackTrace();
    }

我花了很多时间检查互联网连接。 - Ganesh Gudghe
有没有其他方法可以检查? - Ganesh Gudghe
您可以尝试使用以下链接:https://dev59.com/r3E85IYBdhLWcg3wYicB - Harish Vats
我也遇到了同样的问题,我正在按照我提供的代码进行操作,它帮助我找到了缓慢的互联网连接。目前还没有一种方法可以检查我们所连接的wifi是否能够ping通。 :) - Harish Vats

-4

如果您想检查是否通过 Wi-Fi 连接到互联网,请查看下面的代码片段:

NetworkInfo getWifi(){
    ConnectivityManager connManager = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
    return mWifi;
}

通过检查连接状态来确定是否已连接;

if(getWifi().isConnected()) {
//wi-fi connected
}

Kaveesh Kanwal,这不是他要求的内容。 你提供的代码片段只是用来检查设备是否连接到WiFi,而不是测试互联网速度。 - Harish Vats
OP没有询问如何检查互联网速度。祝好运。 - Kaveesh Kanwal
他也没有问如何检查设备是否连接到WiFi。 :) 如果没有互联网访问,我们所能做的就是检查该网络上的数据包发送速度。 - Harish Vats
我尝试了这些,但我需要检查Wi-Fi连接和互联网连接两者都。 - Ganesh Gudghe
但是上面的代码只返回了Wi-Fi是否连接。 - Ganesh Gudghe
同时在你的清单文件中包含以下内容: <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> - Kaveesh Kanwal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接