在Android开发中,许多功能需要网络连接,所以在开发过程中需要进行手机网络的检测。而每做一个App,就要进行检测,那么我直接将检测网络状态的功能封装成一个类。

检测网络状态所需要的Api:

  • ConnectivityManager主要用于查看网络状态和管理网络连接相关的操作
  • NetworkInfo对象包含网络连接的所有信息

实现网络状态检测功能,首先获得ConnectivityManager对象,再获取ConnectivityManager对象对应的NetworkInfo对象,并根据需要从NetworkInfo对象取出关于网络连接的信息,进行后续处理。

注意:Api23及以上时,getNetworkInfo(int networkType)方法已被弃用,取而代之的是:

getAllNetworks();
getNetworkInfo(android.net.Network);
getNetworkInfo(Network network);

所以我们检测网络状态时需要分版本进行检测。

我们使用Android的四大组件之一的BroadcastReceiver(广播接收者)进行接收网络变化的后续处理。

上代码。

实现监听网络状态变更的广播接收器——NetBroadcastReceiver.java

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;import com.maigu.yang.networkinit.bean.NetworkChangeEvent;
import com.maigu.yang.networkinit.utils.NetUtils;import org.greenrobot.eventbus.EventBus;public class NetBroadcastReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {//**判断当前的网络连接状态是否可用*/boolean isConnected = NetUtils.isConnected(context);EventBus.getDefault().post(new NetworkChangeEvent(isConnected));}
}

我们使用广播接收器接收网络变化的 Intent,这里直接使用静态注册的方法,因为我们不需要在每个页面单独注册这个 Receiver,那太重量级了。
在AndroidManifest.xml进行广播的静态注册,以及网络权限

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"package="com.maigu.yang.networkinit"><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" /><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"tools:ignore="AllowBackup,GoogleAppIndexingWarning"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><receiverandroid:name=".broadcast.NetBroadcastReceiver"android:enabled="true"android:exported="true"><intent-filter><actionandroid:name="android.net.conn.CONNECTIVITY_CHANGE"tools:ignore="BatteryLife" /><category android:name="android.intent.category.DEFAULT" /></intent-filter></receiver></application></manifest>

