欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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 安卓