Android进阶之路 - 实时监听网络状态

关于网络状态的监听,主要是基于Android四大组件之一中的BroadcaseReceiver(广播),如果对这方面缺少了解的话,闲下来建议 补补课 - 四大组件之BroadcaseReceiver ~

        • 门前授课
        • 基础配置
        • 静态监听
        • 动态监听
          • 基础版
          • 优化版
        • 兴趣扩展
        • 工具利器

门前授课

Android8.0之后Google基于安全原因已经声明应用无法使用其清单的大部分隐式广播(即,并非专门针对此应用的广播)

针对于此我们在本篇均使用动态注册广播,稍微科普一下,广播的两种注册方式 ~

  • 静态注册
    也就是说在AndroidManifest文件中对BroadcastReceiver进行注册,通常还会加上action用来过滤
  • 动态注册
    调用Context中的registerReceiver对广播进行动态注册,使用unRegisterReceiver方法对广播进行取消注册的操作

还有一点要提示:广播注册是一个创建的过程,那么必然也要有一个销毁的过程,从而防止内存泄露,那么销毁就在是onDestroy中unregisterReceiver广播 ~

Activity/Fragment - 注销广播

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //netWorkReceiver 之前已注册的广播
        if (netWorkReceiver != null) {
            unregisterReceiver(netWorkReceiver);
        }

基础配置

AndroidMainfests - 添加权限

 <!-- 网络状态 -->
 <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" />

MainActivity - 注册广播

package nk.com.networklinstener;

import android.annotation.SuppressLint;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    private NetworkReceiver netWorkReceiver;

    @SuppressLint("SetJavaScriptEnabled")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //注册网络状态监听广播
        netWorkReceiver = new NetworkReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(netWorkReceiver, filter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (netWorkReceiver != null) {
            unregisterReceiver(netWorkReceiver);
        }
    }
}

静态监听

此处的静态监听指的是特定时间需要获取当前的网络状态进行逻辑处理,针对的对象相对单一 ~

关于静态网络监听的话相对简单,很早之前我有写过一篇 Android进阶之路 - 监听网络状态

主要方法

提示:需加入对应权限,可前往上方Blog查看

    public static boolean isOpenNet(Context context){
        boolean bisConnFlag=false;
        ConnectivityManager conManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo network = conManager.getActiveNetworkInfo();
         if(network!=null){
             bisConnFlag=conManager.getActiveNetworkInfo().isAvailable();
             Log.e("tag","网络打开了,true");
             Toast.makeText(context,"有网状态",Toast.LENGTH_LONG).show();
             }else{
             Log.e("tag","网络打开了,false");
             Toast.makeText(context,"无网络连接状态",Toast.LENGTH_LONG).show();
         }
       return bisConnFlag;
    }

动态监听

此处的动态监听指的是全局事实监听网络状态,针对的对象非一个事件而是整个APP应用项目 ~

基础版

这里主要实时判断网络连接状态,同时判断网络类型 ~

效果
在这里插入图片描述
实现

NetworkReceiver:广播接收者

package nk.com.networklinstener;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;

/**
 * @author MrLiu
 * @date 2020/5/11
 * desc 广播接收者
 */
public class NetworkReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // 监听网络连接,包括wifi和移动数据的打开和关闭,以及连接上可用的连接都会接到监听
        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
            //获取联网状态的NetworkInfo对象
            NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
            if (info != null) {
                //如果当前的网络连接成功并且网络连接可用
                if (NetworkInfo.State.CONNECTED == info.getState() && info.isAvailable()) {
                    if (info.getType() == ConnectivityManager.TYPE_WIFI || info.getType() == ConnectivityManager.TYPE_MOBILE) {
                        Log.e("TAG", getConnectionType(info.getType()) + "已连接");
                    }
                } else {
                    Log.e("TAG", getConnectionType(info.getType()) + "已断开");
                }
            }
        }
    }

    /**
     * 获取连接类型
     * @param type
     * @return
     */
    private String getConnectionType(int type) {
        String connType = "";
        if (type == ConnectivityManager.TYPE_MOBILE) {
            connType = "3-4G网络数据";
        } else if (type == ConnectivityManager.TYPE_WIFI) {
            connType = "WIFI网络";
        }
        return connType;
    }
}
优化版

这里在判断网络连接状态的同时主要防止收到多条网络连接回调,从而导致逻辑错乱,所以采用时间校验实现类似同步锁的效果

效果
在这里插入图片描述
实现

NetworkReceiver:广播接收者

package com.nk.machine.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;

import com.nk.machine.base.MainActivity;

import java.text.SimpleDateFormat;

/**
 * @author MrLiu
 * @date 2020/5/15
 * desc 广播接收者
 */
