核心概念
无论使用哪种 API,核心都是通过 ConnectivityManager 这个系统服务来获取网络信息。

使用 BroadcastReceiver (传统方式,适用于旧版 API)
这是最传统的方法,通过监听系统广播来获知网络状态的变化,优点是简单直接,缺点是注册广播和解绑的代码比较繁琐,并且从 Android 8.0 (Oreo) 开始,对隐式广播的接收有严格限制,不推荐在新应用中使用。
添加网络权限
在 AndroidManifest.xml 中必须声明以下权限:
<!-- 允许应用访问网络状态 --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 如果需要检测 Wi-Fi 状态,还需要此权限 --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
创建 BroadcastReceiver
创建一个继承自 BroadcastReceiver 的类,并重写 onReceive 方法。
public class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 检查是否是网络状态变化的广播
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
if (activeNetworkInfo != null && activeNetworkInfo.isConnected()) {
// 网络已连接
Log.d("NetworkChange", "网络已连接: " + activeNetworkInfo.getTypeName());
} else {
// 网络已断开
Log.d("NetworkChange", "网络已断开");
}
}
}
}
在 AndroidManifest.xml 中注册广播
<receiver android:name=".NetworkChangeReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
在 Activity 中动态注册 (可选)
为了避免清单注册的限制,也可以在 Activity 中动态注册和解绑。

// 在 Activity 的 onCreate 中注册 registerReceiver(networkChangeReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_CHANGE)); // 在 Activity 的 onDestroy 中解绑 unregisterReceiver(networkChangeReceiver);
使用 ConnectivityManager.NetworkCallback (推荐方式,API 21+)
这是目前最推荐的方式,它不需要使用广播,而是通过回调的方式监听网络状态的变化,更加高效和现代化。
添加网络权限
与方法一相同,需要在 AndroidManifest.xml 中添加 ACCESS_NETWORK_STATE 权限。
实现 NetworkCallback
创建一个 ConnectivityManager.NetworkCallback 的子类,并重写你关心的回调方法。
public class NetworkCallbackImpl extends ConnectivityManager.NetworkCallback {
@Override
public void onAvailable(Network network) {
// 网络可用时调用
Log.d("NetworkCallback", "网络已连接");
}
@Override
public void onLost(Network network) {
// 网络丢失时调用
Log.d("NetworkCallback", "网络已断开");
}
@Override
public void onUnavailable() {
// 没有任何可用的网络时调用
Log.d("NetworkCallback", "网络不可用");
}
}
在 Activity/Service 中注册和注销回调
private ConnectivityManager.NetworkCallback networkCallback;
private ConnectivityManager connectivityManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
networkCallback = new NetworkCallbackImpl();
// 创建网络请求
NetworkRequest networkRequest = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) // 要求有互联网能力
.build();
// 注册网络回调
connectivityManager.registerNetworkCallback(networkRequest, networkCallback);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 务必在不需要时注销回调,否则会内存泄漏
if (connectivityManager != null && networkCallback != null) {
connectivityManager.unregisterNetworkCallback(networkCallback);
}
}
使用 Kotlin Flow (现代方式,Kotlin + Coroutines)
如果你使用 Kotlin 并且项目使用了 Coroutines,可以结合 NetworkCallback 封装成一个 Flow,这样可以在 ViewModel 或其他地方更优雅地响应网络状态。

添加依赖
确保你的项目已经添加了 Coroutines 依赖。
// build.gradle (Module: app) implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
创建 NetworkStatus 枚举
enum class NetworkStatus {
Available, Unavailable, Lost
}
封装 NetworkCallback 为 Flow
// NetworkCallback.kt
object NetworkCallbackFlow {
fun observeNetworkStatus(context: Context): Flow<NetworkStatus> = callbackFlow {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val callback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
trySend(NetworkStatus.Available)
}
override fun onLost(network: Network) {
trySend(NetworkStatus.Lost)
}
override fun onUnavailable() {
trySend(NetworkStatus.Unavailable)
}
}
val networkRequest = NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build()
connectivityManager.registerNetworkCallback(networkRequest, callback)
// 设置通道关闭时的清理逻辑
awaitClose {
connectivityManager.unregisterNetworkCallback(callback)
}
}
}
在 ViewModel 或 Activity 中使用
// 在 ViewModel 中使用
class MainViewModel : ViewModel() {
private val _networkStatus = MutableStateFlow<NetworkStatus?>(null)
val networkStatus: StateFlow<NetworkStatus?> = _networkStatus
init {
viewModelScope.launch {
NetworkCallbackFlow.observeNetworkStatus(getApplication())
.collect { status ->
_networkStatus.value = status
// 在这里处理网络状态变化
when (status) {
NetworkStatus.Available -> Log.d("ViewModel", "网络已连接")
NetworkStatus.Lost -> Log.d("ViewModel", "网络已断开")
NetworkStatus.Unavailable -> Log.d("ViewModel", "网络不可用")
}
}
}
}
}
使用 Jetpack Compose (最新方式)
如果你的 UI 是用 Jetpack Compose 实现的,官方提供了 ConnectivityStatus 和 ConnectivityMonitor 等工具来简化网络状态的获取。
添加依赖
// build.gradle (Module: app) implementation "androidx.compose.material3:material3:1.1.2" // 或其他版本 implementation "com.google.accompanist:accompanist-permissions:0.32.0" // 包含网络状态监测
(注意:Accompanist 项目已归档,其功能正被官方库取代,具体请查看最新文档)
在 Composable 中使用
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.lifecycle.viewmodel.compose.viewModel
@Composable
fun NetworkStatusScreen(viewModel: MainViewModel = viewModel()) {
val networkStatus by viewModel.networkStatus.collectAsState()
Text(
text = when (networkStatus) {
NetworkStatus.Available -> "网络已连接"
NetworkStatus.Lost -> "网络已断开"
NetworkStatus.Unavailable -> "网络不可用"
null -> "正在检测网络..."
}
)
}
这里的 MainViewModel 就是上面用 Kotlin Flow 封装的那个。
| 方法 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|
| BroadcastReceiver | 简单,兼容性好 | 效率低,代码繁琐,Android 8.0+ 受限 | 维护旧项目 (API < 21) |
| NetworkCallback | 推荐,高效,非阻塞,现代化 | 需要 API 21+ | 所有新项目,Java/Kotlin 均可 |
| Kotlin Flow | 优雅,响应式,易于在 ViewModel 中使用 | 仅限 Kotlin,需要 Coroutines 知识 | Kotlin 项目,MVVM 架构 |
| Jetpack Compose | 与 Compose UI 深度集成,声明式 | 仅限 Compose 项目 | 使用 Compose 的项目 |
对于任何新项目,强烈推荐使用 ConnectivityManager.NetworkCallback,如果你使用 Kotlin 并且项目采用了 MVVM 架构,那么将 NetworkCallback 封装成 Kotlin Flow 是最佳选择,因为它能让你的代码更简洁、更具响应式特性,对于纯 Compose 项目,则应使用 Compose 提供的相关工具。
