你应该用哪个方法?
| Android 版本 | 推荐方法 | 优点 | 缺点 |
|---|---|---|---|
| API 23 (Android 6.0) 及以上 | ConnectivityManager.NetworkCallback |
最佳实践、异步、实时、精确 | 实现稍复杂 |
| API 21 (Android 5.0) - API 22 | ConnectivityManager + NetworkRequest |
异步、实时 | API 21-22 的回调不如 API 23+ 稳定 |
| API 1 - API 20 | ConnectivityManager + getNetworkInfo() |
简单直接、同步、代码少 | 已废弃、不精确、无法实时更新 |
使用 NetworkCallback (推荐,API 23+)
这是目前最推荐、最现代的方法,它采用异步回调的方式,可以让你精确地监听网络连接、丢失和状态变化,非常高效且不会阻塞主线程。

添加网络权限
在 AndroidManifest.xml 中,确保你有访问网络的权限。
<!-- 允许应用完全访问网络 --> <uses-permission android:name="android.permission.INTERNET" /> <!-- 允许应用查看网络状态 --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
代码实现
创建一个管理类来封装网络监听逻辑。
import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.os.Build
class NetworkManager(private val context: Context) {
// 定义网络状态变化的回调接口
interface NetworkStateListener {
fun onAvailable()
fun onLost()
}
private var listener: NetworkStateListener? = null
private val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
// 用于注册网络请求的回调
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
// 网络可用时调用
listener?.onAvailable()
}
override fun onLost(network: Network) {
super.onLost(network)
// 网络丢失时调用
listener?.onLost()
}
}
/**
* 注册网络监听
*/
fun register(listener: NetworkStateListener) {
this.listener = listener
val request = NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
// API 24+ 推荐 registerDefaultNetworkCallback
connectivityManager.registerDefaultNetworkCallback(networkCallback)
} else {
// API 23 使用 registerNetworkCallback
connectivityManager.registerNetworkCallback(request, networkCallback)
}
}
/**
* 取消网络监听
*/
fun unregister() {
connectivityManager.unregisterNetworkCallback(networkCallback)
listener = null
}
}
在 Activity 或 ViewModel 中使用
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity(), NetworkManager.NetworkStateListener {
private lateinit var networkManager: NetworkManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
networkManager = NetworkManager(this)
networkManager.register(this)
}
override fun onAvailable() {
// 在主线程中执行UI更新
runOnUiThread {
Toast.makeText(this, "网络已连接", Toast.LENGTH_SHORT).show()
// 可以在这里开始加载网络数据
}
}
override fun onLost() {
runOnUiThread {
Toast.makeText(this, "网络已断开", Toast.LENGTH_SHORT).show()
// 可以在这里停止加载,显示错误提示
}
}
override fun onDestroy() {
super.onDestroy()
// 一定要在 Activity 销毁时取消注册,否则会导致内存泄漏
networkManager.unregister()
}
}
同步检查当前网络状态 (适用于所有版本,但旧方法)
如果你只是想在某个操作(如点击按钮)前快速检查一下当前是否有网络,可以使用同步方法,注意,旧方法 (getNetworkInfo) 已被废弃,新方法 (getNetworkCapabilities) 更精确。
检查是否有任何类型的网络连接
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
fun isNetworkConnected(context: Context): Boolean {
val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// API 23+ 的方法
val activeNetwork = connectivityManager.activeNetwork
val caps = connectivityManager.getNetworkCapabilities(activeNetwork)
return caps != null && (
caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
caps.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) ||
caps.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH)
)
} else {
// API 22 及以下的方法 (已废弃)
@Suppress("DEPRECATION")
val networkInfo = connectivityManager.activeNetworkInfo
return networkInfo != null && networkInfo.isConnected
}
}
检查是否是 Wi-Fi 或移动数据
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
fun isWifiConnected(context: Context): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val caps = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
return caps != null && caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
} else {
@Suppress("DEPRECATION")
val networkInfo = (context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager)
.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
return networkInfo != null && networkInfo.isConnected
}
}
fun isMobileDataConnected(context: Context): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val caps = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
return caps != null && caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
} else {
@Suppress("DEPRECATION")
val networkInfo = (context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager)
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE)
return networkInfo != null && networkInfo.isConnected
}
}
重要注意事项
-
网络 ≠ 可以上网
(图片来源网络,侵删)isNetworkConnected()只能判断设备是否连接到了一个网络(如 Wi-Fi 或移动数据),它不能保证这个网络可以访问互联网。- 你可能连上了一个需要认证的酒店 Wi-Fi,但没有登录,
isNetworkConnected()返回true,但你无法上网。 - 要真正判断是否能上网,最可靠的方法是尝试发起一个网络请求(如访问一个可靠的轻量级服务器)。
-
后台网络限制
- 从 Android 6.0 (API 23) 开始,系统对后台应用的网络访问有严格限制,如果你的应用在后台,
NetworkCallback的回调可能会被延迟或不会触发,前台服务是解决此问题的一种方式。
- 从 Android 6.0 (API 23) 开始,系统对后台应用的网络访问有严格限制,如果你的应用在后台,
-
Wi-Fi 状态广播
- 除了上述方法,你还可以监听系统广播
ConnectivityManager.CONNECTIVITY_ACTION来获取网络状态变化,但这种方法不如NetworkCallback精准和高效,因为它只告诉你“网络状态变了”,但不知道具体变成了什么。
- 除了上述方法,你还可以监听系统广播
-
权限声明
- 对于 Android 10 (API 29) 及更高版本,如果需要查询 Wi-Fi 状态,你还需要在
AndroidManifest.xml中声明:<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
- 对于 Android 10 (API 29) 及更高版本,如果需要查询 Wi-Fi 状态,你还需要在
最佳实践建议
- 对于需要实时响应网络变化的场景(如下载管理器、聊天应用):使用
NetworkCallback,在Application类或ViewModel中进行管理,确保在组件销毁时正确取消注册。 - 对于只需要在执行特定操作前检查的场景(如点击“上传”按钮):使用同步检查方法 (
isNetworkConnected),并给用户友好的提示(如“请检查网络连接后重试”)。

