-
关于判断是否有网络的方法
老版本判断是否有网络的方法如下:
/**
* 判断网络是否已连接
*/
fun isNetworkConnect(): Boolean {
val manager = application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
return manager.activeNetworkInfo.isConnectedOrConnecting
}
这个在Android源码中已标注为已废弃,NetworkInfo整一个类在API 29被废弃了,取而代之的是下面的新的方式:
/**
* 判断网络是否已连接
*/
fun isNetworkConnect(): Boolean {
val manager = application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val activeNetwork = manager.activeNetwork
val networkCapabilities = manager.getNetworkCapabilities(activeNetwork) ?: return false
return networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
}
新的方法需要关注两个Flag,即NetworkCapabilities.NET_CAPABILITY_INTERNET和NetworkCapabilities.NET_CAPABILITY_VALIDATED:
-
NetworkCapabilities.NET_CAPABILITY_INTERNET : NetworkCapabilities包含该Flag时代表网络已经被正确配置了,比如WIFI已经连接上,但是不代表该网络一定可以上网。
-
NetworkCapabilities.NET_CAPABILITY_VALIDATED:NetworkCapabilities包含该Flag时代表网络可以正常上网。
在官方文档 developer.android.com/reference/a… 中的描述如下:
另外,在Android最新的Compose示例代码 github.com/android/com… 当中也给出了Demo示例:
Demo示例贴心地做了API级别的兼容,即Android6.0以及以上的系统就可以采用新的网络判断方式了。
另外,关于网络监听相关的广播也被放弃了,取而代之的是使用ConnectivityManager.NetworkCallback API,大家也可以关注一下。唯一需要注意的是收到onAvailable()回调时网络不一定可上网,最好在onCapabilitiesChanged()回调中进行处理。
详情可以参考这篇播放的介绍:blog.csdn.net/u012514113/…
-
Captive Portal机制
-
基本概念
上文提到NetworkCapabilities包含NetworkCapabilities.NET_CAPABILITY_VALIDATED Flag时代表网络可以正常上网 , 那么Android如何判断网络是否能够上网的呢?那么就需要引入Captive Portal机制。
Captive Portal机制中文通常译作“强制主页”或“强制登录门户”。是一个登录Web页面,通常由网络运营商或网关在用户能够正常访问互联网之前拦截用户的请求并将一个强制登录或认证主页呈现(通常是通过浏览器)给用户。该页面可能要求用户输入认证信息、支付、接受某些条款或者其他用户授权等,随后用户才能被授权访问互联网。该技术广泛用于移动和个人宽带服务,包括有线电视、商业WiFi、家庭热点等,也可用于访问企业和住宅区有线网络。其中Android是在5.0正式引入Captive Portal机制,上面的Demo示例也是根据这个做API级别的兼容。
Captive Portal机制核心源码相关逻辑位于:aospxref.com/android-14.… ,有兴趣深入研究源码的可以关注一下:
当Android系统连接到网络时,比如WIFI已连接时,Captive Portal机制就会开始工作。大致流程是系统会请求一个204服务器的地址,就是当你连上网络后,系统会给目标产生204响应的服务器发送给一个请求,如果服务器返回的是状态码为204的响应,那么就被认为网络可以访问;否则,如返回的是其他状态码,那么将被视为网络访问需要登录操作等;没有响应的话,就被认为是网络不可访问。并且,当校验成功时NetworkCapabilities会包含NetworkCapabilities.NET_CAPABILITY_VALIDATED Flag,告知应用层当前网络可以正常上网;当校验失败时,网络符号会多出一个感叹号:
在设置APP里面网络相关页面也会提示我们当前网络无法上网,如下图所示:
另外,当网络需要认证或者同意某些协议时,系统会自动给我们打开一个认证页面,如下面的示例:
通常我们在公共场所比如医院、学校、公司等连接这种需要认证的WIFI就会自动弹出这种认证页面。当我们进行登录或者同意相关隐私协议之后设备即可正常访问网络。
-
相关配置
Android系统的Captive Portal机制可以通过命令的形式配置,另外,也可以在Framework源码中直接修改默认配置。
-
配置Captive Portal机制的模式
可以通过get的方式进行配置:
adb shell settings put global captive_portal_mode 0
Captive Portal机制的模式包括:
0:彻底禁用检测
1:检测到需要登录则弹窗提醒(默认值)
2:检测到需要登录则自动断开此热点并不再自动连接
其中即使不配置或已删除了配置,Framework也会提供一个默认值1,其定义在:aospxref.com/android-14.…
-
配置Captive Portal机制的204服务器地址及协议切换
Android原生系统默认配置的204服务器地址是谷歌提供的,可能会被墙,导致Captive Portal机制校验失败,可以通过下面的命令进行204服务器地址的更改,比如换成高通或小米的地址:
adb shell settings put global captive_portal_http_url http://www.qualcomm.cn/generate_204
adb shell settings put global captive_portal_https_url https://connect.rom.miui.com/generate_204
其中地址分为http和https两种,可以通过下面这个命令进行切换:
adb shell settings put global captive_portal_use_https 0
其中即使不配置或已删除了配置,Framework也会提供204服务器地址的默认值,源码位于:aospxref.com/android-14.…
-
查看、删除Captive Portal机制的配置
可以通过下面的命令一次性查看所有配置:
adb shell settings list global
也可以使用get的方式单独查看某个配置:
adb shell settings get global captive_portal_mode
adb shell settings get global captive_portal_use_https
adb shell settings get global captive_portal_http_url
adb shell settings get global captive_portal_https_url
另外,可以通过delete的方式进行删除某个配置:
adb shell settings delete global captive_portal_mode
adb shell settings delete global captive_portal_use_https
adb shell settings delete global captive_portal_http_url
adb shell settings delete global captive_portal_https_url
-
总结
- 当我们遇到其他应用可以请求网络,而自己应用由于判断为无网络导致无法请求网络时,需要关注是否采用了最新的方法进行网络判断,需要关注网络信息里面是否包含NetworkCapabilities.NET_CAPABILITY_VALIDATED 。 如果业务无需准确判断网络能否上网,建议把NetworkCapabilities.NET_CAPABILITY_VALIDATED这个判断条件去掉,即网络已连接好就可以尝试去进行网络请求。
- 当我们遇到Captive Portal机制相关问题导致WIFI提示不可上网时,可以通过adb shell settings put global captive_portal_mode 0命令临时关闭Captive Portal机制解决,注意关闭后需要重新连接WIFI后生效。
- 除了临时解决之外,还需要找Framework相关开发同事配置好默认的204服务器地址及其他相关的源码配置。