然后是监听网络状态的NetUtils.java工具类

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.util.Log;
import android.widget.Toast;/*** 作者    yunyang* 时间    2018/11/7 13:14* 文件    NetWorkInit* 描述   网络工具类*/
public class NetUtils {/*** 判断网络是否连接** @param context* @return 网络是否连接Boolean(true|false)*/@SuppressWarnings({"ConstantConditions", "ForLoopReplaceableByForEach", "IfCanBeSwitch"})public static boolean isConnected(Context context) {StringBuilder sb = null;//检测API是不是小于21,因为到了API21之后getNetworkInfo(int networkType)方法被弃用/***  在系统版本小于21之前,使用以下的方式获取当前网络状态:* 先利用Context对象获取ConnectivityManager对象,* 然后利用ConnectivityManager对象获取NetworkInfo对象,* 然后根据NetworkInfo对象的类型来返回不同的网络状态。* 有三种,移动,Wi-Fi,无网络连接。*/if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {//获得ConnectivityManager对象ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);//获取ConnectivityManager对象对应的NetworkInfo对象//获取WIFI连接的信息NetworkInfo wifiNetworkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);//获取移动数据连接的信息NetworkInfo dataNetworkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);if (wifiNetworkInfo.isConnected() && dataNetworkInfo.isConnected()) {Toast.makeText(context, "WIFI已连接,移动数据已连接", Toast.LENGTH_SHORT).show();Log.e("yunyang", "WIFI已连接,移动数据已连接");return true;} else if (wifiNetworkInfo.isConnected() && !dataNetworkInfo.isConnected()) {Toast.makeText(context, "WIFI已连接,移动数据已断开", Toast.LENGTH_SHORT).show();Log.e("yunyang", "WIFI已连接,移动数据已断开");return true;} else if (!wifiNetworkInfo.isConnected() && dataNetworkInfo.isConnected()) {Toast.makeText(context, "WIFI已断开,移动数据已连接", Toast.LENGTH_SHORT).show();Log.e("yunyang", "WIFI已断开,移动数据已连接");return true;} else {Toast.makeText(context, "WIFI已断开,移动数据已断开", Toast.LENGTH_SHORT).show();Log.e("yunyang", "WIFI已断开,移动数据已断开");return false;}} else {/***  在系统21及之后,获取网络连接状态的方式:利用ConnectivityManager对象获取* 所有的网络连接信息,然后遍历每个网络连接,获取相应的NetworkInfo,* 然后根据NetworkInfo对象的类型来返回不同的网络状态。*/if (sb != null) {sb.setLength(0);}//获得ConnectivityManager对象ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);//获取所有网络连接的信息Network[] networks = connMgr.getAllNetworks();//用于存放网络连接信息sb = new StringBuilder();//通过循环将网络信息逐个取出来for (int i = 0; i < networks.length; i++) {//获取ConnectivityManager对象对应的NetworkInfo对象NetworkInfo networkInfo = connMgr.getNetworkInfo(networks[i]);sb.append(networkInfo.getTypeName() + " connect is " + networkInfo.isConnected());}Log.e("yunyang", "sb.toString() : " + sb.toString());if (sb.toString().equals("WIFI connect is true")) {Toast.makeText(context, "WIFI已连接", Toast.LENGTH_SHORT).show();Log.e("yunyang", "WIFI已连接");return true;} else if (sb.toString().equals("MOBILE connect is true")) {Toast.makeText(context, "移动数据已连接", Toast.LENGTH_SHORT).show();Log.e("yunyang", "移动数据已连接");return true;} else if (sb.toString().equals("MOBILE connect is trueWIFI connect is true")|| sb.toString().equals("WIFI connect is trueMOBILE connect is true")) {Toast.makeText(context, "WIFI已连接,移动数据已连接", Toast.LENGTH_SHORT).show();Log.e("yunyang", "WIFI已连接,移动数据已连接");return true;} else if (sb.toString().equals("MOBILE connect is falseWIFI connect is true")|| sb.toString().equals("WIFI connect is trueMOBILE connect is false")) {Toast.makeText(context, "WIFI已连接,移动数据已断开", Toast.LENGTH_SHORT).show();Log.e("yunyang", "WIFI已连接,移动数据已断开");return true;} else if (sb.toString().equals("MOBILE connect is trueWIFI connect is false")|| sb.toString().equals("WIFI connect is falseMOBILE connect is true")) {Toast.makeText(context, "WIFI已断开,移动数据已连接", Toast.LENGTH_SHORT).show();Log.e("yunyang", "WIFI已断开,移动数据已连接");return true;} else {Toast.makeText(context, "WIFI已断开,移动数据已断开", Toast.LENGTH_SHORT).show();Log.e("yunyang", "WIFI已断开,移动数据已断开");return false;}}}}

我们希望当用户网络连接不可用时,及时提醒用户当前的网络状态。当连接恢复时,将提示用的视图隐藏,并且我们希望这个提示视图可以工作在所有需要网络的页面中。

所以我创建一个基类 BaseActivity ,所有页面继承该文件,在该文件中实现根据网络状态显示提示、隐藏提示。

import android.content.Context;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;import com.maigu.yang.networkinit.R;
import com.maigu.yang.networkinit.bean.NetworkChangeEvent;
import com.maigu.yang.networkinit.utils.ActivityCollector;
import com.maigu.yang.networkinit.utils.NetUtils;import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;/*** 作者    yunyang* 时间    2018/11/7 13:18* 文件    NetWorkInit* 描述   BaseActivity*/
public class BaseActivity extends AppCompatActivity {protected Context mContext;protected boolean mCheckNetWork = true; //默认检查网络状态View mTipView;WindowManager mWindowManager;WindowManager.LayoutParams mLayoutParams;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mContext = this;ActivityCollector.addActivity(this);// 将正在创建的活动添加到活动管理器里initTipView();//初始化提示ViewEventBus.getDefault().register(this);}@Overrideprotected void onResume() {super.onResume();//在无网络情况下打开APP时,系统不会发送网络状况变更的Intent,需要自己手动检查hasNetWork(NetUtils.isConnected(mContext));}@Overrideprotected void onPause() {super.onPause();}@Overrideprotected void onDestroy() {super.onDestroy();ActivityCollector.removeActivity(this);// 将活动管理器里活动移除EventBus.getDefault().unregister(this);}@Overridepublic void finish() {super.finish();//当提示View被动态添加后直接关闭页面会导致该View内存溢出,所以需要在finish时移除if (mTipView != null && mTipView.getParent() != null) {mWindowManager.removeView(mTipView);}}@Subscribe(threadMode = ThreadMode.MAIN)public void onNetworkChangeEvent(NetworkChangeEvent event) {hasNetWork(event.isConnected);}private void hasNetWork(boolean has) {if (isCheckNetWork()) {if (has) {if (mTipView != null && mTipView.getParent() != null) {mWindowManager.removeView(mTipView);Log.e("yunyang", "有网络");}} else {if (mTipView.getParent() == null) {mWindowManager.addView(mTipView, mLayoutParams);Log.e("yunyang", "无网络");}}}}/*** 默认所有继承 BaseActivity 的页面当网络状况变化活无网络时都会显示提示,* 如果某个页面不需要网络状态提示,可以在该页面 onCreate* 方法中调用 setCheckNetWork(false) 即可。** @param checkNetWork*/public void setCheckNetWork(boolean checkNetWork) {mCheckNetWork = checkNetWork;}public boolean isCheckNetWork() {return mCheckNetWork;}private void initTipView() {LayoutInflater inflater = getLayoutInflater();mTipView = inflater.inflate(R.layout.layout_network_tip, null); //提示View布局mWindowManager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);mLayoutParams = new WindowManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.TYPE_APPLICATION,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,PixelFormat.TRANSLUCENT);//使用非CENTER时,可以通过设置XY的值来改变View的位置mLayoutParams.gravity = Gravity.TOP;mLayoutParams.x = 0;mLayoutParams.y = 180;
//        mLayoutParams.gravity = Gravity.CENTER;}
}

BaseActivity中使用网络状态提示视图的布局layout_network_tip.java

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="wrap_content"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:text="网络连接不可用,请检查网络设置"android:textColor="@color/colorAccent"android:textSize="18sp"tools:ignore="HardcodedText" /></RelativeLayout>

而且我们的广播是静态注册,并在广播接收者里面使用EventBus三方库。传递信息。那么EventBus是什么呢?

EventBus是Android和Java的发布/订阅事件总线。
简化了组件之间的通信
将事件发送者和接收者分离
在活动,片段和后台线程中表现良好
避免复杂且容易出错的依赖关系和生命周期问题
使您的代码更简单
很快
很小(约50k罐)
已经通过100,000,000+安装的应用程序在实践中得到证实
具有交付线程,用户优先级等高级功能。

关于EventBus的使用,如上EventBus的超链接跳转到Github进行学习。

// EventBusimplementation 'org.greenrobot:eventbus:3.1.1'

这里我简单说一下EventBus的简单使用。

