Android即时网络监听(注解实现)
程序员文章站
2022-03-11 22:57:30
在Android开发中,免不了和网络打交道,而网络监听是必不可少的,本文采用动态注册广播和注解实现即时网络监听。最终实现的效果:public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVi...
在Android开发中,免不了和网络打交道,而网络监听是必不可少的,本文采用动态注册广播和注解实现即时网络监听。
最终实现的效果:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NetworkManager.getDefault().register(this);
}
@Network
public void network(NetType type) {
switch (type) {
case AUTO:
Toast.makeText(this, "当前网络已连接", Toast.LENGTH_LONG).show();
break;
case WIFI:
Toast.makeText(this, "当前为WIFI网络", Toast.LENGTH_LONG).show();
break;
case MOBILE:
Toast.makeText(this, "当前为移动数据网络", Toast.LENGTH_LONG).show();
break;
case UNKNOWN:
Toast.makeText(this, "当前无网络连接", Toast.LENGTH_LONG).show();
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
NetworkManager.getDefault().unregister(this);
}
开始之前,先添加必要的权限。
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
1、自定义注解@Network,该注解作用于公有方法上,注解参数为枚举NetType。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Network {
NetType netType() default NetType.AUTO;
}
枚举类:
public enum NetType {
AUTO, //有网络
WIFI, //WiFi网络
MOBILE, //移动网络
UNKNOWN, //没有网络
}
2、定义一个java bean类,该类代表了Activity或者Fragment。因为只有页面才可以监听网络状态,其他类监听是无意义的。用来管理标识了@Network注解方法的信息,包括参数类型、网络类型、以及需要执行的方法。
public class MethodManager {
//参数类型
private Class<?> type;
//网络类型
private NetType mNetType;
//需要执行的方法
private Method mMethod;
public MethodManager(Class<?> type, NetType netType, Method method) {
this.type = type;
mNetType = netType;
mMethod = method;
}
public Class<?> getType() {
return type;
}
public void setType(Class<?> type) {
this.type = type;
}
public NetType getNetType() {
return mNetType;
}
public void setNetType(NetType netType) {
mNetType = netType;
}
public Method getMethod() {
return mMethod;
}
public void setMethod(Method method) {
mMethod = method;
}
}
3、定义NetworkManager唯一接口类,用于页面注册网络监听和取消监听,广播注册采用动态注册(静态注册会失效),为此需要设计成单例,供外部使用。
public class NetworkManager {
private static volatile NetworkManager instance;
private NetStateReceiver mReceiver;
private Application mApplication;
private NetworkManager() {
mReceiver = new NetStateReceiver();
}
public static NetworkManager getDefault() {
if (instance == null) {
synchronized (NetworkManager.class) {
if (instance == null) {
instance = new NetworkManager();
}
}
}
return instance;
}
public Application getApplication() {
return mApplication;
}
//初始化
public void init(Application application) {
this.mApplication = application;
}
//注册
public void register(Object register) {
IntentFilter filter = new IntentFilter();
filter.addAction(Constant.ANDROID_NET_CHANGE_ACTION);
mApplication.registerReceiver(mReceiver, filter);
mReceiver.register(register);
}
//注销
public void unregister(Object register) {
mReceiver.unregister(register);
}
}
4、定义广播接受者NetStateReceiver,用于接收网络状态改变的广播,由于用到了反射,需要java反射基础知识。在注册监听的时候,用一个HashMap来保存注册了该广播的Activity或者Fragment实例。键key为Activity或者Fragment,value为标识了@Network注解的所有公有方法。在反射执行的时候,需要判断方法参数类型有且只能有一个,并且类型为NetType枚举类型。当页面关闭或者其他不需要监听的时候,就需要将注入的实例释放和注销广播。详细代码如下:
public class NetStateReceiver extends BroadcastReceiver {
private NetType netType;
private HashMap<Object, List<MethodManager>> networkList;
public NetStateReceiver() {
netType = NetType.UNKNOWN;
networkList = new HashMap<>();
}
@Override
public void onReceive(Context context, Intent intent) {
if (intent == null || intent.getAction() == null) {
return;
}
if (intent.getAction().equalsIgnoreCase(Constant.ANDROID_NET_CHANGE_ACTION)) {
netType = NetworkUtils.getNetWorkType();
//通知分发消息
post(netType);
}
}
private void post(NetType netType) {
Set<Object> sets = networkList.keySet();
for (Object set : sets) {
List<MethodManager> methodList = networkList.get(set);
if (methodList != null) {
for (MethodManager methodManager : methodList) {
//方法参数类型校验
if (methodManager.getType().isAssignableFrom(netType.getClass())) {
switch (methodManager.getNetType()) {
case AUTO:
invoke(methodManager, set, netType);
break;
case WIFI:
if (netType == NetType.WIFI || netType == NetType.UNKNOWN) {
invoke(methodManager, set, netType);
}
break;
case MOBILE:
if (netType == NetType.MOBILE || netType == NetType.UNKNOWN) {
invoke(methodManager, set, netType);
}
break;
case UNKNOWN:
if (netType == NetType.UNKNOWN) {
invoke(methodManager, set, netType);
}
break;
}
}
}
}
}
}
private void invoke(MethodManager methodManager, Object object, NetType type) {
try {
methodManager.getMethod().invoke(object, type);
} catch (Exception e) {
e.printStackTrace();
}
}
//注册监听 == key:Activity、Fragment,value: 方法集合
public void register(Object register) {
List<MethodManager> methodList = findAnnotationMethod(register);
networkList.put(register, methodList);
}
private List<MethodManager> findAnnotationMethod(Object register) {
List<MethodManager> methodList = new ArrayList<>();
Class<?> clazz = register.getClass();
//获取当前类中所有公有方法
Method[] methods = clazz.getMethods();
for (Method method : methods) {
//获取方法上的注解
Network network = method.getAnnotation(Network.class);
if (network == null)
continue;
//方法参数校验 ==> 参数只能有一个
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length != 1) {
throw new RuntimeException(method.getName() + "parameter can only have one");
}
MethodManager methodManager = new MethodManager(parameterTypes[0], network.netType(), method);
methodList.add(methodManager);
}
return methodList;
}
public void unregister(Object register) {
if (networkList != null) {
NetworkManager.getDefault().getApplication().unregisterReceiver(this);
networkList.remove(register);
networkList.clear();
}
}
}
最后附上两个工具类:
public class Constant {
public static final String ANDROID_NET_CHANGE_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
}
public class NetworkUtils {
/**
* 判断网络是否可用
*/
public static boolean isNetworkAvailable() {
ConnectivityManager manager = (ConnectivityManager) NetworkManager.getDefault().getApplication().getSystemService(Context.CONNECTIVITY_SERVICE);
if (manager == null) {
return false;
} else {
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
if (networkInfo != null)
return networkInfo.isAvailable();
}
return false;
}
/**
* 获取网络类型
*/
public static NetType getNetWorkType() {
ConnectivityManager manager = (ConnectivityManager) NetworkManager.getDefault().getApplication().getSystemService(Context.CONNECTIVITY_SERVICE);
if (manager != null) {
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
if (networkInfo != null) {
switch (networkInfo.getType()) {
case ConnectivityManager.TYPE_MOBILE:
return NetType.MOBILE;
case ConnectivityManager.TYPE_WIFI:
return NetType.WIFI;
}
if (!networkInfo.isConnected()) {
return NetType.UNKNOWN;
}
}
}
return NetType.UNKNOWN;
}
}
至此本文结束。
本文地址:https://blog.csdn.net/qq_36700023/article/details/108723059
上一篇: 记录学习Android基础的心得00