Android 获取网络连接状态新方法

一. 问题背景

        Android12上,有的app模块判断当前网络的类型和连接状态时,还是使用的旧的API,导致返回的结果不准确,影响代码逻辑判断,本篇文章就这一问题,整理一下判断网络类型和连接状态的新方法。

二. 原因分析

        在Android 10以前的版本,大家都是通过NetworkInfo.java 的getType()方法获取网络类型,通过isConnected()方法来判断是否连接上, 判断网络连接的旧方法如下:

1.是否连接:

 2. 网络类型

 但是在Android10之后,这些方法已过时,官方不推荐使用,我们先来看下官方的源码说明

 

 左边是Android10,右边是Android9的源码 ,   在10上已经标记Deprecated,新加的注释也推荐了使用的API

还有一个旧广播String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"  Android 9之后也废弃,不推荐使用,之前的使用方法:

看下官方说明:

 官方标记Deprecated,是避免在高版本的设备上获取返回的网络状态不对,并且给了推荐的API,以Android10为一个分界点, 之后的版本都推荐使用新的API方法。

三. 官方推荐API

官方推荐:监控 Android 中的互联网连接,可以使用ConnectivityManager类,这是一个允许您查询网络状态的系统服务类,   还有一个NetworkCapabilities类,代表活动网络的功能。

体使用方法如下:

registerNetworkCallback():此函数注册一个NetworkCallback对象来监听网络状态变化。它以一个NetworkCallback对象作为参数。

unregisterNetworkCallback():此函数取消注册以前注册的NetworkCallback对象。

接下来重点关注NetworkCallback中的回调方法描述

回调方法

描述

onCapabilitiesChanged

当网络状态改变 但仍旧是可用状态时调用

onAvailable

网络连接成功,通知可以使用的时候调用

onUnavailable

当网络连接超时或网络请求达不到可用要求时调用

onBlockedStatusChanged

当访问指定的网络被阻止或解除阻塞时调用

onLosing

当网络正在断开连接时调用

onLost

当网络已断开连接时调用

onLinkPropertiesChanged

当网络连接的属性被修改时调用

接下来再说一下

NetworkCapabilities.java类中的NET_CAPABILITY_VALIDATED字段,描述为:

表示此网络上的连接已成功验证。例如,对于具有NET_CAPABILITY_INTERNET的网络,这意味着已成功检测到INTERNET连接。

通过实际log来描述说明一下:

1. 连接上可上网的wifi,可看到VALIDATED的标记:

2. 连接上需要认证和不能上网的wifi,找不到VALIDATED标记:

 3. 用数据流量上网,可以看到VALIDATED的标记:

我们可以通过networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)这个方法作为(连接可以正常上网的网络)判断条件。进一步通过networkCapabilities.hasTransport方法来判断当前的网络类型。

四. 使用方法

看代码更直接一点:

MainActivity.java