  1. 定义事件
    NetworkChangeEvent.java
/*** 作者    yunyang* 时间    2018/11/7 13:16* 文件    NetWorkInit* 描述   EventBus——事件Event*/
public class NetworkChangeEvent {public boolean isConnected; //是否存在网络public NetworkChangeEvent(boolean isConnected) {this.isConnected = isConnected;}
}
  1. 准备订阅者
@Subscribe(threadMode = ThreadMode.MAIN)public void onNetworkChangeEvent(NetworkChangeEvent event) {hasNetWork(event.isConnected);}
  1. 注册和注销您的订阅者
    注册: EventBus.getDefault().register(this);
    注销:EventBus.getDefault().unregister(this);
  2. 发布活动
    EventBus.getDefault().post(new NetworkChangeEvent(isConnected));

BaseActivity中还有一个ActivityCollector,活动管理器类。
ActivityCollector.java

import android.app.Activity;import java.util.ArrayList;
import java.util.List;/*** 作者    yunyang* 时间    2018/11/7 13:31* 文件    NetWorkInit* 描述   在活动管理器中,通过一个List来暂存活动。*/
public class ActivityCollector {public static List<Activity> activities = new ArrayList<Activity>();/*** 用于向List中添加一个活动。** @param activity*/public static void addActivity(Activity activity) {activities.add(activity);}/*** 用于从List中移除活动。** @param activity*/public static void removeActivity(Activity activity) {activities.remove(activity);}/*** 用于将List中存储的活动全部都销毁掉。*/public static void finishAll() {for (Activity activity : activities) {if (!activity.isFinishing())activity.finish();}}}

使用动态广播注册方式
修改MainActivity中的代码

import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.Bundle;import com.maigu.yang.networkinit.base.BaseActivity;
import com.maigu.yang.networkinit.broadcast.NetBroadcastReceiver;public class MainActivity extends BaseActivity {NetBroadcastReceiver mNetBroadcastReceiver;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}//在onResume()方法注册@Overrideprotected void onResume() {if (mNetBroadcastReceiver == null) {mNetBroadcastReceiver = new NetBroadcastReceiver();}IntentFilter filter = new IntentFilter();filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);registerReceiver(mNetBroadcastReceiver, filter);System.out.println("注册");super.onResume();}//onPause()方法注销@Overrideprotected void onPause() {unregisterReceiver(mNetBroadcastReceiver);System.out.println("注销");super.onPause();}}

还有AndroidManifest.xml文件中的代码

