0. 前言

在Android开发中监听手机的网络状态是一个常见的功能,比如在没网的状态下进行提醒并引导用户打开网络设置,或者在非wifi状态下开启无图模式等等。因此本篇将网上的资料进行了整理总结,方便大家用到的时候可以快速地获取到手机的网络状态,节省时间。

1.  主动获取

之所以叫主动获取,是获取网络状态的时机是我们来定的,因此主动获取的代码位置比较灵活,可以是加载网络数据前,也可以在刚开启APP时,若没网则引导用户打开网络设置。下面是主动获取的工具类代码。主要还是调用了ConnectivityManager的系统服务。获取网络状态下面第一个方法基本上就够用了,后面两个获取IP地址、是否可以连接外网一般用不到。

public class NetStateUtils {
/*
* 获取当前的网络状态 :没有网络-0:WIFI网络1:4G网络-4:3G网络-3:2G网络-2
*/
public static int getNetworkType(Context context) {
int netType = 0;
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
if (networkInfo == null || !networkInfo.isAvailable()) {
return netType;
}
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);
if (nSubType == TelephonyManager.NETWORK_TYPE_LTE&&!telephonyManager.isNetworkRoaming()) {
//4G
netType = 4;
} else if (nSubType == TelephonyManager.NETWORK_TYPE_UMTS
|| nSubType == TelephonyManager.NETWORK_TYPE_HSDPA
|| nSubType == TelephonyManager.NETWORK_TYPE_EVDO_0
&& !telephonyManager.isNetworkRoaming()) {
//3G 联通的3G为UMTS或HSDPA 电信的3G为EVDO
netType = 3;
} else if (nSubType == TelephonyManager.NETWORK_TYPE_GPRS
|| nSubType == TelephonyManager.NETWORK_TYPE_EDGE
|| nSubType == TelephonyManager.NETWORK_TYPE_CDMA
&& !telephonyManager.isNetworkRoaming()) {
//2G 移动和联通的2G为GPRS或EGDE,电信的2G为CDMA
netType = 2;
} else {
netType = 2;
}
}
return netType;
}
/**
* 获得本机ip地址
*/
public static String GetHostIp() {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> ipAddr = intf.getInetAddresses(); ipAddr.hasMoreElements(); ) {
InetAddress inetAddress = ipAddr.nextElement();
if (!inetAddress.isLoopbackAddress()) {
return inetAddress.getHostAddress();
}
}
}
} catch (Exception e) {
}
return null;
} /*
* 判断是否有外网连接
*/
public static final boolean ping() {
String result = null;
try {
String ip = "www.baidu.com";
Process p = Runtime.getRuntime().exec("ping -c 3 -w 100 " + ip);// ping网址3次
InputStream input = p.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(input));
StringBuffer stringBuffer = new StringBuffer();
String content = "";
while ((content = in.readLine()) != null) {
stringBuffer.append(content);
}
int status = p.waitFor();
if (status == 0) {
return true;
}
} catch (Exception e) {
}
return false;
}
}

如果没有网络,可以弹出一个对话框来引导用户打开网络设置,这里可能你会用到的几个ACTION如下所示。

ACTION_DATA_ROAMING_SETTINGS : 跳转到移动网络设置界面
ACTION_WIFI_SETTINGS : 跳转到WIFI设置界面
ACTION_WIRELESS_SETTINGS : 跳转到无线控制界面,比如WIFI、蓝牙和移动网络设置界面。

public static void showWifiDlg(final Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context.getApplicationContext());
if (mWifiDialog == null) {
mWifiDialog = builder.setIcon(R.drawable.ic_launcher).setTitle("wifi设置")
.setMessage("无网络").setPositiveButton("设置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 跳转到系统的网络设置界面
Intent intent = null;
// 先判断当前系统版本
if (android.os.Build.VERSION.SDK_INT > 10) { // 3.0以上
intent = new Intent(android.provider.Settings.ACTION_WIFI_SETTINGS);
} else {
intent = new Intent();
intent.setClassName("com.android.settings",Settings.ACTION_WIFI_SETTINGS);
}
if ((context instanceof Application)) {
intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent);
}
}).setNegativeButton("知道了", null).create();
// 设置为系统的Dialog,这样使用Application的时候不会报错
mWifiDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
}
mWifiDialog.show();
}

