NetworkCallback — Android SDK中用于通过ConnectivityManager监控网络状态变化的抽象类。根据Android Developers Documentation (2025),使用NetworkCallback可以让应用程序及时响应连接、断开或连接特性变化。ConnectivityManager.NetworkCallback提供关于网络类型、强制门户和互联网丢失的详细信息,无需不断轮询系统服务。
要点
NetworkCallback — 是来自android.net包的一个抽象类,属于Android SDK的一部分。它旨在通过系统服务ConnectivityManager接收网络连接状态变化的通知。
在NetworkCallback出现之前,开发人员使用广播接收器BroadcastReceiver来跟踪网络。这种方法需要在清单中持续注册,延迟工作,并且不提供关于连接特性的详细信息。Android 5.0 (API 21)引入了NetworkCallback作为更灵活、更高效的替代方案。
回调异步工作:应用程序通过ConnectivityManager订阅事件,系统在网络状态变化时调用回调方法。这消除了定期轮询网络状态的需要,节省了电池和处理器资源。
ConnectivityManager管理设备的所有网络接口 — Wi-Fi、移动数据、Ethernet、VPN。当任何这些接口发生变化时,系统会创建一个Network对象并将其传递给已注册回调的相应方法。每个Network都有一个唯一的标识符,在重新连接时更改。
回调不绑定到特定的网络类型 — 它可以同时跟踪所有可用的接口。为了过滤连接类型,使用NetworkRequest类,在该类中指定所需的传输协议(Wi-Fi、蜂窝数据、Ethernet)和网络能力。
NetworkCallback的注册通过ConnectivityManager.registerNetworkCallback方法进行。第一个参数是描述网络要求的NetworkRequest.Builder,第二个参数是回调实例。运行需要在清单中有ACCESS_NETWORK_STATE权限。
class NetworkMonitor(private val context: Context) {
private val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE)
as ConnectivityManager
private val callback =
object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
Log.d("Network", "可用: ${network}")
}
override fun onLost(network: Network) {
Log.d("Network", "已丢失: ${network}")
}
}
fun register() {
connectivityManager.registerNetworkCallback(
NetworkRequest.Builder().build(), callback
)
}
fun unregister() {
connectivityManager.unregisterNetworkCallback(callback)
}
}
建议在应用程序处于前台时注册NetworkCallback,并在进入后台时取消注册。在Activity中,方便使用onStart和onStop来管理回调的生命周期。在Fragment中 — onResume和onPause。
为了简化注册管理,可以使用Lifecycle-aware组件。AndroidX Lifecycle库允许创建自定义的LifecycleObserver,它会在生命周期状态变化时自动注册和取消回调。
对于后台任务,注册在Service或WorkManager中进行。需要注意的是,在Android 8+中,后台服务的启动受到限制。带有NetworkType的WorkManager是在特定网络状态下执行任务的更可靠方式,因为它与兼容性API集成并考虑了Doze模式。
NetworkCallback提供一组在网络状态变化时调用的方法。并非所有方法都必须重写 — 只需实现应用程序特定任务所需的方法即可。onAvailable和onLost是基本连接监控的最低要求。
| 方法 | 何时调用 | 参数 |
|---|---|---|
| onAvailable | 网络可供使用 | Network — 网络对象 |
| onLost | 网络丢失或断开 | Network — 网络对象 |
| onCapabilitiesChanged | 网络能力已更改 | Network, NetworkCapabilities |
| onBlockedStatusChanged | 阻塞状态已更改 | Network, Boolean |
| onNetworkSuspended | 网络被系统暂停 | Network |
| onNetworkResumed | 网络在暂停后恢复 | Network |
此方法是获取详细网络信息的关键。NetworkCapabilities参数包含标志:NET_CAPABILITY_INTERNET — 互联网访问,NET_CAPABILITY_NOT_METERED — 无限连接,NET_CAPABILITY_NOT_ROAMING — 无漫游。还可以了解信号延迟和带宽。
强制门户(captive portals) — 特殊情况:通过门户连接到公共Wi-Fi网络时,onCapabilitiesChanged方法不会立即显示INTERNET。首先网络可用,但没有互联网 — 需要通过浏览器进行授权。开发人员必须在应用程序逻辑中考虑此延迟。
当系统阻止应用程序的网络流量时调用 — 例如,在开启数据节省模式或限制后台数据时。onBlockedStatusChanged允许应用程序知道其网络请求被暂时禁止,并切换到本地处理。
让我们来看一下用于跟踪互联网访问和处理强制门户的NetworkCallback实际实现。下面的示例展示了对NET_CAPABILITY_INTERNET的检查以及通过HTTP请求到Google服务器验证连接。
val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onCapabilitiesChanged(
network: Network,
caps: NetworkCapabilities
) {
val hasInternet = caps.hasCapability(
NetworkCapabilities.NET_CAPABILITY_INTERNET
)
val isMetered = caps.hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_METERED
).not()
when {
hasInternet && isMetered ->
Log.d("Network", "移动数据已连接")
hasInternet ->
Log.d("Network", "Wi-Fi已连接")
else ->
Log.d("Network", "无互联网访问")
}
}
override fun onLost(network: Network) {
Log.d("Network", "连接已丢失: ${network}")
// 停止网络请求
}
}
当连接到需要授权的公共网络(咖啡馆、机场)时,系统首先报告onAvailable,但onCapabilitiesChanged可能不显示INTERNET。在这种情况下,需要通过对稳定端点(例如https://www.google.com/generate_204)进行HTTP请求来额外检查。
如果请求返回204代码 — 有互联网。如果重定向(301、302、307) — 需要通过浏览器授权。在这种情况下,可以打开WebView或Intent到重定向URL,以在门户上进行身份验证。
fun Context.validateInternet(network: Network) {
CoroutineScope(Dispatchers.IO).launch {
try {
val url = URL("https://www.google.com/generate_204")
val connection =
network.openConnection(url) as HttpURLConnection
connection.instanceFollowRedirects = false
connection.connect()
when (connection.responseCode) {
HttpURLConnection.HTTP_NO_CONTENT ->
Log.d("Network", "互联网可用")
in HttpURLConnection.HTTP_MOVED_PERM
..HttpURLConnection.HTTP_TEMP_REDIRECT ->
Log.d("Network", "检测到强制门户")
}
connection.disconnect()
} catch (e: Exception) {
Log.e("Network", "验证失败: ${e.message}")
}
}
}
在NetworkCallback之前,主要的网络监控方式是带有android.net.conn.CONNECTIVITY_CHANGE过滤器的BroadcastReceiver。这种方法有明显的缺点:延迟几秒钟、缺少接口类型信息、由于设备不断唤醒而导致的能耗增加。
现代替代方案 — 与NetworkCallback配合使用的LiveData或StateFlow。该模式将回调包装成响应式流,自动通知UI状态变化。例如,NetworkStatus类型的MutableStateFlow在回调方法内部更新,ViewCollector订阅更改。
| 方式 | API Level | 延迟 | 详细程度 | 能耗 |
|---|---|---|---|---|
| BroadcastReceiver | 1+ | 高 | 低 | 高 |
| NetworkCallback | 21+ | 低 | 高 | 低 |
| ConnectivityManager.getActiveNetwork | 23+ | 即时 | 中 | 零 |
| NWPathMonitor (iOS) | iOS 12+ | 低 | 高 | 低 |
从Android 10开始,后台限制级别更加严格,当应用程序在后台时,NetworkCallback可能不会被调用。对于关键重要的任务 — 例如网络出现时加载数据 — 使用带有NetworkType.CONNECTED限制的WorkManager。WorkManager保证在网络条件满足时执行任务。
在Android 12+中,对BroadcastReceiver的清单注册有了限制。开发人员必须迁移到NetworkCallback或使用WorkManager。Google Play政策自2022年8月起要求为此操作删除清单注册。
常见问题
带有CONNECTIVITY_CHANGE的BroadcastReceiver只提供网络变化的事实,没有详细信息,延迟可达几秒。NetworkCallback异步工作,提供Network对象、接口类型、连接能力,并且不需要在Android 12+中被禁止的清单注册。
在Android 10+中,后台限制可能会延迟或不调用NetworkCallback。对于后台任务,使用带有NetworkType限制的WorkManager — 它保证在条件满足时执行工作,无论省电模式如何。
在ConnectivityManager上调用unregisterNetworkCallback方法,传递注册时使用的同一个回调实例。未取消的回调可能导致内存泄漏,因为系统保留对它的引用。始终在onStop或onDestroy中取消。
NetworkCallback从API Level 21 (Android 5.0 Lollipop)开始可用。对于版本较旧的设备,使用BroadcastReceiver或兼容性库,如AndroidX Activity NetworkCallback,它们包装API以获得更广泛的支持。
使用ConnectivityManager.getActiveNetwork(API 23+)配合getNetworkCapabilities。该方法同步返回当前活动网络,无需订阅更改。对于API 21-22,使用getActiveNetworkInfo,它在较新版本中被标记为deprecated。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。