一、前言
关于网络请求错误大概有两种情况:
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 查看评论