在 Android 中检查网络是否可用,通常需要检查两个层面:网络连接是否存在 和 网络是否可以正常访问。

这是一个非常重要且常见的任务,因为仅仅有网络连接(比如连上了Wi-Fi)不代表一定能上网(比如Wi-Fi需要登录认证)。
下面我将从简单到复杂,为你介绍几种检查网络的方法,并给出推荐的实践方案。
使用 ConnectivityManager (标准方法)
这是 Android 官方推荐的方法,用于获取网络连接状态。
检查网络连接是否存在
这个方法只能告诉你设备是否连接到了某个网络(Wi-Fi、移动数据等),但不能保证一定能上网。

import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
fun isNetworkConnected(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
// 对于 Android 10 (API 29) 及以上版本
val activeNetwork: Network? = connectivityManager.activeNetwork
return activeNetwork != null
}
注意:在 Android 9 (API 28) 及以下版本,activeNetwork 不可用,你需要使用旧方法:
// 适用于 Android 9 (API 28) 及以下
fun isNetworkConnectedLegacy(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkInfo = connectivityManager.activeNetworkInfo
return networkInfo != null && networkInfo.isConnected
}
检查网络是否可以访问 (更可靠的方法)
为了确保网络是“活的”,你需要尝试进行一个实际的连接,Android 提供了 NetworkCapabilities 来检查网络的详细能力,并且推荐使用 ConnectivityManager.registerNetworkCallback 来监听网络变化。
使用 NetworkCapabilities (API 23+)
这个方法可以检查网络是否满足特定条件,比如是否有互联网访问能力。
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
fun isInternetAvailable(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
// 对于 Android 10 (API 29) 及以上版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val network = connectivityManager.activeNetwork ?: return false
val activeNetworkCapabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
return activeNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
activeNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
} else {
// 对于 Android 9 (API 28) 及以下版本
@Suppress("DEPRECATION")
val networkInfo = connectivityManager.activeNetworkInfo
return networkInfo != null && networkInfo.isConnected && networkInfo.isAvailable
}
}
NET_CAPABILITY_INTERNET: 网络被配置为提供互联网连接。NET_CAPABILITY_VALIDATED: 网络连接已成功验证可以访问互联网,这是比isConnected更可靠的指标。
执行 Ping 操作 (最可靠但最慢)
这是最准确的方法,因为它真的尝试去发送一个网络请求,但缺点是耗时较长,不能在主线程执行,并且可能会因为防火墙或策略限制而失败。

import java.io.IOException
import java.net.InetSocketAddress
import java.net.Socket
// 在后台线程调用此方法
fun isInternetReachable(): Boolean {
return try {
val timeoutMs = 1500
val socket = Socket()
val socketAddress = InetSocketAddress("8.8.8.8", 53) // Google DNS
socket.connect(socketAddress, timeoutMs)
socket.close()
true
} catch (e: IOException) {
false
}
}
- 为什么用
8.8.8和53端口?8.8.8是 Google 的公共 DNS 服务器,它通常稳定且可访问。- 端口
53是 DNS 端口,通常防火墙很少会封锁这个端口,比尝试80(HTTP) 端口的成功率更高。
使用第三方库 (简化开发)
为了简化代码处理,特别是处理不同 Android 版本的兼容性问题,开发者通常会选择使用成熟的第三方库。
推荐:android-networking
这是一个功能强大的网络库,内置了网络状态检查功能。
添加依赖:
// build.gradle (Module: app) implementation 'com.amitshekhar.android:android-networking:1.0.2'
初始化:
在 Application 类的 onCreate() 方法中初始化。
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
AndroidNetworking.initialize(applicationContext)
}
}
检查网络状态:
import com.androidnetworking.AndroidNetworking
import com.androidnetworking.error.ANError
// 检查网络是否可用,并自动处理不同版本
fun isNetworkAvailable(context: Context): Boolean {
return AndroidNetworking.get("https://www.google.com") // 可以用任意一个可靠地址
.setPriority(Priority.LOW)
.build()
.isStarted // 这个方法不会真正发送请求,只是检查连接
}
// 更可靠的方式:执行一个简单的 HEAD 请求来检查网络
fun isInternetReachableWithLibrary() {
AndroidNetworking.head("https://www.google.com")
.setPriority(Priority.LOW)
.build()
.setRequestListener { _, error ->
if (error == null) {
// 网络可用
println("Internet is reachable")
} else {
// 网络不可用
println("Internet is not reachable: ${error.errorDetail}")
}
}
}
最佳实践:结合使用 + 监听网络变化
一个健壮的应用应该能够:
- 在需要时检查网络状态。
- 在后台持续监听网络变化,以便在网络恢复时自动重试失败的操作。
完整示例:监听网络变化的广播接收器
创建 NetworkChangeReceiver.kt
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
class NetworkChangeReceiver : BroadcastReceiver() {
interface NetworkStateListener {
fun onNetworkStateChanged(isConnected: Boolean)
}
private var listener: NetworkStateListener? = null
fun setListener(listener: NetworkStateListener) {
this.listener = listener
}
override fun onReceive(context: Context, intent: Intent?) {
if (intent?.action == ConnectivityManager.CONNECTIVITY_ACTION) {
val isConnected = isInternetAvailable(context) // 使用前面介绍的可靠方法
listener?.onNetworkStateChanged(isConnected)
}
}
// ... 这里可以放上前面 isInternetAvailable() 的实现 ...
}
在 Activity 或 Service 中注册和注销
import android.content.IntentFilter
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity(), NetworkChangeReceiver.NetworkStateListener {
private lateinit var networkChangeReceiver: NetworkChangeReceiver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
networkChangeReceiver = NetworkChangeReceiver()
networkChangeReceiver.setListener(this)
// 注册广播接收器
val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
registerReceiver(networkChangeReceiver, filter)
}
override fun onDestroy() {
super.onDestroy()
// 注销广播接收器,防止内存泄漏
unregisterReceiver(networkChangeReceiver)
}
override fun onNetworkStateChanged(isConnected: Boolean) {
if (isConnected) {
Toast.makeText(this, "网络已连接", Toast.LENGTH_SHORT).show()
// 在这里可以重试之前失败的网络请求
} else {
Toast.makeText(this, "网络已断开", Toast.LENGTH_SHORT).show()
// 在这里可以停止正在进行的网络请求,并提示用户
}
}
}
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
ConnectivityManager |
官方标准,无需额外依赖 | 处理多版本兼容性稍显繁琐 | 所有标准应用,推荐作为基础方案。 |
| 执行 Ping | 最准确,能真实反映网络可达性 | 耗时较长,不能在主线程,可能被防火墙拦截 | 在关键操作前(如下载大文件前)进行一次最终确认。 |
| 第三方库 | 简化代码,提供高级功能(如自动重试) | 增加项目依赖,可能引入未知问题 | 快速开发,特别是当你的应用网络逻辑复杂时。 |
推荐策略:
- 日常检查:使用
ConnectivityManager+NetworkCapabilities(方案一) 来快速判断网络是否可用。 - 关键操作前:在执行重要网络请求前,可以增加一个轻量级的 Ping 操作作为二次确认。
- 后台监听:实现一个
BroadcastReceiver来持续监听网络变化,提升用户体验。 - 项目复杂时:考虑使用
android-networking或Retrofit+OkHttp这样的成熟网络库,它们通常已经内置了健壮的网络状态处理机制。
