Android Q 版本新的网络状况判断方式

当targetSdkVersion <29 之前判断设备当前是否连接网络的时候,直接用的getActiveNetworkInfo是这样的方式:

 // 当前网络是否可用
    public boolean isInternetAvailable() {
        ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();

        return networkInfo != null && networkInfo.isConnected();
    }

但是当targetSdkVersion=29的时候,ConnectivityManager.getActiveNetworkInfo()方法被标为deprecated了。根据Google官方文档中提供了几个新API来获取当前的网络状态。

1.异步获取
		使用ConnectivityManager.NetworkCallback回调。
2.同步获取
	    使用ConnectivityManager.getNetworkCapabilities(network: Network?)和ConnectivityManager.getLinkProperties(network: Network?)方法。
需要注意的点:
  1. 异步回调的方式会将网络状况改变事件按发生的顺序依次进行回调,也就是说可能会产生延迟,拿到的不是实时网络状况,可能是几ms之前的状态(这里需要测试一下回调速度!!!!!!)。
  2. 同步获取的方则没有此限制。官方还提了一嘴,由于这两种方式各自的特性,如果在异步回调再通过同步的方式获取网络状态,两者拿到的结果可能是不一样的,不过我相信应该没人会这么干吧。另外官方是建议通过回调来获取网络状况改变的事件,进而获取当前的网络状况的。

异步回调方式api>=24

ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            connectivityManager.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback() {
                @Override
                public void onAvailable(Network network) {
                    super.onAvailable(network);
                }

                @Override
                public void onLosing(Network network, int maxMsToLive) {
                    super.onLosing(network, maxMsToLive);
                }

                @Override
                public void onLost(Network network) {
                    super.onLost(network);
                }

                @Override
                public void onUnavailable() {
                    super.onUnavailable();
                }

                @Override
                public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
                    super.onCapabilitiesChanged(network, networkCapabilities);
                }

                @Override
                public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
                    super.onLinkPropertiesChanged(network, linkProperties);
                }

                @Override
                public void onBlockedStatusChanged(Network network, boolean blocked) {
                    super.onBlockedStatusChanged(network, blocked);
                }
            });

        }

tip:
建议只监测onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities)回调,因为别的回调在连接上VPN后,在APP使用过程中就完全不会被调用。

会调用,可能常用的API就以下几个:

  1. hasCapability
networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_XXX)

括号中的参数主要用到的就是NetworkCapabilities.NET_CAPABILITY_INTERNET和NetworkCapabilities.NET_CAPABILITY_VALIDATED

NET_CAPABILITY_INTERNET:表示是否连接到互联网,即是否连接上了WIFI或者移动蜂窝网络,这个为TRUE不一定能正常上网

NET_CAPABILITY_VALIDATED:表示是否确实能和连接的互联网通信,这个为TRUE,才是真的能上网

tip:
其余还有十几个参数,各自的意思,直接看文档或者源码即可。
这些参数表示的状态是可以共存的,也就是说networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)和networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)的返回值可能同时为TRUE。

  1. hasTransport
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_XXX)

括号中的参数主要用到的就是NetworkCapabilities.TRANSPORT_CELLULAR和NetworkCapabilities.TRANSPORT_WIFI

TRANSPORT_CELLULAR:表示当前接入的是否是蜂窝网络
TRANSPORT_WIFI:表明当前接入的是WIFI网络,还有一些别的蓝牙网络,有线网络等等可以直接查看文档或源码了解

tip:
这些参数表示的状态是不可共存的,即你不可能又连接到蜂窝网络又连接到WIFI网络,它们同时只会有一个返回TRUE。

同步获取状态api>=23

 ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {

            NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(connectivityManager.getActiveNetwork());
            if(networkCapabilities!=null && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
                    networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)){
                return true;

            }

        }

综合

对目前使用的获取当前是否联网的工具方法改造一下。虽然Google是建议使用回调,但我还是用同步方法吧,这样就不用又是回调又是同步获取那么麻烦了,顺手一点。

 /**
     * 检测网络连接状态是否可用
     *
     * @return
     */
    public boolean isNetAvailable(Context context) {
        if (context!= null) {
            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            if (cm != null) {
                if (Build.VERSION.SDK_INT < 23) {
                    NetworkInfo mWiFiNetworkInfo = cm.getActiveNetworkInfo();
                    if (mWiFiNetworkInfo != null) {
                        if (mWiFiNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI) {//WIFI
                            return true;
                        } else if (mWiFiNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {//移动数据
                            return true;
                        }
                    }
                } else {
                    Network network = cm.getActiveNetwork();
                    if (network != null) {
                        NetworkCapabilities nc = cm.getNetworkCapabilities(network);
                        if (nc != null) {
                            if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {//WIFI
                                return true;
                            } else if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {//移动数据
                                return true;
                            }
                        }
                    }
                }
            }
        }
        return false;
    }

你可能感兴趣的:(android)