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

以你之姓@ 2024-03-23 17:48 152阅读 0赞

一. 问题背景

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

二. 原因分析

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

1.是否连接:

bf37be913e044639924f0ae4ec5d0e07.png

  1. 网络类型

5eca91a6a03c4dcda6bea05a49f468d1.png

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

171b18346f5543a29a61296187fe2952.png

97b13e4879ef4064b7acda85ad9fc984.png

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

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

511d0417f8204883a915256f1dd8fc37.png

看下官方说明:

0deb2193f38442ea8249509b5fbf810b.png

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

三. 官方推荐API

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

39359488b38044cd924253455dd75a94.png

体使用方法如下:

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

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

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




































回调方法

描述

onCapabilitiesChanged

当网络状态改变时回调,比如信号强度切换,或者连接上网络—>断开网络,或者 mobile网络切换到Wifi网络,都会回调

onAvailable

网络连接成功 但不能判断该网络是否可以正常上网

onUnavailable

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

onBlockedStatusChanged

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

onLosing

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

onLost

当网络已断开连接时调用

onLinkPropertiesChanged

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

接下来再说一下

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

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

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

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

f649c93f39b34afcb33824e8a51a07a7.png

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

2691fc8845164a4099de807d6973ead1.png

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

d2db6544d59c4f318196fd5352e71e3e.png

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

9cce5d2018374ae1a5fea84fa45e8086.png

四. 使用方法

看代码更直接一点:

MainActivity.java

  1. @SuppressLint("NewApi")
  2. public class MainActivity extends AppCompatActivity {
  3. private static final String TAG = "ConnectManager";
  4. private ConnectivityManager networkService;
  5. @Override
  6. protected void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.activity_main);
  9. networkService = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
  10. if (networkService != null) {
  11. //注册 NetworkCallBack
  12. networkService.registerDefaultNetworkCallback(networkCallBack);
  13. }
  14. }
  15. /*
  16. * 测试网络工具类方法
  17. * */
  18. @Override
  19. protected void onResume() {
  20. super.onResume();
  21. //Log.e(TAG, "=====在onResume方法中判断 : isMobileNetwork :" + NetworkUtils.isMobileNetwork(this));
  22. //Log.e(TAG, "=====在onResume方法中判断 : isWifiNetwork :" + NetworkUtils.isWifiNetwork(this));
  23. //Log.e(TAG, "=====在onResume方法中判断 : getConnectedNetworkType :" + NetworkUtils.getConnectedNetworkType(this));
  24. }
  25. @Override
  26. protected void onDestroy() {
  27. super.onDestroy();
  28. if (networkService != null && networkCallBack != null) {
  29. networkService.unregisterNetworkCallback(networkCallBack);
  30. }
  31. }
  32. private final ConnectivityManager.NetworkCallback networkCallBack = new ConnectivityManager.NetworkCallback(){
  33. //当网络状态修改但仍旧是可用状态时调用
  34. @Override
  35. public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
  36. super.onCapabilitiesChanged(network, networkCapabilities);
  37. if (NetworkUtils.isConnectedAvailableNetwork(getBaseContext())) {
  38. Log.d(TAG, "onCapabilitiesChanged ---> ====网络可正常上网===网络类型为: "+ NetworkUtils.getConnectedNetworkType(MainActivity.this));
  39. }
  40. //表明此网络连接验证成功
  41. if(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
  42. if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
  43. Log.d(TAG, "===当前在使用Mobile流量上网===");
  44. } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
  45. Log.d(TAG, "====当前在使用WiFi上网===");
  46. } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH)) {
  47. Log.d(TAG, "=====当前使用蓝牙上网=====");
  48. } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
  49. Log.d(TAG, "=====当前使用以太网上网=====");
  50. } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
  51. Log.d(TAG, "===当前使用VPN上网====");
  52. } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE)) {
  53. Log.d(TAG, "===表示此网络使用Wi-Fi感知传输====");
  54. } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_LOWPAN)) {
  55. Log.d(TAG, "=====表示此网络使用LoWPAN传输=====");
  56. } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_USB)) {
  57. Log.d(TAG, "=====表示此网络使用USB传输=====");
  58. }
  59. }
  60. }
  61. @Override
  62. public void onAvailable(@NonNull Network network) {
  63. super.onAvailable(network);
  64. Log.e(TAG, "==网络连接成功,通知可以使用的时候调用====onAvailable===");
  65. }
  66. @Override
  67. public void onUnavailable() {
  68. Log.e(TAG, "==当网络连接超时或网络请求达不到可用要求时调用====onUnavailable===");
  69. super.onUnavailable();
  70. }
  71. @Override
  72. public void onBlockedStatusChanged(@NonNull Network network, boolean blocked) {
  73. Log.e(TAG, "==当访问指定的网络被阻止或解除阻塞时调用===onBlockedStatusChanged==");
  74. super.onBlockedStatusChanged(network, blocked);
  75. }
  76. @Override
  77. public void onLosing(@NonNull Network network, int maxMsToLive) {
  78. Log.e(TAG, "==当网络正在断开连接时调用===onLosing===");
  79. super.onLosing(network, maxMsToLive);
  80. }
  81. @Override
  82. public void onLost(@NonNull Network network) {
  83. Log.e(TAG, "==当网络已断开连接时调用===onLost===");
  84. super.onLost(network);
  85. }
  86. @Override
  87. public void onLinkPropertiesChanged(@NonNull Network network, @NonNull LinkProperties linkProperties) {
  88. Log.e(TAG, "==当网络连接的属性被修改时调用===onLinkPropertiesChanged===");
  89. super.onLinkPropertiesChanged(network, linkProperties);
  90. }
  91. };
  92. }

