0. 前言

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

1.  主动获取

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

  1. public class NetStateUtils {
  2. /*
  3. * 获取当前的网络状态 :没有网络-0:WIFI网络1:4G网络-4:3G网络-3:2G网络-2
  4. */
  5. public static int getNetworkType(Context context) {
  6. int netType = 0;
  7. ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
  8. NetworkInfo networkInfo = manager.getActiveNetworkInfo();
  9. if (networkInfo == null || !networkInfo.isAvailable()) {
  10. return netType;
  11. }
  12. int nType = networkInfo.getType();
  13. if (nType == ConnectivityManager.TYPE_WIFI) {
  14. //WIFI
  15. netType = 1;
  16. } else if (nType == ConnectivityManager.TYPE_MOBILE) {
  17. int nSubType = networkInfo.getSubtype();
  18. TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
  19. if (nSubType == TelephonyManager.NETWORK_TYPE_LTE&&!telephonyManager.isNetworkRoaming()) {
  20. //4G
  21. netType = 4;
  22. } else if (nSubType == TelephonyManager.NETWORK_TYPE_UMTS
  23. || nSubType == TelephonyManager.NETWORK_TYPE_HSDPA
  24. || nSubType == TelephonyManager.NETWORK_TYPE_EVDO_0
  25. && !telephonyManager.isNetworkRoaming()) {
  26. //3G 联通的3G为UMTS或HSDPA 电信的3G为EVDO
  27. netType = 3;
  28. } else if (nSubType == TelephonyManager.NETWORK_TYPE_GPRS
  29. || nSubType == TelephonyManager.NETWORK_TYPE_EDGE
  30. || nSubType == TelephonyManager.NETWORK_TYPE_CDMA
  31. && !telephonyManager.isNetworkRoaming()) {
  32. //2G 移动和联通的2G为GPRS或EGDE,电信的2G为CDMA
  33. netType = 2;
  34. } else {
  35. netType = 2;
  36. }
  37. }
  38. return netType;
  39. }
  40. /**
  41. * 获得本机ip地址
  42. */
  43. public static String GetHostIp() {
  44. try {
  45. for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
  46. NetworkInterface intf = en.nextElement();
  47. for (Enumeration<InetAddress> ipAddr = intf.getInetAddresses(); ipAddr.hasMoreElements(); ) {
  48. InetAddress inetAddress = ipAddr.nextElement();
  49. if (!inetAddress.isLoopbackAddress()) {
  50. return inetAddress.getHostAddress();
  51. }
  52. }
  53. }
  54. } catch (Exception e) {
  55. }
  56. return null;
  57. }
  58.  
  59. /*
  60. * 判断是否有外网连接
  61. */
  62. public static final boolean ping() {
  63. String result = null;
  64. try {
  65. String ip = "www.baidu.com";
  66. Process p = Runtime.getRuntime().exec("ping -c 3 -w 100 " + ip);// ping网址3次
  67. InputStream input = p.getInputStream();
  68. BufferedReader in = new BufferedReader(new InputStreamReader(input));
  69. StringBuffer stringBuffer = new StringBuffer();
  70. String content = "";
  71. while ((content = in.readLine()) != null) {
  72. stringBuffer.append(content);
  73. }
  74. int status = p.waitFor();
  75. if (status == 0) {
  76. return true;
  77. }
  78. } catch (Exception e) {
  79. }
  80. return false;
  81. }
  82. }

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

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

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

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

  1. <uses-permission android:name="android.permission.INTERNET"/>
  2. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
  3. <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
  4. <!--允许弹出系统级别的AlertDialog-->
  5. <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

