前言
Android 应用开发中,经常有需要确保在网络切换或连接丢失时能正确运行。而 ConnectivityManager
这个系统服务,是我们管理网络连接的得力助手,配合 Flow 使用实时监听网络状态,保证用户体验的流畅性
认识 ConnectivityManager
ConnectivityManager 是 Android 的系统服务,通过它我们能获取设备网络连接的状态信息。简单来说,它就像一个 “网络小管家”,可以帮我们实现这些功能:
- 检查网络连接状态:快速判断设备当前有没有联网。
- 监测网络类型:区分是 Wi - Fi、蜂窝网络还是以太网等。
- 注册监听器当网络状态发生变化时,我们能及时收到通知并做出反应。
- 评估网络适用性:判断当前网络是否满足应用的特定操作需求,比如有没有互联网访问权限。
下面,我就来一步步教大家怎么利用它创建一个网络检测器。
打造一个网络监听器
1. 初始化 ConnectityManager
通过 getSystemService
方法来获取 ConnectivityManager
的实例,代码如下:
private var connectivityManager: ConnectivityManager? =
context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
这一步就像是给我们的 “网络小管家” 发了个 “入职通知”,让它开始为我们服务。
2. 创建网络回调
这里要用到 NetworkCallback
,它是 ConnectivityManager
API 里的一个类,能帮我们方便地监听网络连接的变化。比如说,网络什么时候能用了,什么时候突然没了,或者网络的一些功能(像能不能上网)发生变化了,它都能及时告诉我们。
在应用里使用 NetworkCallback
,就能根据网络状态的改变灵活调整,给用户提供无缝的网络体验,就算他们频繁切换网络或者遇到连接不稳定的情况,也不用担心。
几个关键的回调方法:
- onAvailable(Network network) :当网络可用时,这个方法就会被调用,相当于跟我们喊 “网络通啦”!
- onLost(Network network) :一旦网络丢失,比如用户切换到其他网络了,它就会出声提醒我们。
- onUnavailable() :要是没有可用网络了,它就会来报信。
- onCapabilitiesChanged(Network network, NetworkCapabilities capabilities) :当网络的功能有变化,像是网络能不能上网、是不是有效这类情况改变时,它就会通知我们。
看看具体代码实现:
val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
connectivityManager?.getNetworkCapabilities(network)?.let {
if (it.hasCapability(NET_CAPABILITY_INTERNET)) {
// trySend(true)
}
}
}
override fun onLost(network: Network) {
// trySend(false)
}
override fun onUnavailable() {
// trySend(false)
}
override fun onCapabilitiesChanged(
network: Network,
capabilities: NetworkCapabilities
) {
super.onCapabilitiesChanged(network, capabilities)
if (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
// trySend(true)
} else {
// trySend(false)
}
}
}
3. 创建网络请求
我们得用 NetworkRequest.Builder
来创建一个网络请求。这个请求的目的是找到符合特定要求的网络,像能提供互联网访问,还支持 Wi - Fi、以太网、蜂窝网络这些传输类型的网络。
代码如下:
val networkRequest = NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.build()
这里面几个关键操作解释一下:
- NetworkRequest.Builder() :这是创建一个请求构建器,就像是搭个框架,用来设置我们想要的网络标准。
- addCapability(NET_CAPABILITY_INTERNET) :给网络加上一个必须能上网的要求,这样找出来的网络肯定是能让应用联网的。
- addTransportType :给网络请求指定传输类型,像 Wi - Fi、以太网或者蜂窝网络,这样就能找到符合这些传输类型要求的网络。
4. 注册网络回调
把前面创建好的网络请求和网络回调关联起来,注册一下,代码很简单:
connectivityManager?.registerNetworkCallback(networkRequest, networkCallback)
这样,我们的网络监测器基本就搭建好了。不过,为了能实时发送网络状态变化的信息,我们还得用上 Flow
。
用 Flow 实现实时网络事件发送
我们通过 Flow API 的 trySend
方法来发送网络状态的实时变化。trySend
在 Kotlin 的协程里经常用,它的特点就是不阻塞调用线程,能直接给通道或者共享流发送值。如果流能接收值,它就返回 true
,发不出去就返回 false
。
具体代码如下:
val isConnectedFlow: Flow<Boolean> = callbackFlow {
val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
connectivityManager?.getNetworkCapabilities(network)?.let {
if (it.hasCapability(NET_CAPABILITY_INTERNET)) {
trySend(true)
}
}
}
override fun onLost(network: Network) {
trySend(false)
}
override fun onUnavailable() {
trySend(false)
}
override fun onCapabilitiesChanged(
network: Network,
capabilities: NetworkCapabilities
) {
super.onCapabilitiesChanged(network, capabilities)
if (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
trySend(true)
} else {
trySend(false)
}
}
}
val networkRequest = NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.build()
connectivityManager?.registerNetworkCallback(networkRequest, networkCallback)
awaitClose {
connectivityManager?.unregisterNetworkCallback(networkCallback)
}
}
实际使用场景
1. 创建 ViewModel
class MainViewModel(networkObserver: NetworkObserverFlow) : ViewModel() {
val isConnected = networkObserver.isConnectedFlow.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000L),
initialValue = false
)
}
2. 在 View 或 Compose 中监听网络状态
Compose 中使用
val viewModel = viewModel<MainViewModel>(viewModelStoreOwner = this@MainActivity)
val isConnected by viewModel.isConnected.collectAsState()
println("Network status: $isConnected") // isConnected为true表示已连接,false表示未连接
View 中使用
val networkObserver = NetworkObserverFlow(context)
// 在活动的onCreate方法或片段的onViewCreated方法中添加以下代码
viewLifecycleOwner.lifecycleScope.launch {
networkObserver.isConnected.collect { isConnected ->
if (isConnected == ConnectivityStatus.STATE_CONNECTED) {
// 网络已连接
}
}
}
以上,我们就完成了基于 ConnectivityManager + Flow
的 Android 网络连接监测功能。