Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

Android 网络状态监听那些事

$
0
0
一、前言
关于网络请求错误大概有两种情况:
1)当前没有网络。
2)有网络,客户端错误或者服务器错误。
今天我们就来讨论第一种:当前没有网络这种错误。网络可以分为移动数据网络和wifi。至于这些网络状态的变化,我们有必要去正真的研究一下。

二、实现的思路
经过认真查找网上资料,大概有三种思路:
1)启动Service服务并开启一条线程,线程一直检测当前网络状态,并通过广播方式发送这些状态信息。
2)只有与服务器交互时(比如:加载,上传等),才检测当前网络状态是否有连接。这种方法优点就是不用实时监听网络状态,不足的是每一个请求方法都要写判断,代码量变大。有人会说写成一个封装类,这样虽然减少代码编写,但是也都需要我们主动去获取,也会麻烦。
3)对于上面这种情况,谷歌已经帮我们封装好,只需要我们接收广播做进一步监听即可。
在这里我会实现以上第二和第三两种思路!

1、第一种:请求时,做网络判断
网络类型主要有两种:第一种,wifi;第二种,移动数据网络。
下面通过一些代码来获得当前网络状态以及网络信息。
判断当前网络状态是否有连接。
/**
 * 判断是否有网络连接
 * @param context
 * @return
    */
public static boolean isNetworkConnected(Context context) {
   if (context != null) {
      ConnectivityManager mConnectivityManager = (ConnectivityManager) context
            .getSystemService(Context.CONNECTIVITY_SERVICE);
      NetworkInfo mNetworkInfo = mConnectivityManager
            .getActiveNetworkInfo();
      if (mNetworkInfo != null) {
         return mNetworkInfo.isAvailable();
      }
   }
   return false;
}
判断当前是否是wifi网络。
/**
 * 判断当前网络是否是wifi网络
 *
 * @param context
 * @return boolean
 */
public static boolean isWifi(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context
            .getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
    if (activeNetInfo != null
            && activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI) {
        return true;
    }
    return false;
}
判断当前是否是移动数据网络。
/**
 * 判断当前网络是否是移动网络
 *
 * @param context
 * @return boolean
 */
public static boolean isMoble(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context
            .getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
    if (activeNetInfo != null
            && activeNetInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
        return true;
    }
    return false;
}
获取当前网络状态。
/**
 * 获取当前的网络状态 :没有网络-0:WIFI网络1:4G网络-4:3G网络-3:2G网络-2
 * 自定义
 *
 * @param context
 * @return
 */
public static int getAPNType(Context context) {
    //结果返回值
    int netType = 0;
    //获取手机所有连接管理对象
    ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context
            .CONNECTIVITY_SERVICE);
    //获取NetworkInfo对象
    NetworkInfo networkInfo = manager.getActiveNetworkInfo();
    //NetworkInfo对象为空 则代表没有网络
    if (networkInfo == null) {
        return netType;
    }
    //否则 NetworkInfo对象不为空 则获取该networkInfo的类型
    int nType = networkInfo.getType();
    if (nType == ConnectivityManager.TYPE_WIFI) {
        //WIFI
        netType = 1;
    } else if (nType == ConnectivityManager.TYPE_MOBILE) {
        int nSubType = networkInfo.getSubtype();
        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService
                (Context.TELEPHONY_SERVICE);
        //3G   联通的3G为UMTS或HSDPA 电信的3G为EVDO
        if (nSubType == TelephonyManager.NETWORK_TYPE_LTE
                && !telephonyManager.isNetworkRoaming()) {
            netType = 4;
        } else if (nSubType == TelephonyManager.NETWORK_TYPE_UMTS
                || nSubType == TelephonyManager.NETWORK_TYPE_HSDPA
                || nSubType == TelephonyManager.NETWORK_TYPE_EVDO_0
                && !telephonyManager.isNetworkRoaming()) {
            netType = 3;
            //2G 移动和联通的2G为GPRS或EGDE,电信的2G为CDMA
        } else if (nSubType == TelephonyManager.NETWORK_TYPE_GPRS
                || nSubType == TelephonyManager.NETWORK_TYPE_EDGE
                || nSubType == TelephonyManager.NETWORK_TYPE_CDMA
                && !telephonyManager.isNetworkRoaming()) {
            netType = 2;
        } else {
            netType = 2;
        }
    }
    return netType;
}
获取当前网络信息。
/**
 * 获取网络连接的类型信息
 * @param context
 * @return
    */
public static String getNetInfo(Context context) {
   ConnectivityManager mConnectivityManager = (ConnectivityManager) context
         .getSystemService(Context.CONNECTIVITY_SERVICE);
   NetworkInfo wifi = mConnectivityManager
         .getNetworkInfo(ConnectivityManager.TYPE_WIFI);
   NetworkInfo mobile = mConnectivityManager
         .getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
   StringBuffer sb = new StringBuffer();
   if (wifi != null && wifi.isAvailable()) {
      sb.append("WIFI");
   }
   if (mobile != null && mobile.isAvailable()) {
      sb.append(mobile.getSubtypeName() + ",");
      sb.append(getMobileInfo(mobile.getSubtype()));
   }

   return sb.toString();
}

