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.mzph.cn/news/21436.shtml

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

相关文章

JVM基础篇-本地方法栈与堆

JVM基础篇-本地方法栈与堆 本地方法栈 什么是本地方法? 本地方法即那些不是由java层面实现的方法,而是由c/c实现交给java层面进行调用,这些方法在java中使用native关键字标识 public native int hashCode()本地方法栈的作用? 为本地方法提供内存空…

新手入门吉他买什么好?千元内VEAZEN费森VZ200和恩雅X1pro综合评测,你会选新型材质HPL还是传统木吉他?

千元内入门吉他少不了VEAZEN费森VZ200单板系列和恩雅X1 PRO系列这两款热门系列,最近很多初学者朋友来私信,咨询这两款琴有什么优缺点,哪一款更值得初学者选购,那么今天,就以它们为本期的评测主角,全方位评测…

基于ARM+FPGA的驱控一体机器人控制器设计

目前市场上工业机器人,数控机床等多轴运动控制系统普遍采用运动控制器加 伺服驱动器的分布式控制方式。在这种控制方式中,控制器一方面完成人机交互,另 一方面进行 NC 代码的解释执行,插补运算,继而将计算出来的位…

vue v-slot指令

目录 定义语法使用场景场景一场景二场景三tips只有一个默认插槽时 定义 在Vue中, v-slot 指令用于定义插槽的模板内容。它用于在父组件中传递内容到子组件中的插槽。 v-slot 指令可以用于 标签或组件标签上,以便在子组件中使用插槽。 语法 使用 v-slo…

一位年薪50W的测试被开除,回怼的一番话,令人沉思

一位年薪35W测试工程师被开除回怼道:“反正我有技术,在哪不一样” 一技傍身,万事不愁,当我们掌握了一技之长后,在职场上说话就硬气了许多,不用担心被炒,反过来还可以炒了老板,这一点…

MVC配置原理

如果你想保存springboot的mvc配置并且还想自己添加自己的配置就用这个。 视图解析器原理,它会从IOC容器里获取配置好视图解析器的配置类里的视图解析器集合, 然后遍历集合,生成一个一个的视图对象,放入候选 视图里,…

MQTT协议详解「概念、特性、版本及作用」

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是ISO标准下基于发布/订阅方式的轻量级消息协议。MQTT通常使用TCP / IP(传输控制协议/Internet协议)作为其传输,但也可以使用其他双向传输。MQ…

海外版金融理财系统源码 国际投资理财系统源码 项目投资理财源码

海外版金融理财系统源码 国际投资理财系统源码 项目投资理财源码

8.3一日总结

1.远程仓库的使用 a.克隆远程仓库 1>.在桌面克隆远程仓库 git clone 仓库名 2>.修改仓库内容 3>添加目录 git add. 4>提交: git commit -m 完成登录功能 5>推送提交远程仓库 : git push origin master -u 6>更改推送:git push(简写形式) 需要先添加,再提交,最…

一文学透设计模式——工厂模式

工厂模式 概念 牛马人生公司最近开启了线上直播,直播中牛马人生公司宣称他们建造了一家世界上最为先进的工厂,任何人只要去到工厂面前,告诉工厂你要什么牌子的汽车,工厂就会给你一辆什么牌子的汽车。 这引起了粉丝朋友的注意&a…

stm32与上位机电脑间最快的通信方式是什么?

对于小型多关节机械臂的控制电路设计,选择合适的通信方式可以提高MCU与上位机之间的实时性。以下是一些在STM32上常用的通信方式,你可以根据你的具体需求选择适合的: 串口通信(UART):串口通信是一种常见的…

opencv-34 图像平滑处理-2D 卷积 cv2.filter2D()

2D卷积是一种图像处理和计算机视觉中常用的操作,用于在图像上应用滤波器或卷积核,从而对图像进行特征提取、平滑处理或边缘检测等操作。 在2D卷积中,图像和卷积核都是二维的矩阵或数组。卷积操作将卷积核在图像上滑动,对每个局部区…

Netty学习(四)

文章目录 四. 优化与源码1. 优化1.1 扩展序列化算法jdk序列化与反序列化Serializer & AlgorithmConfigapplication.properties MessageCodecSharableMessage(抽象类) 测试序列化测试反序列化测试 1.2 参数调优1)CONNECT_TIMEOUT_MILLIS2&…

ansible配置文件案例

案例一 控制主机上的普通用户控制受控主机 控制端1台,受控端两台 1.将两台受控主机添加到/etc/hosts文件中 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhos…

Qt5.13引入QtWebApp的模块后报错: error C2440: “reinterpret_cast”: 无法从“int”转换为“quintptr”

1、开发环境 Win10-64 qt5.13 msvc2015-64bit-release 2、报错 新建一个demo工程。 引入QtWebApp的httpserver、logging、templateengine三个模块后。 直接运行,,此时报错如下: E:\Qt5.13.1\install\5.13.1\msvc2015_64\include\QtCore…

Java 8 中使用 Stream 遍历树形结构

在实际开发中,我们经常会开发菜单,树形结构,数据库一般就使用父id来表示,为了降低数据库的查询压力,我们可以使用Java8中的Stream流一次性把数据查出来,然后通过流式处理,我们一起来看看&#x…

GEE:矢量数据去除重复值(输出样本点数据的标签信息)

作者:CSDN @ _养乐多_ 本文记录了在GoogleEarthEngine(GEE)平台上,将样本点数据中某个字段的值去除重复值,并将剩下的值打印到控制台的代码。该代码可以用于快速在GEE平台上查询土地利用分类信息中landcover的类别信息。 矢量数据信息如下所示, 打印结果如下所示, 文章…

Flask-SocketIO

一、简介: Flask-SocketIO使Flask应用程序可以实现客户端和服务器之间的低延迟双向通信。客户端应用程序可以使用 Javascript、Python、C、Java和Swift中的任何SocketIO客户端库或任何其他兼容客户端来建立与服务器的永久连接。 二、安装: pip instal…

【TypeScript】类型断言的基本使用

类型断言的概念 有些时候开发者比TS本身更清楚当前的类型是什么&#xff0c;可以使用断言&#xff08;as&#xff09;让类型更加精确和具体。 类型断言&#xff08;Type Assertion&#xff09;表示可以用来手动指定一个值的类型。 类型断言语法&#xff1a; 值 as 类型 或 <…

4.2的幂次方表示

【题目】 任何一个正整数都可以用2进制表示&#xff0c;例如&#xff1a;137的2进制表示为10001001。 将这种2进制表示写成2的次幂的和的形式&#xff0c;令次幂高的排在前面&#xff0c;可得到如下表达式&#xff1a;137 2^7 2^3 2^0 现在约定幂次用括号来表示&#xff0…