在上述代码中,如果上下文信息是全局的上下文,则需要addFlags并且加入倒数第二行代码,否则会出错,还有就是不要忘记声明权限,最后一条权限即允许弹出系统级别的AlertDialog。

<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"/>
<!--允许弹出系统级别的AlertDialog-->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

2.  被动获取

被动获取是监听系统网络状态的广播。如果需要监听比如用户Wifi/移动网打开和关闭,以及连接上可用的连接等等行为,那么可以使用广播接收者来完成。因为不需要在APP退出后继续监听,因此可以使用动态的形式注册广播。

<receiver android:name=".NetworkConnectChangedReceiver"/>

接着在代码里动态的注册广播:

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");
registerReceiver(mNetworkChangeListener,filter);

最后是广播接收者的具体代码如下,主要是几个广播的几个intent.getAction()的含义,需要多注意。

注释里已经写的很明白了,得感谢一下gdutxiaoxu,省的我们自己去查了。

public class NetworkConnectChangedReceiver 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);
switch (wifiState) {
case WifiManager.WIFI_STATE_DISABLED:
//引导用户打开设置
break;
case WifiManager.WIFI_STATE_DISABLING:
break;
case WifiManager.WIFI_STATE_ENABLING:
break;
case WifiManager.WIFI_STATE_ENABLED:
//网络可用
break;
case WifiManager.WIFI_STATE_UNKNOWN:
break;
default:
break;
}
}
// 这个监听wifi的连接状态即是否连上了一个有效无线路由,当上边广播的状态是WifiManager
// .WIFI_STATE_DISABLING,和WIFI_STATE_DISABLED的时候,根本不会接到这个广播。
// 在上边广播接到广播是WifiManager.WIFI_STATE_ENABLED状态的同时也会接到这个广播,
// 当然刚打开wifi肯定还没有连接到有效的无线
if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(intent.getAction())) {
Parcelable parcelableExtra = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if (null != parcelableExtra) {
NetworkInfo networkInfo = (NetworkInfo) parcelableExtra;
State state = networkInfo.getState();
boolean isConnected = state == State.CONNECTED;
if (isConnected) {
//网络可用
} else {
//网络不可用
}
}
}
// 最好用的还是这个监听。Wifi/移动网打开,关闭,以及连接上可用的连接都会接到监听
// 这个广播的最大弊端是比上边两个广播的反应要慢,如果只是要监听wifi用上边两个配合比较合适
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
} else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
// connected to the mobile signal
}
} else {
//无网络连接
}
} else { // not connected to the internet
}
}
}
}

感谢:

http://blog.csdn.net/gdutxiaoxu/article/details/53008266

http://www.jianshu.com/p/10ed9ae02775