public class NetWorkReceiver extends BroadcastReceiver {
    private static long WIFI_TIME = 0;
    private static long ETHERNET_TIME = 0;
    private static long NONE_TIME = 0;
    private static int LAST_TYPE = -3;
    private static String TAG = "TAG";

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
            long time = getTime();
            if (time != WIFI_TIME && time != ETHERNET_TIME && time != NONE_TIME) {
                final int netWorkState = getNetWorkState(context);
                if (netWorkState == 0 && LAST_TYPE != 0) {
                    WIFI_TIME = time;
                    LAST_TYPE = netWorkState;
                    Log.e(TAG, "wifi:" + time);
                } else if (netWorkState == 1 && LAST_TYPE != 1) {
                    ETHERNET_TIME = time;
                    LAST_TYPE = netWorkState;
                    Log.e(TAG, "数据网络:" + time);
                } else if (netWorkState == -1 && LAST_TYPE != -1) {
                    NONE_TIME = time;
                    LAST_TYPE = netWorkState;
                    Log.e(TAG, "无网络:" + time);
                }
            }
        }
    }

    public long getTime() {
        SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyyMMddhhmmss");
        String date = sDateFormat.format(new java.util.Date());
        return Long.valueOf(date);
    }

    private static final int NETWORK_NONE = -1; //无网络连接
    private static final int NETWORK_WIFI = 0; //wifi
    private static final int NETWORK_MOBILE = 1; //数据网络
    public static int getNetWorkState(Context context) {
        ConnectivityManager connectivityManager = (ConnectivityManager)
                context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        if (activeNetworkInfo != null && activeNetworkInfo.isConnected()) {
            if (activeNetworkInfo.getType() == (ConnectivityManager.TYPE_WIFI)) {
                return NETWORK_WIFI;
            } else if (activeNetworkInfo.getType() == (ConnectivityManager.TYPE_MOBILE)) {
                return NETWORK_MOBILE;
            }
        } else {
            return NETWORK_NONE;
        }
        return NETWORK_NONE;
    }
}

兴趣扩展

wifi连接/关闭过程 - 广播接收者

效果
Android进阶之路 - 实时监听网络状态_第1张图片
实现

package nk.com.networklinstener;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiManager;
import android.util.Log;

/**
 * @author MrLiu
 * @date 2020/5/11
 * desc wifi连接/断开过程
 */
public class NetworkReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // 监听wifi的打开与关闭,与wifi的连接无关
        if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) {
            int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);
            Log.e("TAG", "wifiState:" + wifiState);
            switch (wifiState) {
                case WifiManager.WIFI_STATE_ENABLING:
                    Log.e("TAG", "wifi状态:打开中");
                    break;
                case WifiManager.WIFI_STATE_ENABLED://主用:打开状态
                    Log.e("TAG", "wifi状态:已打开");
                    break;
                case WifiManager.WIFI_STATE_DISABLING:
                    Log.e("TAG", "wifi状态:关闭中");
                    break;
                case WifiManager.WIFI_STATE_DISABLED://主用:关闭状态
                    Log.e("TAG", "wifi状态:已关闭");
                    break;
                case WifiManager.WIFI_STATE_UNKNOWN:
                    Log.e("TAG", "wifi状态:无法识别");
                    break;
                default:
                    Log.e("TAG", "wifi状态:未知");
                    break;
            }
        }
    }
}

闲来无事正好看到了屏幕打开/关闭的的监听广播,特此记录一番

package nk.com.networklinstener;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

/**
 * @author MrLiu
 * @date 2020/5/12
 * desc 此时APP可以后台运行,广播依然有效,但是如果被杀死则无法收到广播。
 *
 */
public class ScreenReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        switch (intent.getAction()) {
            case Intent.ACTION_SCREEN_OFF:
                Log.e("屏幕广播","屏幕被关闭");
                break;
            case Intent.ACTION_SCREEN_ON:
                Log.e("屏幕广播","屏幕被打开");
                break;
        }
    }
}

工具利器

NetWorkTool:包含常用网络连接状态、移动网络/wifi的开启状态、判断网络类型(包含wifi/2G/3G/4G)

package nk.com.networklinstener;

import android.content.Context;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.os.Build;
import android.telephony.TelephonyManager;
import android.util.Log;

import java.util.List;

/**
 * @author MrLiu
 * @date 2020/5/12
 * desc 网络状态相关工具
 */
