You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何检测WiFi已连接但无网络(流量超限/无信号)?Android技术咨询

老哥,你碰到的这个问题我太熟了——之前做项目也踩过这个坑!ConnectivityManager只能告诉你设备连上了某个网络,但没法确认这个网络真的能打通互联网(比如WiFi连了但路由器没插网线、或者网络被墙了的情况)。我给你几个靠谱的实现方案,按需选:

方案1:发起轻量级网络请求(最精准,推荐)

要判断真的能上网,最直接的就是发个极小的请求到稳定的公共服务,比如Google的generate_204接口(返回空内容,流量可以忽略不计,而且服务器稳定性拉满)。

注意:必须在子线程执行,不能阻塞主线程!

给你Java的示例代码:

// 先保留你原来的「是否连了网络」检测方法
public static boolean isConnectedToNetwork(Context context) {
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (cm == null) return false;
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    return activeNetwork != null && activeNetwork.isConnected();
}

// 核心:检测是否能实际访问互联网
public static boolean hasInternetAccess(Context context) {
    // 先判断有没有连网络,没连直接返回false
    if (!isConnectedToNetwork(context)) {
        return false;
    }

    try {
        // 用Google的generate_204接口,无内容返回,流量极小
        URL url = new URL("http://clients3.google.com/generate_204");
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setRequestProperty("User-Agent", "Android");
        urlConnection.setRequestProperty("Connection", "close");
        urlConnection.setConnectTimeout(1500); // 1.5秒超时,别设太长影响体验
        urlConnection.connect();
        // 204状态码+内容长度为0,说明请求成功
        return (urlConnection.getResponseCode() == 204 && urlConnection.getContentLength() == 0);
    } catch (IOException e) {
        Log.e("InternetCheck", "检测互联网连接出错", e);
    }
    return false;
}

额外注意点:

  • 必须在AndroidManifest.xml里申请权限:<uses-permission android:name="android.permission.INTERNET" />
  • Android 10及以上禁止主线程网络请求,所以要配合线程执行。比如手动开线程:
// 示例:开子线程执行检测
new Thread(() -> {
    boolean hasInternet = hasInternetAccess(MainActivity.this);
    // 回到主线程更新UI或处理结果
    runOnUiThread(() -> {
        if (hasInternet) {
            // 有网逻辑
        } else {
            // 无网逻辑
        }
    });
}).start();
方案2:用NetworkCapabilities(Android 10+,无需发请求)

从Android 10(API 29)开始,系统提供了NetworkCapabilities来判断网络是否具备互联网访问能力,这是系统层面的判断,不用发请求,但偶尔会有不准的情况(比如网络被墙但系统认为有网)。

示例代码:

@RequiresApi(api = Build.VERSION_CODES.M)
public static boolean hasInternetCapability(Context context) {
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (cm == null) return false;

    Network activeNetwork = cm.getActiveNetwork();
    if (activeNetwork == null) return false;

    NetworkCapabilities capabilities = cm.getNetworkCapabilities(activeNetwork);
    // NET_CAPABILITY_VALIDATED表示系统已验证该网络能访问互联网
    return capabilities != null 
            && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
}

如果你的APP只针对Android 10+,可以用这个做快速判断,再结合方案1做最终验证,兼顾性能和准确性。

方案3:Ping命令(不推荐)

也可以执行系统的ping命令,但需要ACCESS_NETWORK_STATE权限,而且不同设备的命令参数可能有差异,还可能被厂商限制,所以一般不建议用这个方案。


总结一下:

  • 100%精准判断,优先选方案1;
  • 追求性能不想发请求,Android 10+可以用方案2做初步判断,再用方案1兜底;
  • 别依赖ConnectivityManagerisAvailable(),它真的只是告诉你网络硬件可用,不是能上网。

内容的提问来源于stack exchange,提问作者Nuwan Withanage

火山引擎 最新活动