2.  被动获取

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

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

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

  1. IntentFilter filter = new IntentFilter();
  2. filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
  3. filter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
  4. filter.addAction("android.net.wifi.STATE_CHANGE");
  5. registerReceiver(mNetworkChangeListener,filter);

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

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

  1. public class NetworkConnectChangedReceiver extends BroadcastReceiver {
  2. @Override
  3. public void onReceive(Context context, Intent intent) {
  4. // 这个监听wifi的打开与关闭,与wifi的连接无关
  5. if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) {
  6. int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);
  7. switch (wifiState) {
  8. case WifiManager.WIFI_STATE_DISABLED:
  9. //引导用户打开设置
  10. break;
  11. case WifiManager.WIFI_STATE_DISABLING:
  12. break;
  13. case WifiManager.WIFI_STATE_ENABLING:
  14. break;
  15. case WifiManager.WIFI_STATE_ENABLED:
  16. //网络可用
  17. break;
  18. case WifiManager.WIFI_STATE_UNKNOWN:
  19. break;
  20. default:
  21. break;
  22. }
  23. }
  24. // 这个监听wifi的连接状态即是否连上了一个有效无线路由,当上边广播的状态是WifiManager
  25. // .WIFI_STATE_DISABLING,和WIFI_STATE_DISABLED的时候,根本不会接到这个广播。
  26. // 在上边广播接到广播是WifiManager.WIFI_STATE_ENABLED状态的同时也会接到这个广播,
  27. // 当然刚打开wifi肯定还没有连接到有效的无线
  28. if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(intent.getAction())) {
  29. Parcelable parcelableExtra = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
  30. if (null != parcelableExtra) {
  31. NetworkInfo networkInfo = (NetworkInfo) parcelableExtra;
  32. State state = networkInfo.getState();
  33. boolean isConnected = state == State.CONNECTED;
  34. if (isConnected) {
  35. //网络可用
  36. } else {
  37. //网络不可用
  38. }
  39. }
  40. }
  41. // 最好用的还是这个监听。Wifi/移动网打开,关闭,以及连接上可用的连接都会接到监听
  42. // 这个广播的最大弊端是比上边两个广播的反应要慢,如果只是要监听wifi用上边两个配合比较合适
  43. if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
  44. ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
  45. NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
  46. if (activeNetwork != null) { // connected to the internet
  47. if (activeNetwork.isConnected()) {
  48. if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
  49. // connected to wifi
  50. } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
  51. // connected to the mobile signal
  52. }
  53. } else {
  54. //无网络连接
  55. }
  56. } else { // not connected to the internet
  57. }
  58. }
  59. }
  60. }

感谢:

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. VideoView获取本地视频播放

    主布局: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android ...

  2. 绝版Node--Sequlize搭建服务(Node全栈之路 二)

    在Node全栈之路(一),也就是上篇文章中,我们讲到了sequlize的基本增删该查,这篇文章,我们在上篇文章的基础上继续探讨,讲一下关于sequlize创建的表之间的对应关系 参考资料:https: ...

  3. vs2017安装cuda9.0编译默认示例失败解决方法

    https://devtalk.nvidia.com/default/topic/1027209/cuda-setup-and-installation/cuda-9-0-does-not-work- ...

  4. go语言练习:类型转换

    package main import "fmt" func main() { var a int var b uint var c float32 var d float64 a ...

  5. 转:.NET面试题汇总(三)

    原文地址:http://www.cnblogs.com/yuan-jun/p/6600692.html 1.简述 private. protected. public. internal 修饰符的访问 ...

  6. 高通Audio中ASOC的machine驱动(一)

    ASoC被分为Machine.Platform和Codec三大部分,其中的Machine驱动负责Platform和Codec之间的耦合以及部分和设备或板子特定的代码,再次引用上一节的内容:Machin ...

  7. 参观阿拉斯加进行产品培训[My representation]

    I  suggest to visit Alaska for product training. Alaska is one of the best places to spend a trainin ...

  8. JDK5新特性之 可变参数的方法

    可变参数的方法:不知道这个方法该定义多少个参数 注意: > 参数实际上是数组 > 必须写在参数列表最后一个 package cn.itcast.day24.varparam; import ...

  9. TiDB数据库 mydumper与loader导入数据

    从mysql导出数据最好的方法是使用tidb官方的工具mydumper. 导入tidb最好的方法是使用loader工具,大概19.4G每小时的速度. 详细的步骤可以参考官网:https://pingc ...

  10. ansible 碎记录

    https://www.zhukun.net/archives/8167 ansible -i new/hosts new -m authorized_key -a "user=root k ...