DevYM Note

Do what you like is the most important thing !

Android即时监听网络状态

前言

记录开发成长过程中的点点滴滴,在探索的道路上从未止步,共勉!!!

近期重新梳理了下之前封装的即时监听网络状态变化功能逻辑,此文记录下整个思路。

即时监听网络状态变化功能的应用场景还是比较广泛的,比如网络断开时给出提示、WiFi切换到蜂窝移动网络时播放视频下载文件等提示用户注意流量消耗等。

从API Level 21也就是Android5.0新增的一种监听网络状态回调的方式ConnectivityManager.NetworkCallback,对于Android5.0以下设备则采用通过接收系统发送的android.net.conn.CONNECTIVITY_CHANGE广播的方式来实现。

具体的实现逻辑

  • 由于兼容了两种方式来实现,因此这里采用了接口分离原则,首先定义一个接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* Created by DevYM
* description:网络状态监听接口
*/
public interface INetwork {

void registerObserver(Object observer);

void unRegisterObserver(Object observer);

void registerNetworkCallback();

void unRegisterNetworkCallback();

}
  • 再创建一个单例类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/**
* Created by DevYM
* description:NetworkManager单例
*/
public class NetworkManager {
private static volatile NetworkManager instance;
private final INetwork networkCallback;
private Application application;

private NetworkManager() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
networkCallback = new NetworkCallbackImpl();
} else {
networkCallback = new NetworkStateReceiver();
}
}

public static NetworkManager getInstance() {
if (instance == null) {
synchronized (NetworkManager.class) {
if (instance == null) {
instance = new NetworkManager();
}
}
}
return instance;
}

public Application getApplication() {
if (application == null) {
throw new NullPointerException("application is not init");
}
return application;
}

public void init(Application application) {
if (this.application == null) {
this.application = application;
networkCallback.registerNetworkCallback();
}
}

public void unRegisterNetworkCallback() {
networkCallback.unRegisterNetworkCallback();
application = null;
}

public void registerObserver(Object observer) {
networkCallback.registerObserver(observer);
}

public void unRegisterObserver(Object observer) {
networkCallback.unRegisterObserver(observer);
}

}
  • 创建一个枚举类用来区分网络状态
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* Created by DevYM
* description:网络类型枚举
*/
public enum NetworkType {

AUTO, // 有网络

WIFI, // WIFI

MOBILE, // 移动网络

NONE, // 没有网络
}
  • Android5.0以上采用实现ConnectivityManager.NetworkCallback类方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/**
* Created by DevYM
* description:网络状态回调实现类
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class NetworkCallbackImpl extends ConnectivityManager.NetworkCallback implements INetwork {
private ConnectivityManager connectivityManager;
private final List<Network> networkList;
private final Map<Object, List<MethodBean>> methodMap;

public NetworkCallbackImpl() {
networkList = new ArrayList<>();
methodMap = new ArrayMap<>();
}

@Override
public void onAvailable(Network network) {
super.onAvailable(network);
networkList.add(network);
}

@Override
public void onLost(Network network) {
super.onLost(network);
networkList.remove(network);
if (networkList.isEmpty()) {
NetworkUtils.postNetworkTypeCallback(methodMap, NetworkType.NONE);
}
}

@Override
public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
super.onCapabilitiesChanged(network, networkCapabilities);
if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
NetworkType networkType;
if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
networkType = NetworkType.WIFI;
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
networkType = NetworkType.MOBILE;
} else {
networkType = NetworkType.AUTO;
}
NetworkUtils.postNetworkTypeCallback(methodMap, networkType);
}
}

public void registerObserver(Object observer) {
// observer所有网络监听注解方法
List<MethodBean> methodList = methodMap.get(observer);
if (methodList == null) {
// 添加方法
methodList = NetworkUtils.findAnnotationMethod(observer);
methodMap.put(observer, methodList);
}
}

/**
* 从集合中移除
*
* @param observer
*/
public void unRegisterObserver(Object observer) {
if (!methodMap.isEmpty()) {
methodMap.remove(observer);
}
}

