You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 10:57:45