/**
 * 移动网络信息
 *
 * @param type
 * @return
 */
public static String getMobileInfo(int type) {
   String netInfo = null;
   switch (type) {
   case 0:
      netInfo = "未知";
      break;
   case 1:
      netInfo = "联通2G";
      break;
   case 2:
      netInfo = "移动2G";
      break;
   case 3:
      netInfo = "联通3G";
      break;
   case 4:
      netInfo = "电信2G";
      break;
   case 5:
      netInfo = "电信3G";
      break;
   case 6:
      netInfo = "电信3G";
      break;
   case 7:
      netInfo = "1xRTT";
      break;
   case 8:
      netInfo = "联通3G";
      break;
   case 9:
      netInfo = "HSUPA";
      break;
   case 10:
      netInfo = "HSPA";
      break;
   case 11:
      netInfo = "IDEN";
      break;
   case 12:
      netInfo = "电信3G";
      break;
   case 13:
      netInfo = "4G";
      break;
   case 14:
      netInfo = "eHRPD";
      break;
   case 15:
      netInfo = "HSPAP";
      break;

   default:
      break;
   }

   return netInfo;
}
以上封装方法可以在网络请求是做判断,并且可以得出当前网络信息。

2、第二种:自定义广播监听网络状态
说到自定义广播,首先要知道广播的注册方式。注册方式有:动态注册、静态注册。
静态注册:
AndroidMainest文件中配置:
<receiver android:name=".receiver.NetWorkReceiver">
    <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE"></action>
        <action android:name="android.net.wifi.WIFI_STATE_CHANGED"></action>
        <action android:name="android.net.wifi.STATE_CHANGE"></action>
    </intent-filter>
</receiver>
动态注册:
在Application中的oncreate()方法中调用一下方法,做动态注册。
/**
 * 网络状态广播注册
 * @author hjy
 * created at 2016/12/12 15:30
 */
private void netWorkReceiver()
{
    IntentFilter filter = new IntentFilter();
    filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
    filter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
    filter.addAction("android.net.wifi.STATE_CHANGE");
    mNetWorkReceiver = new NetWorkReceiver(netWorkHandler);
    registerReceiver(mNetWorkReceiver,filter);
}
注册好了,接下来就来看一下自定义广播中是怎么去接收的呢?贴上代码.....
/**
 * 网络状态监听广播
 * @author hjy
 * created at 2016/12/12 15:20
 */
public class NetWorkReceiver extends BroadcastReceiver {

    private static final String TAG = "test";
    private Handler mHandler;

    public NetWorkReceiver() {}

    public NetWorkReceiver(Handler mHandler) {
        this.mHandler = mHandler;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        //wifi开关监听
        isOpenWifi(intent, mHandler);
        //是否连接wifi
        isConnectionWifi(intent, mHandler);
        //监听网络连接设置
        isConnection(intent, mHandler, context);
    }

    /**
     * 监听wifi打开与关闭
     * (与连接与否无关)
     * @author hjy
     * created at 2016/12/12 17:33
     */
    private void isOpenWifi(Intent intent, Handler mHandler)
    {
        // 这个监听wifi的打开与关闭,与wifi的连接无关
        if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) {
            int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);
            switch (wifiState) {
                //Wifi关闭
                case WifiManager.WIFI_STATE_DISABLED:
                    LogUtil.e(TAG, "wifiState:wifi关闭!" );
                    break;
                case WifiManager.WIFI_STATE_DISABLING:
                    break;
                case WifiManager.WIFI_STATE_ENABLING:
                    break;
                case WifiManager.WIFI_STATE_ENABLED:
                    LogUtil.e(TAG, "wifiState:wifi打开!" );
                    break;
                case WifiManager.WIFI_STATE_UNKNOWN:
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * 连接有用的wifi(有效无线路由)
     * WifiManager.WIFI_STATE_DISABLING与WIFI_STATE_DISABLED的时候,根本不会接到这个广播
     * @author hjy
     * created at 2016/12/13 9:47
     */
    private void isConnectionWifi(Intent intent, Handler mHandler)
    {
        if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(intent.getAction())) {
            Parcelable parcelableExtra = intent
                    .getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
            if (null != parcelableExtra) {
                NetworkInfo networkInfo = (NetworkInfo) parcelableExtra;
                NetworkInfo.State state = networkInfo.getState();
                boolean isConnected = state == NetworkInfo.State.CONNECTED;
                //wifi连接
                if (isConnected) {
                    mHandler.sendEmptyMessage(ConstantsUtil.NetWork.IS_WIFI);
                    LogUtil.e(TAG, "isConnected:isWifi:true");
                }
            }
        }
    }

