监听网络变化--含7.0以上适配
我们知道最早监听网络变化,是通过广播,静态或动态注册广播,处理"android.net.conn.CONNECTIVITY_CHANGE"这个action就可以了intent就可以了。
我们发现"android.net.conn.CONNECTIVITY_CHANGE"这个action已经加了注解@Deprecated,不推荐使用了。根据注释说明,7.0及以上静态注册广播(manifest中)不能收到这个广播了,但是动态注册的广播还可以收到。 所以一般思路就是 判断一下,7.0及以后 增加动态注册就可以了。
同时还有一段说明,说应该使用 更牛逼、 更多功能、更多细节的 {@link #requestNetwork},
{@link #registerNetworkCallback} or {@link #registerDefaultNetworkCallback}。
注意到这些方式是回调的方式,也必须APP运行才可以了。我们知道 静态注册广播接收器不需要App运行也能收到, 也就是说随着系统的更迭,网络变化的获取只能在App运行期间了。这是Android系统对权限的限制。
同时注意到,推荐使用的方法要求是 在5.0及以上的。

所以总结一下就是两个方式处理网络变化监听的适配了:
1、使用广播,7.0及7.0以前使用静态注册,以后使用动态注册。(或者直接 全版本使用动态注册)
2、7.0以前使用静态广播,7.0及以后使用回调方式registerNetworkCallback等。
(或者5.0以前使用广播(动态或静态),5.0及一会使用回调方式)
因为新的回调方式,可以提供更细节更牛逼的功能,且是官方推荐的,那就采用第2个方法。
关于registerNetworkCallback(NetworkRequest request, NetworkCallback networkCallback)参数NetworkCallback 回调方法的说明,建议查看官方文档,这里简单说明:
public static class NetworkCallback {
/**
*连接网络了,开计算是否满足要求
*/
public void onPreCheck(Network network) {}
/**
* 网络准备可用了
*/
public void onAvailable(Network network, NetworkCapabilities networkCapabilities,
LinkProperties linkProperties) {
onAvailable(network);
if (!networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)) {
onNetworkSuspended(network);
}
onCapabilitiesChanged(network, networkCapabilities);
onLinkPropertiesChanged(network, linkProperties);
}
/**
* 网络准备可用了
*/
public void onAvailable(Network network) {}
/**
* 网络将要断开
*/
public void onLosing(Network network, int maxMsToLive) {}
/**
* 网络断开
*/
public void onLost(Network network) {}
/**
* 网络不可用
*/
public void onUnavailable() {}
/**
* 网络能力变化,还是可用状态,可能多次调用
*/
public void onCapabilitiesChanged(Network network,
NetworkCapabilities networkCapabilities) {}
/**
* 链接属性改变
*/
public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {}
/**
* 网络暂停
*/
public void onNetworkSuspended(Network network) {}
/**
* 网络恢复
*/
public void onNetworkResumed(Network network) {}
private NetworkRequest networkRequest;
}
回调方法很多,网络变化的各种状态,广播是没有这个功能的。这些方法的回调时机可以自行测试,或者看这篇android 5.0 以上监听网络变化。
下面就给出我的实现方式:
/**
* 网络连接变化 监听帮助类
*
* 说明:
* 1、静态注册广播监听网络变化 的方式,{@link ConnectivityManager#CONNECTIVITY_ACTION}已有说明,
* 7.0及以后 静态注册的接收器不会收到 CONNECTIVITY_ACTION,只能用动态注册。(这是官方对广播权限的限制)
* 2、5.0后有新的api{@link ConnectivityManager.NetworkCallback} ,但是只能在app 存活时监听到。和动态注册效果类似,但有更多细节的回调。
*
* 综合这两点,本类实现方案:7.0及以后使用新api,只能在app存活时接收到回调;7.0以前使用静态注册广播。
*/
public class NetworkChangeListenHelper {
/**
* 网络不可用
*/
private static final int NETWORK_STATE_UNAVAILABLE = -1;
/**
* 网络可用
*/
private static final int NETWORK_STATE_AVAILABLE = 0;
// /**
// * 网络可用,且是移动数据
// */
// private static final int NETWORK_STATE_AVAILABLE_MOBILE = 1;
//
// /**
// * 网络可用,且是wifi
// */
// private static final int NETWORK_STATE_AVAILABLE_WIFI = 2;
private static NetworkChangeListener mNetworkChangeListener;
public boolean hasRegistNetworkCallback(){
return mNetworkChangeListener != null;
}
public void registerNetworkCallback(NetworkChangeListener networkChangeListener) {
if (hasRegistNetworkCallback()) {
XLogUtil.d("hasRegistNetworkCallback");
return;
}
mNetworkChangeListener = networkChangeListener;
//7.0及以后 使用这个新的api(7.0以前还是用静态注册广播)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
ConnectivityManager connectivityManager = (ConnectivityManager) MyApplication.getInstance().getSystemService(Context.CONNECTIVITY_SERVICE);
// 请注意这里会有一个版本适配bug,所以请在这里添加非空判断
if (connectivityManager != null) {
NetworkRequest request = new NetworkRequest.Builder().build();
connectivityManager.registerNetworkCallback(request, new AkuNetworkCallback());
}
}
}
private void handleOnNetworkChange(int networkState) {
if (mNetworkChangeListener == null) {
return;
}
switch (networkState){
case NETWORK_STATE_UNAVAILABLE:
mNetworkChangeListener.onNetworkChange(false);
break;
case NETWORK_STATE_AVAILABLE:
mNetworkChangeListener.onNetworkChange(true);
break;
// case NETWORK_STATE_AVAILABLE_WIFI:
// mNetworkChangeListener.onNetworkChange(true);
// break;
default:
break;
}
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class AkuNetworkCallback extends ConnectivityManager.NetworkCallback{
@Override
public void onAvailable(Network network) {
super.onAvailable(network);
XLogUtil.d("网络连接了");
handleOnNetworkChange(NETWORK_STATE_AVAILABLE);
}
@Override
public void onLost(Network network) {
super.onLost(network);
XLogUtil.d("网络断开了");
handleOnNetworkChange(NETWORK_STATE_UNAVAILABLE);
}
@Override
public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
super.onCapabilitiesChanged(network, networkCapabilities);
//网络变化时,这个方法会回调多次
if(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)){
if(networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)){
XLogUtil.d("wifi网络已连接");
// handleOnNetworkChange(NETWORK_STATE_AVAILABLE_WIFI);
}else {
XLogUtil.d("移动网络已连接");
// handleOnNetworkChange(NETWORK_STATE_AVAILABLE_MOBILE);
}
}
}
}
public static class NetworkChangeBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//7.0以下用静态广播
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
return;
}
if (intent == null) {
return;
}
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
return;
}
if (mNetworkChangeListener == null) {
return;
}
boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
mNetworkChangeListener.onNetworkChange(!noConnectivity);
}
}
/**
* NetworkChangeListener
*/
public interface NetworkChangeListener {
void onNetworkChange(boolean isNetworkAvailable);
}
}
使用方式,很简单:
/**
* 监听网络变化
*/
private static void registerNetworkListener() {
if (mNetworkChangeListenHelper != null && mNetworkChangeListenHelper.hasRegistNetworkCallback()) {
return;
}
mNetworkChangeListenHelper = new NetworkChangeListenHelper();
mNetworkChangeListenHelper.registerNetworkCallback(new NetworkChangeListenHelper.NetworkChangeListener() {
@Override
public void onNetworkChange(boolean isNetworkAvailable) {
if (!isNetworkAvailable) {
//没网啦,do something
return;
}
//有网啦,do something
}
});
}
别忘了,在manifest中注册:
<receiver
android:name=".NetworkChangeListenHelper$NetworkChangeBroadcastReceiver"
android:exported="true">
<intent-filter >
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
<action android:name="android.Net.wifi.WIFI_STATE_CHANGED" />
<action android:name="android.net.wifi.STATE_CHANGE" />
</intent-filter>
</receiver>
好了,讲完啦~