@SuppressLint("NewApi")
public class MainActivity extends AppCompatActivity {private static final String TAG = "ConnectManager";private ConnectivityManager networkService;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);networkService = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);if (networkService != null) {//注册 NetworkCallBacknetworkService.registerDefaultNetworkCallback(networkCallBack);}}/** 测试网络工具类方法* */@Overrideprotected void onResume() {super.onResume();//Log.e(TAG,  "=====在onResume方法中判断 : isMobileNetwork :" + NetworkUtils.isMobileNetwork(this));//Log.e(TAG,  "=====在onResume方法中判断 : isWifiNetwork :" + NetworkUtils.isWifiNetwork(this));//Log.e(TAG,  "=====在onResume方法中判断 : getConnectedNetworkType :" + NetworkUtils.getConnectedNetworkType(this));}@Overrideprotected void onDestroy() {super.onDestroy();if (networkService != null && networkCallBack != null) {networkService.unregisterNetworkCallback(networkCallBack);}}private final ConnectivityManager.NetworkCallback networkCallBack = new ConnectivityManager.NetworkCallback(){//当网络状态修改但仍旧是可用状态时调用@Overridepublic void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {super.onCapabilitiesChanged(network, networkCapabilities);if (NetworkUtils.isConnectedAvailableNetwork(getBaseContext())) {Log.d(TAG, "onCapabilitiesChanged ---> ====网络可正常上网===网络类型为: "+ NetworkUtils.getConnectedNetworkType(MainActivity.this));}//表明此网络连接验证成功if(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {Log.d(TAG, "===当前在使用Mobile流量上网===");} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {Log.d(TAG, "====当前在使用WiFi上网===");} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH)) {Log.d(TAG, "=====当前使用蓝牙上网=====");} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {Log.d(TAG, "=====当前使用以太网上网=====");} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {Log.d(TAG, "===当前使用VPN上网====");} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE)) {Log.d(TAG, "===表示此网络使用Wi-Fi感知传输====");} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_LOWPAN)) {Log.d(TAG, "=====表示此网络使用LoWPAN传输=====");} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_USB)) {Log.d(TAG, "=====表示此网络使用USB传输=====");}}}@Overridepublic void onAvailable(@NonNull Network network) {super.onAvailable(network);Log.e(TAG, "==网络连接成功,通知可以使用的时候调用====onAvailable===");}@Overridepublic void onUnavailable() {Log.e(TAG, "==当网络连接超时或网络请求达不到可用要求时调用====onUnavailable===");super.onUnavailable();}@Overridepublic void onBlockedStatusChanged(@NonNull Network network, boolean blocked) {Log.e(TAG, "==当访问指定的网络被阻止或解除阻塞时调用===onBlockedStatusChanged==");super.onBlockedStatusChanged(network, blocked);}@Overridepublic void onLosing(@NonNull Network network, int maxMsToLive) {Log.e(TAG, "==当网络正在断开连接时调用===onLosing===");super.onLosing(network, maxMsToLive);}@Overridepublic void onLost(@NonNull Network network) {Log.e(TAG, "==当网络已断开连接时调用===onLost===");super.onLost(network);}@Overridepublic void onLinkPropertiesChanged(@NonNull Network network, @NonNull LinkProperties linkProperties) {Log.e(TAG, "==当网络连接的属性被修改时调用===onLinkPropertiesChanged===");super.onLinkPropertiesChanged(network, linkProperties);}};}

网络工具类NetworkUtils.java

@SuppressLint("NewApi")
public class NetworkUtils {private static final String TAG = "ConnectManager";/*** Indicates this network uses a Cellular transport.*/public static final int TRANSPORT_CELLULAR = 0;/*** Indicates this network uses a Wi-Fi transport.*/public static final int TRANSPORT_WIFI = 1;/*** Indicates this network uses a Bluetooth transport.*/public static final int TRANSPORT_BLUETOOTH = 2;/*** Indicates this network uses an Ethernet transport.*/public static final int TRANSPORT_ETHERNET = 3;/*** Indicates this network uses a VPN transport.*/public static final int TRANSPORT_VPN = 4;/*** Indicates this network uses a Wi-Fi Aware transport.*/public static final int TRANSPORT_WIFI_AWARE = 5;/*** Indicates this network uses a LoWPAN transport.*/public static final int TRANSPORT_LOWPAN = 6;/*** Indicates this network uses a Test-only virtual interface as a transport.* @hide*/public static final int TRANSPORT_TEST = 7;/*** Indicates this network uses a USB transport.*/public static final int TRANSPORT_USB = 8;/*** >= Android 10(Q版本)推荐** 当前使用MOBILE流量上网*/public static boolean isMobileNetwork(Context context) {ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);Network network = cm.getActiveNetwork();if (null == network) {return false;}NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);if (null == capabilities) {return false;}return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)&& capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);}/*** >= Android 10(Q版本)推荐** 当前使用WIFI上网*/public static boolean isWifiNetwork(Context context) {ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);Network network = cm.getActiveNetwork();if (null == network) {return false;}NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);if (null == capabilities) {return false;}return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)&& capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);}/***  >= Android 10(Q版本)推荐** 当前使用以太网上网*/public static boolean isEthernetNetwork(Context context) {ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);Network network = cm.getActiveNetwork();if (null == network) {return false;}NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);if (null == capabilities) {return false;}return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)&& capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);}/*** >= Android 10(Q版本)推荐** NetworkCapabilities.NET_CAPABILITY_INTERNET,表示此网络应该(maybe)能够访问internet**  判断当前网络可以正常上网*  表示此连接此网络并且能成功上网。  例如,对于具有NET_CAPABILITY_INTERNET的网络,这意味着已成功检测到INTERNET连接。*/public static boolean isConnectedAvailableNetwork(Context context) {ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);Network network = cm.getActiveNetwork();if (null == network) {return false;}NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);if (null == capabilities) {return false;}return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)&& capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);}/*** >= Android 10(Q版本)推荐** 获取成功上网的网络类型* value = {*    TRANSPORT_CELLULAR,   0 表示此网络使用蜂窝传输。*    TRANSPORT_WIFI,       1 表示此网络使用Wi-Fi传输。*    TRANSPORT_BLUETOOTH,  2 表示此网络使用蓝牙传输。*    TRANSPORT_ETHERNET,   3 表示此网络使用以太网传输。*    TRANSPORT_VPN,        4 表示此网络使用VPN传输。*    TRANSPORT_WIFI_AWARE, 5 表示此网络使用Wi-Fi感知传输。*    TRANSPORT_LOWPAN,     6 表示此网络使用LoWPAN传输。*    TRANSPORT_TEST,       7 指示此网络使用仅限测试的虚拟接口作为传输。*    TRANSPORT_USB,        8 表示此网络使用USB传输* }*/public static int getConnectedNetworkType(Context context) {ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);Network network = cm.getActiveNetwork();if (null == network) {return -1;}NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);if (null == capabilities) {return -1;}if (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {return NetworkCapabilities.TRANSPORT_CELLULAR;} else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {return NetworkCapabilities.TRANSPORT_WIFI;} else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH)) {return NetworkCapabilities.TRANSPORT_BLUETOOTH;} else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {return NetworkCapabilities.TRANSPORT_ETHERNET;} else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {return NetworkCapabilities.TRANSPORT_VPN;} else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE)) {return NetworkCapabilities.TRANSPORT_WIFI_AWARE;} else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_LOWPAN)) {return NetworkCapabilities.TRANSPORT_LOWPAN;} else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_USB)) {return NetworkCapabilities.TRANSPORT_USB;}}return -1;}
}