  <receiverandroid:name=".broadcast.NetBroadcastReceiver"android:enabled="true"android:exported="true"><!--<intent-filter>--><!--<action--><!--android:name="android.net.conn.CONNECTIVITY_CHANGE"--><!--tools:ignore="BatteryLife" />--><!--<category android:name="android.intent.category.DEFAULT" />--><!--</intent-filter>--></receiver>

那么是使用静态广播还是动态注册广播的方式好呢?
我们的应用要监听网络状态的变化,主要是为了在网络错误的情况下方便进行处理,退出我们当前的应用之后当然不需要监听了,所以这里选择动态注册广播更好一点。

动态注册:随着所在的Activity或者应用销毁 以后,不会受到该广播
静态注册:退出应用后,仍然能够收到相应的广播
共同点:都需要在AndroidManifest.xml清单文件里面注册。

最后测试结果。
因为我们的监听网络状态的Api发生了改变,所以我们先使用4.4的模拟器进行测试,然后在使用6.0的模拟器进行测试。
4.4模拟器演示效果


6.0模拟器演示效果

源码下载

Android移动开发检测网络状态并使用BroadcastReceiver(广播接收者)进行接收网络变化的后续处理相关推荐

  1. 仿手机QQ网络状态条的显示与消失,没网络时显示,有网络时自动消失 ,点击网络条设置网络

    关注finddreams,一起分享,一起进步: http://blog.csdn.net/finddreams/article/details/44647843 我们都知道手机QQ上有这样一个功能,就 ...

  2. 网络状态是一条横线 连接不上网络的解决办法

    1. 问题描述 在一次重置了win10操作系统之后,网络状态 为一条横虚线,不能连接网络. 2.解法方法 win+R 运行 services.msc 启动 window Event log 如果报错, ...