    /**
     * 监听网络连接的设置,包括wifi和移动数据的打开和关闭。(推荐)
     * 这个广播的最大弊端是比上边两个广播的反应要慢,如果只是要监听wifi,我觉得还是用上边两个配合比较合适
     * @author hjy
     * created at 2016/12/13 9:47
     */
    private void isConnection(Intent intent, Handler mHandler, Context context)
    {
        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
            ConnectivityManager manager = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);

            NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
            if (activeNetwork != null) {
                // connected to the internet
                if (activeNetwork.isConnected()) {
                    if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
                        // connected to wifi
                        mHandler.sendEmptyMessage(ConstantsUtil.NetWork.IS_WIFI);
                        LogUtil.e(TAG, "当前WiFi连接可用 ");
                    } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
                        // connected to the mobile provider's data plan
                        mHandler.sendEmptyMessage(ConstantsUtil.NetWork.IS_MOBILE);
                        LogUtil.e(TAG, "当前移动网络连接可用 ");
                    }
                } else {
                    LogUtil.e(TAG, "当前没有网络连接,请确保你已经 打开网络 ");
                    mHandler.sendEmptyMessage(ConstantsUtil.NetWork.NO_CONNECTION);
                }
                LogUtil.e(TAG, "TypeName:" + activeNetwork.getTypeName());
                LogUtil.e(TAG, "SubtypeName:" + activeNetwork.getSubtypeName());
                LogUtil.e(TAG, "State:" + activeNetwork.getState());
                LogUtil.e(TAG, "DetailedState:"
                        + activeNetwork.getDetailedState().name());
                LogUtil.e(TAG, "ExtraInfo:" + activeNetwork.getExtraInfo());
                LogUtil.e(TAG, "Type:" + activeNetwork.getType());

            } else {   // not connected to the internet
                LogUtil.e(TAG, "当前没有网络连接,请确保你已经打开网络 ");
                mHandler.sendEmptyMessage(ConstantsUtil.NetWork.NO_CONNECTION);
            }
        }
    }
}
辅助类:
/**
 * 常量工具类
 * Created by hjy on 2016/9/26.
 */
public class ConstantsUtil {
    /**
     * 网络监听
     * @author hjy
     * created at 2016/11/25 12:03
     */
    public class NetWork
    {
        //移动:Moblie
        public static final String MOBLIE = "Moblie";
        // Wifi:Wifi
        public static final String WIFI = "Wifi";
        //当前是wifi状态
        public static final int IS_WIFI = 0x001;
        //当前是Mobile状态
        public static final int IS_MOBILE = 0x002;
        //都没有连接
        public static final int NO_CONNECTION = 0x003;
        //关闭wifi
        //public static final int OPEN_WIFI = 0x004;
        //打开wifi
        //public static final int CLOSE_WIFI = 0x005;
    }
}
在Application中调用:
/**
 * Created by hjy on 2016/9/26.
 */
public class BaseApplication extends Application {
    //网络监听广播
    private NetWorkReceiver mNetWorkReceiver;
    //表示是否连接
    public static boolean isConnected;
    //表示网络类型(移动数据或者wifi)移动:Moblie Wifi:Wifi
    public static String netWorkState;

    @Override
    public void onCreate() {
        super.onCreate();
        /*****网络状态监听********/
        netWorkReceiver();
    }

    /**
     * 获取上下文
     * @author hjy
     * created at 2016/9/26 9:03
     */
    public static Context getContext()
    {
        return mContext;
    }

    /**
     * 网络状态广播注册
     * @author hjy
     * created at 2016/12/12 15:30
     */
    private void netWorkReceiver()
    {
        IntentFilter filter = new IntentFilter();
        filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        filter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
        filter.addAction("android.net.wifi.STATE_CHANGE");
        mNetWorkReceiver = new NetWorkReceiver(netWorkHandler);
        registerReceiver(mNetWorkReceiver,filter);
    }

    //网络监听Handler
    private Handler netWorkHandler = new Handler()
    {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what)
            {
                case ConstantsUtil.NetWork.IS_WIFI:
                    netWorkState = ConstantsUtil.NetWork.WIFI;
                    isConnected = true;
                    break;
                case ConstantsUtil.NetWork.IS_MOBILE:
                    netWorkState = ConstantsUtil.NetWork.MOBLIE;
                    isConnected = true;
                    break;
                case ConstantsUtil.NetWork.NO_CONNECTION:
                    isConnected = false;
                    break;
            }
        }
    };
}
实现思路大概是这样:在NetWorkReceiver广播中监测到当前网络状态,通过Handler发送消息给Application,然后在BaseApplication中定义静态isConnected静态netWorkState字段来保存网络状态。isConnected代表网络是否连接。netWorkState代表网络连接时,当前连接的是Wifi还是移动数据网络。网络状态保存在这两个字段中,方便供其他页面调用。如果想添加更多状态,请自行添加!

好了!网络状态监听大概就讲到这边!如果有出错或者需要改进的地方,欢迎指点或者交流。
作者:qq_21126979 发表于2016/12/13 16:58:22 原文链接
阅读:24 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>