Android10之后,请使用新的API方法, 工具类可以根据业务需求去扩展, 供参考。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/58469.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CC++内存管理与模版初阶

目录 四、C&C内存管理 (一)C/C内存分布 (二)C内存管理方式 1、new/delete操作内置类型 2、new和delete操作自定义类型 (三)operator new与operator delete函数 (四)new和delete的实现原理 1、内置类型 2、自定义类型 (五)定位new表达式(placement-new) (六)八股文 1、n…

华为发布数字资产继承功能

在华为开发者大会2023(HDC.Together)上,华为常务董事、终端BG CEO、智能汽车解决方案BU CEO余承东正式发布了数字资产继承功能,HarmonyOS提供了安全便捷的数字资产继承路径。 在鸿蒙世界中,我们每个人在每台设备、应用…

Git从远程仓库中删除文件,并上传新文件

目录 删除: 拉取远程分支的更新: ​编辑 首先查看git状态: ​编辑 删除文件并提交版本库: 提交: 上传新文件: 首先查看git状态: 提交到暂存区: 提交到版本库: 上…

windows环境下如何更改pip安装的默认位置

1.查看配置信息 python -m site2.查看配置文件位置 python -m site -help3.修改配置文件 USER_SITE "D:\\soft\\Anaconda\\Lib\\site-packages" USER_BASE "D:\\soft\\Anaconda\\Scripts"如果遇到文件无法保存情况,请给用户增加权限。 4.…

Netty框架自带类DefaultEventExecutorGroup的作用,用来做业务的并发

一、DefaultEventExecutorGroup的用途 DefaultEventExecutorGroup 是 Netty 框架中的一个类,用于管理和调度事件处理器(EventExecutor)的组。在 Netty 中,事件处理是通过多线程来完成的,EventExecutor 是处理事件的基…

uniapp scroll-view 隐藏滚动条

/*清除滚动条 - 适配安卓*/::-webkit-scrollbar {width: 0;height: 0;color: transparent;}/*清除滚动条 - 适配IOS*/::-webkit-scrollbar {display: none;}

ffmpeg下载安装教程

ffmpeg官网下载地址https://ffmpeg.org/download.html 这里以windows为例,鼠标悬浮到windows图标上,再点击 Windows builds from gyan.dev 或者直接打开 https://www.gyan.dev/ffmpeg/builds/ 下载根据个人需要下载对应版本 解压下载的文件,并复制bin所在目录 新打开一个命令…

clickhouse调研报告2

由Distributed表发送分片数据 clickhouse分区目录合并 clickhouse副本协同流程 clickhouse索引查询逻辑 clickhouse一级索引生成逻辑(两主键) clickhouse的data目录下包含如下目录: [root@brfs-stress-01 201403_10_10_0]# ll /data01/clickhouse/data total 4 drwxr-x---…

stable-diffusion-webui 界面汉化

本教程通过安装 sd-webui-bilingual-localization 插件来达到汉化目的, 项目地址为:https://github.com/journey-ad/sd-webui-bilingual-localization 一、安装插件 先进入插件安装界面 在搜索栏搜索 zh_CN Localization 中文语言包, 项目地址: https://github.com/dtlnor/st…

数据结构--最小生成树

数据结构–最小生成树 连通图 \color{red}连通图 连通图的生成树是 包含图中全部顶点的一个极小连通子图 \color{red}包含图中全部顶点的一个极小连通子图 包含图中全部顶点的一个极小连通子图。 若图中顶点数为n,则它的生成树含有 n-1 条边。对生成树而言&#xff…

Elasticsearch:如何创建 Elasticsearch PEM 和/或 P12 证书?

你是否希望使用 SSL/TLS 证书来保护你的 Elasticsearch 部署? 在本文中,我们将指导你完成为 Elasticsearch 创建 PEM 和 P12 证书的过程。 这些证书在建立安全连接和确保 Elasticsearch 集群的完整性方面发挥着至关重要的作用。 友情提示:你可…

【2.3】Java微服务:sentinel服务哨兵

✅作者简介:大家好,我是 Meteors., 向往着更加简洁高效的代码写法与编程方式,持续分享Java技术内容。 🍎个人主页:Meteors.的博客 💞当前专栏:Java微服务 ✨特色专栏: 知识分享 &…