首页 Android 正文
  • 本文约4713字,阅读需24分钟
  • 99
  • 0

ConnectivityManager + Flow 打造 Android 网络状态监听器

摘要

前言 Android 应用开发中,经常有需要确保在网络切换或连接丢失时能正确运行。而 ConnectivityManager 这个系统服务,是我们管理网络连接的得力助手,配合 Flow 使用实时监听网络状态,保证用户体验的流畅性 认识 ConnectivityManager ConnectivityManager 是 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() {
    overridefun onAvailable(network: Network) {
        connectivityManager?.getNetworkCapabilities(network)?.let {
            if (it.hasCapability(NET_CAPABILITY_INTERNET)) {
                // trySend(true)
            }
        }
    }
    overridefun onLost(network: Network) {
        // trySend(false)
    }
    overridefun onUnavailable() {
        // trySend(false)
    }
    overridefun 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() {
        overridefun onAvailable(network: Network) {
            connectivityManager?.getNetworkCapabilities(network)?.let {
                if (it.hasCapability(NET_CAPABILITY_INTERNET)) {
                    trySend(true)
                }
            }
        }
        overridefun onLost(network: Network) {
            trySend(false)
        }
        overridefun onUnavailable() {
            trySend(false)
        }
        overridefun 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 网络连接监测功能。


扫描二维码,在手机上阅读
文章目录


    扫描二维码,在手机上阅读
      评论
      友情链接