  3. html5中检测网络状态的方法,前端js监听浏览器网络变化

    首先,为什么要让前端判断用户的网络状态呢--为了更好的用户体验. 其次,前端能否判断网络状态?有哪些方法? 1,可以做到渐进式判断,不能做到绝对准确. 2,使用的是navigator.onLine或n ...

  4. android 广播的权限,Android四大组件详解之BroadcastReceiver广播接收者

    Android四大组件详解---BroadcastReceicer广播接收者 广播有两个角色,一个是广播发送者,另一个是广播接收者. 广播按照类型分为两种,一种是全局广播,另一种是本地广播 全局广播: ...

  5. 【Android 应用开发】Activity 状态保存 OnSaveInstanceState参数解析

    作者 : 韩曙亮 转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/38297083 一. 相关方法简介 1. 状态保存方法示例 p ...

  6. 【Android 应用开发】Activity 状态保存 OnSaveInstanceState參数解析

    作者 : 韩曙亮 转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/38297083 一. 相关方法简单介绍 1. 状态保存方法演示 ...

  7. 无网络状态下修改计算机ip,电脑突然没有网络的到底是什么原因,查看ip地址...

    电脑路由器的几种操作方法,上网设置.无线桥接.行为管理那么这些设置都是建立在已经进入"路由管理"界面的基础上,才能进行设置生活中接触过很多网络问题,也接触过很多各种"不同 ...

  8. Android通过使用系统广播监听网络状态的改变

    Android通过使用广播监听网络状态的改变 得先添加权限 //查看网络状态<uses-permission android:name="android.permission.ACCE ...

  9. 怎么用nodejs检测网络状态?

    nodejs可以使用检测因特网状态的库internet-available.is-online来检查网络状态,其原理是检测dns连接状态.这两个库提供了超时检测. 用nodejs检测网络状态: int ...

最新文章

  1. 《Unity开发实战》——2.2节创建画中画效果
  2. 程序员必知的20个Python技巧
  3. 【论文解读】MV3D-Net、AVOD-Ne用于自动驾驶的多视图3D目标检测网络
  4. linux 系统基础知识 - fdisk命令
  5. Codeforces Round #470 (rated, Div. 2 C. Producing Snow(思维)
  6. pelco-d协议数据解析示例
  7. spring beans源码解读之--Bean的注解(annotation)
  8. 实例化bean的三种方式
  9. Rxjs 里 Subject 和 BehaviorSubject 的区别
  10. python简单开发接口
  11. vue自定义组件,插槽,自定义事件
  12. 我学习的第一个uiautomator从创建到运行结束
  13. ~~朴素dijkstra算法
  14. ip=request.servervariables(Remote_Addr)获得ip显示::1
  15. JPA用TABLE生成主键
  16. 正交多项式-勒让德多项式,两类切比雪夫多项式及零点,拉盖尔多项式,埃尔米特多项式
  17. 人脸识别活体检测之眨眨眼和张张嘴
  18. vue导出服务器上的excel文件,详解如何在Vue项目中导出Excel
  19. 智能硬件不止树莓派,八款优秀智能硬件开源项目推荐
  20. 解决win10笔记本电脑无法睡眠只是黑屏问题的方法

热门文章

  1. 树莓派教程-串口调试
  2. 跟Gregg学习系统性能--[7.4.5]内存性能指标监测内容
  3. Vue登录第2.1版
  4. BZOJ 4296 PA2015 Mistrzostwa
  5. matlab模糊控制图怎么导出_用MATLAB生成模糊控制离线查询表
  6. L1-028 判断素数(C语言版)
  7. 表单标签的作用、常用的表单控件
  8. 计算机科学导论作业大纲,《计算机科学导论》课程复习大纲与综合练习题.doc...
  9. burpsuite入门,实用教程
  10. SpringBoot 入门小程序