Android开发:如何检测互联网真实可用状态及连接变化?
解决Android互联网连接真实可用性检测的问题
嘿,作为Android开发新手,碰到这个需求太常见啦!你之前的代码确实只能判断设备是否连接到了本地网络(比如Wi-Fi、移动数据),但没法验证是否真的能访问互联网——毕竟很多时候设备连了热点但热点本身没网,这种情况你的代码会误判。我来给你几个实用的解决方案:
一、推荐方案:使用ConnectivityManager.NetworkCallback + 轻量网络请求
从Android 7.0(API 24)开始,NetworkInfo就被标记为废弃了,官方推荐用NetworkCallback来监听网络状态变化,再结合一个轻量的网络请求来验证互联网可用性。
1. 添加必要权限
首先在AndroidManifest.xml里添加权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
2. 实现网络状态监听与互联网验证
class NetworkMonitor(private val context: Context) { private val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager private lateinit var networkCallback: ConnectivityManager.NetworkCallback fun startMonitoring() { val request = NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .build() networkCallback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { super.onAvailable(network) // 网络已连接,现在验证是否能访问互联网 CoroutineScope(Dispatchers.IO).launch { val hasInternet = isInternetAvailable() // 在这里处理结果:比如通知UI更新状态 withContext(Dispatchers.Main) { if (hasInternet) { // 设备已连接网络且互联网可用 } else { // 设备已连接网络但无互联网 } } } } override fun onLost(network: Network) { super.onLost(network) // 网络断开,处理对应的状态 } } connectivityManager.registerNetworkCallback(request, networkCallback) } fun stopMonitoring() { try { connectivityManager.unregisterNetworkCallback(networkCallback) } catch (e: IllegalArgumentException) { // 避免重复注销的异常 } } private suspend fun isInternetAvailable(): Boolean { return try { // 用谷歌的generate_204接口,轻量无内容,适合检测 val url = URL("http://clients3.google.com/generate_204") val connection = url.openConnection() as HttpURLConnection connection.connectTimeout = 3000 // 3秒超时 connection.readTimeout = 3000 connection.responseCode == HttpURLConnection.HTTP_NO_CONTENT } catch (e: Exception) { false } } }
3. 使用说明
在你的Activity或者Application里初始化并启动监听:
class MainActivity : AppCompatActivity() { private lateinit var networkMonitor: NetworkMonitor override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) networkMonitor = NetworkMonitor(this) } override fun onStart() { super.onStart() networkMonitor.startMonitoring() } override fun onStop() { super.onStop() networkMonitor.stopMonitoring() } }
二、兼容旧版本的方案:BroadcastReceiver(不推荐,但可用)
如果需要兼容Android 7.0以下的设备,可以用BroadcastReceiver监听网络变化,同样结合网络请求验证:
class NetworkReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (intent?.action == ConnectivityManager.CONNECTIVITY_ACTION) { val cm = context?.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? cm?.activeNetworkInfo?.let { networkInfo -> if (networkInfo.isConnected) { // 网络已连接,验证互联网可用性 CoroutineScope(Dispatchers.IO).launch { val hasInternet = isInternetAvailable() // 处理结果 } } } } } private suspend fun isInternetAvailable(): Boolean { // 和上面的实现一样 return try { val url = URL("http://clients3.google.com/generate_204") val connection = url.openConnection() as HttpURLConnection connection.connectTimeout = 3000 connection.readTimeout = 3000 connection.responseCode == HttpURLConnection.HTTP_NO_CONTENT } catch (e: Exception) { false } } }
然后在Manifest里注册Receiver:
<receiver android:name=".NetworkReceiver"> <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter> </receiver>
注意事项
- 不要频繁发起网络检测,避免消耗过多流量和电量,可以加个防抖机制(比如两次检测间隔至少5秒)。
- 网络请求必须在子线程执行,这里用了协程,你也可以用
OkHttp等网络库简化请求。 - 如果你的应用面向国内用户,也可以把检测地址换成国内的可靠接口(比如
http://www.baidu.com,但要注意处理响应)。
内容的提问来源于stack exchange,提问作者Mr e
相关产品推荐
相关产品推荐