Android开发——监听Android手机的网络状态的更多相关文章

  1. Android 开发 监听back并且执行home键功能

    方法一: 在activity中重写onBackPressed()方法 ,注意此处一定要注释或者删除 super.onBackPressed();方法 @Override public void onB ...

  2. Android来电监听和去电监听

    我觉得写文章就得写得有用一些的,必须要有自己的思想,关于来电去电监听将按照下面三个问题展开 1.监听来电去电有什么用? 2.怎么监听,来电去电监听方式一样吗? 3.实战,有什么需要特别注意地方? 监听 ...

  3. Android实时监听网络状态

    Android实时监听网络状态(1)   其实手机在网络方面的的监听也比较重要,有时候我们必须实时监控这个程序的实时网络状态,android在网络断开与连接的时候都会发出广播,我们通过接收系统的广播就 ...

  4. Android 监听 Android中监听系统网络连接打开或者关闭的实现代码

    本篇文章对Android中监听系统网络连接打开或者关闭的实现用实例进行了介绍.需要的朋友参考下 很简单,所以直接看代码 复制代码 代码如下: package xxx; import android.c ...

  5. Android之监听手机软键盘弹起与关闭

    背景: 在很多App开发过程中需要在Activity中监听Android设备的软键盘弹起与关闭,但是Android似乎没有提供相关的的监听API给我们来调用,本文提供了一个可行的办法来监听软键盘的弹起 ...

  6. Android如何监听蓝牙耳机的按键事件

    写在前面: 直接想要代码很简单,你直接把滚动条拉到最底端就可以看到.如果想要十分地了解为什么,那就按照我规划的一步一步来理解.以下测试环境以手头上有的「Bluedio + 红米手机」. 1.蓝牙耳机的 ...

  7. Android如何监听蓝牙耳机的按键事件(转)

    源: Android如何监听蓝牙耳机的按键事件 写在前面: 直接想要代码很简单,你直接把滚动条拉到最底端就可以看到.如果想要十分地了解为什么,那就按照我规划的一步一步来理解.以下测试环境以手头上有的「 ...

  8. Android怎样监听蓝牙耳机的按键事件

    Android怎样监听蓝牙耳机的按键事件 写在前面: 直接想要代码非常easy,你直接把滚动栏拉到最底端就能够看到.假设想要十分地了解为什么,那就依照我规划的一步一步来理解.下面測试环境以手头上有的「 ...

  9. Android ScrollView监听滑动到顶部和底部的两种方式(你可能不知道的细节)

    Android ScrollView监听滑动到顶部和底部,虽然网上很多资料都有说,但是不全,而且有些细节没说清楚 使用场景: 1. 做一些复杂动画的时候,需要动态判断当前的ScrollView是否滚动 ...

随机推荐

  1. 学习MVC之租房网站(一)-项目概况

    这儿的MVC是ASP.NET MVC,只用过C#一种语言,后面就直接称呼为MVC了. 一年多没接触MVC后,现在想用MVC做个网站,觉得特别吃力,以前学的仅仅是皮毛,所以闲置了一年后,MVC知识就重新 ...

  2. Python中可视化图表处理echarts库的安装

    系统环境:Windows 7 企业版 进入cmd 输入:python –m pip install pyecharts

  3. Node.js环境搭建和学习(windwos环境)

    Node.js环境搭建和学习 一.环境搭建 1.下载安装文件 下载地址http://nodejs-org.qiniudn.com/下载Node.js环境安装包,根据操作系统下载对应的安装包 下载地址 ...

  4. [Spark Core] Spark 在 IDEA 下编程

    0. 说明 Spark 在 IDEA 下使用 Scala  & Spark 在 IDEA 下使用 Java 编写 WordCount 程序 1. 准备 在项目中新建模块,为模块添加 Maven ...

  5. SDN2017 第三次实验作业

    实验目的 在给定如上实验拓扑情况下,用vlan得到下列虚拟网段 h1--h4互通 h2--h5互通 h3--h6互通 其余主机间无法通信 实验步骤 1. 创建拓扑 #! /usr/bin/python ...

  6. 【Python】os.path.isfile()的使用方法汇总

    方法一: # -*- coding:utf-8 -*- import os import sys from uiautomator import device as d filepath = r'E: ...

  7. [NOIP2016 DAY1 T2]天天爱跑步-[差分+线段树合并][解题报告]

    [NOIP2016 DAY1 T2]天天爱跑步 题面: B[NOIP2016 DAY1]天天爱跑步 时间限制 : - MS 空间限制 : 565536 KB 评测说明 : 2s Description ...

  8. Actor模式初步入门

    Actor模型概念 Actor模型为并行而生,简单说是未解决高并发的一种编程思路.在Actor模型中,主角是Actor,类似一种worker,Actor彼此之间直接发送消息,不需要经过什么中介,消息是 ...

  9. ACM模拟赛

    今天是毕业的学长给高二的同学测试.组队比赛,ACM赛制,于是就愉快的和学姐一队啦. 看到英文题面感到恐慌,不过好在不难读懂. A:并没有什么技术含量的模拟题: B:字符串题,给定一些比赛和每个队胜利的 ...

  10. BZOJ4269:再见Xor(线性基)

    Description 给定N个数,你可以在这些数中任意选一些数出来,每个数可以选任意多次,试求出你能选出的数的异或和的最大值和严格次大值. Input 第一行一个正整数N. 接下来一行N个非负整数. ...