ConnectivityManager + Flow 打造 Android 网络状态检测器

前言

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 网络连接监测功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fundroid

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值