网络工具类NetworkUtils.java

  1. @SuppressLint("NewApi")
  2. public class NetworkUtils {
  3. private static final String TAG = "ConnectManager";
  4. /**
  5. * Indicates this network uses a Cellular transport.
  6. */
  7. public static final int TRANSPORT_CELLULAR = 0;
  8. /**
  9. * Indicates this network uses a Wi-Fi transport.
  10. */
  11. public static final int TRANSPORT_WIFI = 1;
  12. /**
  13. * Indicates this network uses a Bluetooth transport.
  14. */
  15. public static final int TRANSPORT_BLUETOOTH = 2;
  16. /**
  17. * Indicates this network uses an Ethernet transport.
  18. */
  19. public static final int TRANSPORT_ETHERNET = 3;
  20. /**
  21. * Indicates this network uses a VPN transport.
  22. */
  23. public static final int TRANSPORT_VPN = 4;
  24. /**
  25. * Indicates this network uses a Wi-Fi Aware transport.
  26. */
  27. public static final int TRANSPORT_WIFI_AWARE = 5;
  28. /**
  29. * Indicates this network uses a LoWPAN transport.
  30. */
  31. public static final int TRANSPORT_LOWPAN = 6;
  32. /**
  33. * Indicates this network uses a Test-only virtual interface as a transport.
  34. * @hide
  35. */
  36. public static final int TRANSPORT_TEST = 7;
  37. /**
  38. * Indicates this network uses a USB transport.
  39. */
  40. public static final int TRANSPORT_USB = 8;
  41. /**
  42. * >= Android 10(Q版本)推荐
  43. *
  44. * 当前使用MOBILE流量上网
  45. */
  46. public static boolean isMobileNetwork(Context context) {
  47. ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
  48. Network network = cm.getActiveNetwork();
  49. if (null == network) {
  50. return false;
  51. }
  52. NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
  53. if (null == capabilities) {
  54. return false;
  55. }
  56. return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
  57. && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
  58. }
  59. /**
  60. * >= Android 10(Q版本)推荐
  61. *
  62. * 当前使用WIFI上网
  63. */
  64. public static boolean isWifiNetwork(Context context) {
  65. ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
  66. Network network = cm.getActiveNetwork();
  67. if (null == network) {
  68. return false;
  69. }
  70. NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
  71. if (null == capabilities) {
  72. return false;
  73. }
  74. return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
  75. && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
  76. }
  77. /**
  78. * >= Android 10(Q版本)推荐
  79. *
  80. * 当前使用以太网上网
  81. */
  82. public static boolean isEthernetNetwork(Context context) {
  83. ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
  84. Network network = cm.getActiveNetwork();
  85. if (null == network) {
  86. return false;
  87. }
  88. NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
  89. if (null == capabilities) {
  90. return false;
  91. }
  92. return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)
  93. && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
  94. }
  95. /**
  96. * >= Android 10(Q版本)推荐
  97. *
  98. * NetworkCapabilities.NET_CAPABILITY_INTERNET,表示此网络应该(maybe)能够访问internet
  99. *
  100. * 判断当前网络可以正常上网
  101. * 表示此连接此网络并且能成功上网。 例如,对于具有NET_CAPABILITY_INTERNET的网络,这意味着已成功检测到INTERNET连接。
  102. */
  103. public static boolean isConnectedAvailableNetwork(Context context) {
  104. ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
  105. Network network = cm.getActiveNetwork();
  106. if (null == network) {
  107. return false;
  108. }
  109. NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
  110. if (null == capabilities) {
  111. return false;
  112. }
  113. return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
  114. && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
  115. }
  116. /**
  117. * >= Android 10(Q版本)推荐
  118. *
  119. * 获取成功上网的网络类型
  120. * value = {
  121. * TRANSPORT_CELLULAR, 0 表示此网络使用蜂窝传输。
  122. * TRANSPORT_WIFI, 1 表示此网络使用Wi-Fi传输。
  123. * TRANSPORT_BLUETOOTH, 2 表示此网络使用蓝牙传输。
  124. * TRANSPORT_ETHERNET, 3 表示此网络使用以太网传输。
  125. * TRANSPORT_VPN, 4 表示此网络使用VPN传输。
  126. * TRANSPORT_WIFI_AWARE, 5 表示此网络使用Wi-Fi感知传输。
  127. * TRANSPORT_LOWPAN, 6 表示此网络使用LoWPAN传输。
  128. * TRANSPORT_TEST, 7 指示此网络使用仅限测试的虚拟接口作为传输。
  129. * TRANSPORT_USB, 8 表示此网络使用USB传输
  130. * }
  131. */
  132. public static int getConnectedNetworkType(Context context) {
  133. ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
  134. Network network = cm.getActiveNetwork();
  135. if (null == network) {
  136. return -1;
  137. }
  138. NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
  139. if (null == capabilities) {
  140. return -1;
  141. }
  142. if (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
  143. if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
  144. return NetworkCapabilities.TRANSPORT_CELLULAR;
  145. } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
  146. return NetworkCapabilities.TRANSPORT_WIFI;
  147. } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH)) {
  148. return NetworkCapabilities.TRANSPORT_BLUETOOTH;
  149. } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
  150. return NetworkCapabilities.TRANSPORT_ETHERNET;
  151. } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
  152. return NetworkCapabilities.TRANSPORT_VPN;
  153. } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE)) {
  154. return NetworkCapabilities.TRANSPORT_WIFI_AWARE;
  155. } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_LOWPAN)) {
  156. return NetworkCapabilities.TRANSPORT_LOWPAN;
  157. } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_USB)) {
  158. return NetworkCapabilities.TRANSPORT_USB;
  159. }
  160. }
  161. return -1;
  162. }
  163. }

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

发表评论

表情:
评论列表 (有 0 条评论,152人围观)

还没有评论,来说两句吧...

相关阅读