如何检测Android已连接WiFi但无互联网连接的状态
Android平台可靠网络连接检测方案(适配Unity项目)
你的现有代码只判断了设备连接的网络传输类型(WiFi/蜂窝/以太网),但没有验证该网络是否真正能访问互联网——这就是为什么连接无网WiFi时会误判为CONNECTIVITY_WIFI的原因。
修复现有代码:加入互联网连通性验证
从Android API 23开始,NetworkCapabilities提供了两个关键能力来判断网络有效性:
NET_CAPABILITY_INTERNET:网络具备访问互联网的权限NET_CAPABILITY_VALIDATED:系统已验证该网络可以实际访问互联网(比如通过网关检测、DNS解析等)
修改后的代码如下:
// for Build.VERSION.SDK_INT > 23 int connectionType = NO_CONNECTIVITY; Network[] networksList = connectivityManager.getAllNetworks(); int len = networksList.length; if(len == 0) { return NO_CONNECTIVITY; } for(Network network : networksList) { NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(network); if(networkCapabilities == null) { continue; } // 先验证网络是否具备有效互联网访问能力 boolean hasValidInternet = networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); if(!hasValidInternet) { continue; // 跳过无有效互联网的网络 } // 再判断网络传输类型,优先级:以太网 > WiFi > 蜂窝 if(networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) { connectionType = CONNECTIVITY_ETHERNET; break; // 以太网优先级最高,直接跳出循环 } else if(networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) && !networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_WIFI_P2P)) { connectionType = CONNECTIVITY_WIFI; } else if(networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { if(connectionType != CONNECTIVITY_WIFI) { connectionType = CONNECTIVITY_CELLULAR; } } } return connectionType;
其他可行的Android原生方案
1. 使用NetworkCallback实时监听网络状态
主动轮询不如监听网络状态变化高效,你可以注册ConnectivityManager.NetworkCallback,在网络连接、断开或验证状态变化时收到回调:
ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(Network network) { // 网络可用,可在此验证有效性并更新状态 NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network); boolean isValid = capabilities != null && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); if(isValid) { // 更新为有效连接状态 } } @Override public void onLost(Network network) { // 网络断开,更新为无连接状态 } @Override public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { // 网络能力变化,重新验证有效性 boolean isValid = networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); // 更新状态 } }; // 注册回调 connectivityManager.registerNetworkCallback( new NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .build(), networkCallback );
2. 轻量级网络探测(极端场景兜底)
如果某些特殊网络环境下NET_CAPABILITY_VALIDATED不准确(比如企业内网、特殊代理环境),可以发起一个HEAD请求到一个稳定的、资源极小的端点(比如自己服务器的空接口,或公共的静态资源),避免使用ping(ping可能被防火墙拦截)。示例:
private boolean isInternetAvailable() { try { HttpURLConnection urlConnection = (HttpURLConnection) new URL("https://your-server.com/ping").openConnection(); urlConnection.setRequestMethod("HEAD"); urlConnection.setConnectTimeout(1000); // 1秒超时 urlConnection.setReadTimeout(1000); return urlConnection.getResponseCode() == 200; } catch (Exception e) { return false; } }
注意:要在子线程执行此操作,避免阻塞UI线程;同时需要申请INTERNET权限。
适配Unity的建议
将修改后的Android代码打包成AAR包,在Unity项目中通过AndroidJavaClass或AndroidJavaObject调用原生方法,实现跨平台的网络检测逻辑(后续iOS平台可类似实现原生检测)。
内容的提问来源于stack exchange,提问作者Isma Rekathakusuma
相关产品推荐
相关产品推荐