@Override
public void registerNetworkCallback() {
if (connectivityManager == null) {
NetworkRequest.Builder builder = new NetworkRequest.Builder();
NetworkRequest request = builder.build();
connectivityManager = (ConnectivityManager) NetworkManager.getInstance().getApplication().getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager != null) {
connectivityManager.registerNetworkCallback(request, this);
}
}
}

@Override
public void unRegisterNetworkCallback() {
// 应用退出时
if (!methodMap.isEmpty()) {
methodMap.clear();
}
if (connectivityManager != null) {
connectivityManager.unregisterNetworkCallback(this);
connectivityManager = null;
}
}
}
  • 动态注册广播方式监听网络变化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/**
* Created by DevYM on 2019/7/5
* description:网络状态变化广播方式监听
*/
public class NetworkStateReceiver extends BroadcastReceiver implements INetwork {
private NetworkType curNetworkType;
private final Map<Object, List<MethodBean>> methodMap;

public NetworkStateReceiver() {
methodMap = new HashMap<>();
}

@Override
public void onReceive(Context context, Intent intent) {
if (intent == null || intent.getAction() == null) return;
if (intent.getAction().equalsIgnoreCase(NetworkUtils.ANDROID_NETWORK_CHANGE_ACTION)) {
// 监听到网络状态
NetworkType tempType;
if (NetworkUtils.isNetworkAvailable()) {
tempType = NetworkUtils.getNetType();
} else {
tempType = NetworkType.NONE;
}
if (tempType != null && tempType != curNetworkType) {
curNetworkType = tempType; // 防止多次刷新重复状态的情况
NetworkUtils.postNetworkTypeCallback(methodMap, curNetworkType); // 总线:全局通知
}
}
}

public void registerObserver(Object observer) {
// observer所有网络监听注解方法
List<MethodBean> methodList = methodMap.get(observer);
if (methodList == null) {
// 添加方法
methodList = NetworkUtils.findAnnotationMethod(observer);
methodMap.put(observer, methodList);
}
}

/**
* 从集合中移除
*
* @param observer
*/
public void unRegisterObserver(Object observer) {
if (!methodMap.isEmpty()) {
methodMap.remove(observer);
}
}

@Override
public void registerNetworkCallback() {
// 动态注册广播
IntentFilter filter = new IntentFilter();
filter.addAction(NetworkUtils.ANDROID_NETWORK_CHANGE_ACTION);
NetworkManager.getInstance().getApplication().registerReceiver(this, filter);
}

@Override
public void unRegisterNetworkCallback() {
// 应用退出时
if (!methodMap.isEmpty()) {
methodMap.clear();
}
NetworkManager.getInstance().getApplication().unregisterReceiver(this);
}
}
  • 用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 可在application类中进行初始化
NetworkManager.getInstance().init(this);

// 应用退出时进行反注册
NetworkManager.getInstance().unRegisterNetworkCallback();

// 在需要监听网络状态的类中进行注册观察者
NetworkManager.getInstance().registerObserver(this);

// 此处采用面向切面的思路来实现,在当前类中添加带@NetworkAnnotation注解的方法(有且只能有一个)
@NetworkAnnotation(netType = NetworkType.AUTO)
public void network(NetworkType networkType) {
switch (networkType) {
case WIFI:
Log.e(Constants.LOG_TAG, "当前是WIFI网络");
Toast.makeText(this, "当前是WIFI网络", Toast.LENGTH_SHORT).show();
break;
case MOBILE:
Log.e(Constants.LOG_TAG, "当前是蜂窝移动网络" + networkType.name());
Toast.makeText(this, "当前是蜂窝移动网络", Toast.LENGTH_SHORT).show();
break;
case NONE:
Log.e(Constants.LOG_TAG, "BaseActivity >>> NET_NONE");
Toast.makeText(this, "当前无网络连接", Toast.LENGTH_SHORT).show();
break;
}
}

// 在界面关闭时或不需要监听时进行反注册观察者
NetworkManager.getInstance().unRegisterObserver(this);