public class NetWorkTool {
    /**
     * 判断:移动网络是否开启
     */
    public static boolean isMobile(Context context) {
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
            return true;
        }
        return false;
    }

    /**
     * 判断:wifi是否开启
     */
    public static boolean isWifiEnabled(Context context) {
        ConnectivityManager mgrConn = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        TelephonyManager mgrTel = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        return ((mgrConn.getActiveNetworkInfo() != null && mgrConn.getActiveNetworkInfo().getState() == NetworkInfo.State.CONNECTED) || mgrTel.getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS);
    }

    /**
     * 判断:网络是否连接
     * 兼容新旧API(旧版API有会存在网络,新版相对准确)
     */
    public static boolean isNetworkAvailable(Context context) {
        if (context == null) {
            return false;
        }
        ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        //新版本调用方法获取网络状态
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Network[] networks = connectivity.getAllNetworks();
            NetworkInfo networkInfo;
            for (Network mNetwork : networks) {
                networkInfo = connectivity.getNetworkInfo(mNetwork);
                if (networkInfo.getState().equals(NetworkInfo.State.CONNECTED)) {
                    return true;
                }
            }
        } else {
            //否则调用旧版本方法
            if (connectivity != null) {
                NetworkInfo[] info = connectivity.getAllNetworkInfo();
                if (info != null) {
                    for (NetworkInfo anInfo : info) {
                        if (anInfo.getState() == NetworkInfo.State.CONNECTED) {
                            Log.d("Network", "NETWORKNAME: " + anInfo.getTypeName());
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    /**
     * 判断:当前网络状态是否连接
     */
    public static boolean isConnected(Context context) {
        try {
            ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            if (connectivity != null) {
                NetworkInfo info = connectivity.getActiveNetworkInfo();
                if (info != null && info.isConnected()) {
                    if (info.getState() == NetworkInfo.State.CONNECTED) {
                        return true;
                    }
                }
            }
        } catch (Exception e) {
            return false;
        }
        return false;
    }

    /**
     * 获取当前的网络状态:WIFI/2G/3G/4G
     */
    public static String GetNetworkType() {
        String strNetworkType = "";
        //获取系统的连接服务
        ConnectivityManager connectivityManager = (ConnectivityManager) MyApplication.getApp().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
//        NetworkInfo networkInfo = (ConnectivityManager)MyApplication.getApp().getSystemService(Context.CONNECTIVITY_SERVICE).getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) {
            if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
                strNetworkType = "WIFI";
            } else if (networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
                String _strSubTypeName = networkInfo.getSubtypeName();
                Log.e("cocos2d-x", "Network getSubtypeName : " + _strSubTypeName);
                // TD-SCDMA   networkType is 17
                int networkType = networkInfo.getSubtype();
                switch (networkType) {
                    case TelephonyManager.NETWORK_TYPE_GPRS:
                    case TelephonyManager.NETWORK_TYPE_EDGE:
                    case TelephonyManager.NETWORK_TYPE_CDMA:
                    case TelephonyManager.NETWORK_TYPE_1xRTT:
                    case TelephonyManager.NETWORK_TYPE_IDEN: //api<8 : replace by 11
                        strNetworkType = "2G";
                        break;
                    case TelephonyManager.NETWORK_TYPE_UMTS:
                    case TelephonyManager.NETWORK_TYPE_EVDO_0:
                    case TelephonyManager.NETWORK_TYPE_EVDO_A:
                    case TelephonyManager.NETWORK_TYPE_HSDPA:
                    case TelephonyManager.NETWORK_TYPE_HSUPA:
                    case TelephonyManager.NETWORK_TYPE_HSPA:
                    case TelephonyManager.NETWORK_TYPE_EVDO_B: //api<9 : replace by 14
                    case TelephonyManager.NETWORK_TYPE_EHRPD:  //api<11 : replace by 12
                    case TelephonyManager.NETWORK_TYPE_HSPAP:  //api<13 : replace by 15
                        strNetworkType = "3G";
                        break;
                    case TelephonyManager.NETWORK_TYPE_LTE:    //api<11 : replace by 13
                        strNetworkType = "4G";
                        break;
                    default:
                        // http://baike.baidu.com/item/TD-SCDMA 中国移动 联通 电信 三种3G制式
                        if (_strSubTypeName.equalsIgnoreCase("TD-SCDMA") || _strSubTypeName.equalsIgnoreCase("WCDMA") || _strSubTypeName.equalsIgnoreCase("CDMA2000")) {
                            strNetworkType = "3G";
                        } else {
                            strNetworkType = _strSubTypeName;
                        }
                        break;
                }
                Log.e("cocos2d-x", "Network getSubtype : " + Integer.valueOf(networkType).toString());
            }
        }
        Log.e("cocos2d-x", "Network Type : " + strNetworkType);
        return strNetworkType;
    }

你可能感兴趣的:(Android进阶之路,#,项目开发知识点归纳)