要判断和监听网络连接状态,要使用的系统服务是 ConnectivityManager
对象,可以通过 context.getSystemService(Context.CONNECTIVITY_SERVICE)
来获得。所以首先可以定义一个Context的扩展属性来方便的获取该对象:
private val Context.connectivityManager: ConnectivityManager
get() = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
判断网络瞬时连接状态
也就是判断当前那一刻的连接状态,一般用于请求后台接口前的检查准备工作。
- 如果是在
Android 6.0
以下(API < 23
)系统版本,可以使用ConnectivityManager
的getActiveNetworkInfo()
方法先拿到返回的NetworkInfo
对象,然后调用NetworkInfo
的isConnected()
方法来判断。 - 如果是在
Android 6.0 +
(API >= 23
)系统版本,可以先调用ConnectivityManager
的getActiveNetwork()
方法返回一个Network
对象,然后调用ConnectivityManager
的getNetworkCapabilities(Network)
,会返回一个NetworkCapabilities
对象,再调用NetworkCapabilities
的hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
判断即可。
我们可以为 ConnectivityManager
定义一个扩展属性来实现上面的判断逻辑:
private val ConnectivityManager.isNetWorkConnected
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val networkCapabilities = getNetworkCapabilities(activeNetwork)
networkCapabilities?.hasCapability(NET_CAPABILITY_INTERNET) ?: false
} else {
activeNetworkInfo?.isConnected ?: false
}
监听网络连接状态的变化
一种古老的办法是注册一个action为"android.net.conn.CONNECTIVITY_CHANGE"
的动态广播来监听(Android7.0以上已经不允许在静态广播中监听该action了),在接受到该广播的时候去判断。但是这种办法已经不是一个较好的解决方案了,尤其在较高的版本中,Android官方已经不推荐这种做法了,甚至会屏蔽应用接受该类型的广播。目前官方推荐的方案是使用ConnectivityManager
对象进行注册一个Callback回调来监听,你可以使用ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback)
及 ConnectivityManager.registerNetworkCallback(NetworkCallback)
来实现。这两个注册方法可以结合使用。
但它们的用途各有不同。
所有 Android 应用都有一个默认网络。系统决定了哪个网络应是默认网络。系统通常首选不按流量计费的网络而非按流量计费的网络,首选网速较快的网络而非网速较慢的网络。当应用发出网络请求时,系统会使用默认网络满足该请求。应用也可以通过其他网络发送流量。
在应用的整个生命周期内,设置为默认网络的网络可能随时发生变化。典型的例子是设备处于一个已知活跃、不按流量计费、速度快于移动网络的 Wi-Fi 接入点的覆盖范围内。设备将连接到此接入点,并将所有应用的默认网络切换至新的 Wi-Fi 网络。
当新网络成为默认网络时,应用打开的任何新连接都会使用此网络。一段时间后,上一个默认网络上的所有剩余连接都将被强制终止。如果知道默认网络发生变化的时间对应用很重要,它应按如下方式注册默认网络回调:
connectivityManager.registerDefaultNetworkCallback(object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network : Network) {
Log.e(TAG, "The default network is now: " + network)
}
override fun onLost(network : Network) {
Log.e(TAG, "The application no longer has a default network. The last default network was " + network)
}
override fun onCapabilitiesChanged(network : Network, networkCapabilities : NetworkCapabilities) {
Log.e(TAG, "The default network changed capabilities: " + networkCapabilities)
}
override fun onLinkPropertiesChanged(network : Network, linkProperties : LinkProperties) {
Log.e(TAG, "The default network changed link properties: " + linkProperties)
}
})
注意:请勿在回调中调用同步方法来查找新可用网络的属性,因为这会受到竞态条件的影响。相反,应该等待对该网络的 onCapabilitiesChanged() 和 onLinkPropertiesChanged() 的调用,在搭载 Android 8.0(API 级别 26)及更高版本的设备上,在调用 onAvailable() 后会立即调用它们。
对于通过 registerDefaultNetworkCa