一. 问题背景
Android12上,有的app模块判断当前网络的类型和连接状态时,还是使用的旧的API,导致返回的结果不准确,影响代码逻辑判断,本篇文章就这一问题,整理一下判断网络类型和连接状态的新方法。
二. 原因分析
在Android 10以前的版本,大家都是通过NetworkInfo.java 的getType()方法获取网络类型,通过isConnected()方法来判断是否连接上, 判断网络连接的旧方法如下:
是否连接:
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 | 当网络状态改变时回调,比如信号强度切换,或者连接上网络—>断开网络,或者 mobile网络切换到Wifi网络,都会回调 |
onAvailable | 网络连接成功 但不能判断该网络是否可以正常上网 |
onUnavailable | 当网络连接超时或网络请求达不到可用要求时调用 |
onBlockedStatusChanged | 当访问指定的网络被阻止或解除阻塞时调用 |
onLosing | 当网络正在断开连接时调用 |
onLost | 当网络已断开连接时调用 |
onLinkPropertiesChanged | 当网络连接的属性被修改时调用 |
接下来再说一下
NetworkCapabilities.java类中的NET_CAPABILITY_VALIDATED字段,描述为:
表示此网络上的连接已成功验证。例如,对于具有NET_CAPABILITY_INTERNET的网络,这意味着已成功检测到INTERNET连接。
通过实际log来描述说明一下:
1. 连接上可上网的wifi,可看到VALIDATED的标记:
连接上需要认证和不能上网的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; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); networkService = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE); if (networkService != null) { //注册 NetworkCallBack networkService.registerDefaultNetworkCallback(networkCallBack); } } @Override protected 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)); } @Override protected void onDestroy() { super.onDestroy(); if (networkService != null && networkCallBack != null) { networkService.unregisterNetworkCallback(networkCallBack); } } private final ConnectivityManager.NetworkCallback networkCallBack = new ConnectivityManager.NetworkCallback(){ //当网络状态修改但仍旧是可用状态时调用 @Override public 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传输====="); } } } @Override public void onAvailable(@NonNull Network network) { super.onAvailable(network); Log.e(TAG, "==网络连接成功,通知可以使用的时候调用====onAvailable==="); } @Override public void onUnavailable() { Log.e(TAG, "==当网络连接超时或网络请求达不到可用要求时调用====onUnavailable==="); super.onUnavailable(); } @Override public void onBlockedStatusChanged(@NonNull Network network, boolean blocked) { Log.e(TAG, "==当访问指定的网络被阻止或解除阻塞时调用===onBlockedStatusChanged=="); super.onBlockedStatusChanged(network, blocked); } @Override public void onLosing(@NonNull Network network, int maxMsToLive) { Log.e(TAG, "==当网络正在断开连接时调用===onLosing==="); super.onLosing(network, maxMsToLive); } @Override public void onLost(@NonNull Network network) { Log.e(TAG, "==当网络已断开连接时调用===onLost==="); super.onLost(network); } @Override public 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"; public static final int TRANSPORT_CELLULAR = 0; public static final int TRANSPORT_WIFI = 1; public static final int TRANSPORT_BLUETOOTH = 2; public static final int TRANSPORT_ETHERNET = 3; public static final int TRANSPORT_VPN = 4; public static final int TRANSPORT_WIFI_AWARE = 5; public static final int TRANSPORT_LOWPAN = 6; public static final int TRANSPORT_TEST = 7; public static final int TRANSPORT_USB = 8; 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); } 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); } 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); } 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); } 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方法, 工具类可以根据业务需求去扩展, 供参考。
来源地址:https://blog.csdn.net/u012514113/article/details/132091769