最近项目升级到Android29版本发现网络连接及网络类型的好多方法都被弃用了。比如以往获取网络状态我们会使用NetworkInfo来获取但是现在这个类已经完全被抛弃了。而Google官网推荐我们使用ConnectivityManager#NetworkCallback回调的这种方式,也可以使用ConnectivityManager#getNetworkCapabilities或者ConnectivityManager#getLinkProperties的方式直接获取网络类型等信息。官网地址:https://developer.android.google.cn/reference/android/net/NetworkInfo
那如何通过Android29提供的新API后去网络连接及状态。
通过上图大家可以大概了解到获取网络连接及状态的几个类。其中NetworkManager是一个单例用来管理和分发网络连接及状态。NetworkCallbackImpl是ConnectivityManager#NetworkCallback的实现类用来获取网络变化是的连接状态和网络类型。Network中包含的是一些回调的抽象类、枚举、公共的一些方法等。最下面的NetworkReceiver和NetworkService是为了兼容Android21版本以下的终端获取网络连接和状态使用的类。
首先我们先从NetworkCallbackImpl类说起,这个类继承了ConnectivityManager#NetworkCallback并实现了其中的三个方法。请看如下代码:
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
class NetworkCallbackImpl(val isConnection: (isconn: Boolean) -> Unit, val getNetType: (type: NetType) -> Unit) : ConnectivityManager.NetworkCallback() {
/**
* 网络连接方法
* @param network
*/
override fun onAvailable(network: Network) {
super.onAvailable(network)
isConnection(true)
}
/**
* 网络断开方法
* @param network
*/
override fun onLost(network: Network) {
super.onLost(network)
isConnection(false)
}
/**
* 检测网络类型
* @param network
* @param networkCapabilities
*/
override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
super.onCapabilitiesChanged(network, networkCapabilities)
if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
getNetType(getNetType21(networkCapabilities))
}
}
}
其中onAvailable方法在通过ConnectivityManager中注册的时候会调用一次,而后当网络断开后再次连接会被再次调用。onLost也是如此。但是在这里需要强调一点onCapabilitiesChanged方法在注册的时候不会回调只能等到网络重新连接该方法才会回调。这样就会导致我们打开程序的时候获取不到网络类型。不过没有关系因为ConnectivityManager类给我们提供了getNetworkCapabilities方法,可以手动获取当先网络类型(这个少狗再说)。该类中我还传递了两个方法isConnection和getNetType用来通知Manager当前网络的相关信息。
需要注意的是在onCapabilitiesChanged中用到了getNetType21方法可以通过反馈的NetworkCapabilities获取到网络类型。该类型如下几种
private static final String[] TRANSPORT_NAMES = {
"CELLULAR",
"WIFI",
"BLUETOOTH",
"ETHERNET",
"VPN",
"WIFI_AWARE",
"LOWPAN",
"TEST"
};
这七种类型所对应的常亮标记为:
/**
* 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;
接下来看一下NetworkManager管理器。管理器主要的作用就是初始化ConnectivityManager对象,注册我们继承的NetworkCallBack对象及注册回调等功能,想必这个一看代码就能够理解很简单无难度。
/**
* 初始化方法
*/
@SuppressLint("MissingPermission")
fun init(context: Context) {
mContext = context
if (isHigherThenLollipop()) {
networkCallbackImpl = NetworkCallbackImpl(::observerIsConnection, ::observerNetWorkType)
val request = NetworkRequest.Builder().build()
val manager = INSTANCE.mContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
manager.registerNetworkCallback(request, networkCallbackImpl)
netType = if (isHigherThenM()) {
try {
val capabilities = manager.getNetworkCapabilities(manager.activeNetwork)
getNetType21(capabilities)
}catch (e : Exception){
e.printStackTrace()
NetType.NONE
}
} else {
getNetType(manager)
}
} else {
if (!EventBus.getDefault().isRegistered(INSTANCE))
EventBus.getDefault().register(INSTANCE)
//开启服务
mContext.startService(Intent(mContext, NetworkService::class.java))
}
}
初始化方法用于注册NetworkCallback子类对象到ConnectivityManager中。后面判断版本是否高于M(isHigherThenM)是为了解决注册时候的时候不能回调onCapabilitiesChanged方法而无法获取网络类型问题。其中getNetType21是Android21版本以上的获取方法,21版本一下获取方式使用的是getNetType方法获取。具体代码可以下载文末的Demo。位置在Network.kt文件中。
状态的分发本来想使用Java反射的方式进行事件的分发,但是有一个问题就是如果使用反射就涉及到代码混淆的问题。为了避免这个问题选择了回调。感兴趣的朋友也可以使用EventBus或者其他方式。如果有更好的方法希望在评论区转告我谢谢。
演示代码地址:https://github.com/liming870906/NetworkTools/tree/master