Android中wifi与数据流量的切换监听详解

 更新时间:2017年01月10日 10:55:54   作者:一杯清泉  
本文主要介绍了Android中wifi与数据流量的切换监听的方法步骤。具有一定的参考价值,下面跟着小编一起来看下吧

最近在做一个wifi和移动数据的监控功能,来来回回折腾了一阵子,这个模块的主要功能是监听整个APP的wifi与数据流量的切换,让用户使用专用流量,而不是用wifi,给一个弹窗,点击确认,自动切换数据流量,关闭wifi。我的思路是写一个静态广播,监听在广播里面进行监听,启用系统弹窗,点击确认,自动切换网络,这里面有一个坑就是弹窗会在广播中多次被调用,其实只调用了一次,但是实际上多次调用系统的弹窗会一个叠加一个,搞了好久,终于搞好了,原来是系统广播导致的叠加,详情看代码:

网络封装类ConnectivityManager:

ConnectivityManager 是一个网络连接的管理类,里面封装了网络请求的详细信息,包括WiFi与移动数据流量的开关状态,正在开启与关闭的状态,连接状态等等,很适合做网络监听。还有一个类WifiManager ,这个类专门用来做WiFi的监听,他的监听效果比ConnectivityManager更加详细丰富,可以检测但是对流量没法生效。这里使用ConnectivityManager 就足够了。

一、注册广播

1、写一个类继承自BroadcastReceiver。

@Override 
public void onReceive(Context context, Intent intent) { 
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 
 NetworkInfo gprs = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); 
NetworkInfo wifi = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); 
if (intent.getAction().equals("Android.net.conn.CONNECTIVITY_CHANGE"))  { 
//移动数据连接上时 
if (gprs.isConnected()){ 
} 
//wifi连接上时 
if (wifi.isConnected()) { 
// 切换网络,关闭wifi,开启流量 
if (isShow) {//做一个标记,避免多次弹窗的叠加bug,初始值为true,重要 
switchNetwork(context); 
}  
} 
//断网时 
if (!netManager.getGRPS().isConnected() || !netManager.getGRPS().isConnected()) { 
}   
} 

二、弹窗

弹窗一般用四种常用的方式:

1、使用popupwindow

2、使用dialog

3、WindowManager

4、系统弹窗

一般的弹窗需要依附于activity,在activity中弹窗,但是在服务中,不能简单的使用这种方式,一般是采用系统的弹窗,他的优先级很高,覆盖于应用界面的最高层,并且要设置setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT),要不然会崩溃的。

private void switchNetwork(final Context context) { 
AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.AlertDialog); 
builder.setTitle("提示"); 
builder.setMessage("请关闭wifi,打开移动网络"); 
builder.setCancelable(false); 
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { 
@Override 
public void onClick(DialogInterface dialog, int which) { 
// 控制网络的开关 
controlNetWork(context); 
isShow = true; 
} 
}); 
AlertDialog dialog = builder.create(); 
// 需要把对话框的类型设为TYPE_SYSTEM_ALERT,否则对话框无法在广播接收器里弹出 
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 
dialog.show(); 
isShow = false; 
} 

三、网络切换

wifi的网络切换比较容易,直接设置setWifiEnabled就可以完成切换,而数据流量的切换比较麻烦,他的方法是私有的,无法调用,我们可以通过反射,找到他的方法进行调用:具体看代码

private void controlNetWork(Context context) { 
    WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 
      // 允许流量,阻止wifi 
      wifiManager.setWifiEnabled(false);//false表示断开WiFi 
      NetManager netManager = new NetManager(context); 
      if (!netManager.getGRPS().isConnected()) { 
        ConnectivityManager gprsCM = (ConnectivityManager) context 
            .getSystemService(Context.CONNECTIVITY_SERVICE); 
        Class conmanClass; 
        try { 
          conmanClass = Class.forName(gprsCM.getClass().getName()); 
          final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService"); 
iConnectivityManagerField.setAccessible(true); 
          final Object iConnectivityManager = iConnectivityManagerField.get(gprsCM); 
          final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName()); 
          final Method setMobileDataEnabledMethod = iConnectivityManagerClass 
              .getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE); 
setMobileDataEnabledMethod.setAccessible(true);//true表示连接网络 
          setMobileDataEnabledMethod.invoke(iConnectivityManager, true); 
        } catch (Exception e) { 
          e.printStackTrace(); 
        } 
      } 
    } 
  } 

2、在清单文件中注册广播

<receiver 
      android:name=".NetChangeReceiver" 
      android:label="NetChangeReceiver" > 
      <intent-filter> 
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> 
      </intent-filter> 
</receiver> 

添加权限:

<uses-permission Android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

以上代码很详细的描述了网络切换的实时检测,更加详细丰富的就不在这里写出来了。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • Flutter实现底部和顶部导航栏

    Flutter实现底部和顶部导航栏

    这篇文章主要为大家详细介绍了Flutter实现底部和顶部导航栏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • Kotlin 作用域函数apply、let、run、with、also使用指南

    Kotlin 作用域函数apply、let、run、with、also使用指南

    在 Kotlin 开发中,作用域函数(Scope Functions)是一组能让代码更简洁、更函数式的高阶函数,本文将结合核心特性、代码示例和对比表格,助你精准掌握apply、let、run、with、also的使用精髓,感兴趣的朋友一起看看吧
    2025-04-04
  • 详解android使用ItemDecoration 悬浮导航栏效果

    详解android使用ItemDecoration 悬浮导航栏效果

    本篇文章主要介绍了Android 最流行的吸顶效果的实现及代码,非常具有实用价值,需要的朋友可以参考下。
    2017-01-01
  • Flutter 实现酷炫的3D效果示例代码

    Flutter 实现酷炫的3D效果示例代码

    这篇文章主要介绍了Flutter 实现酷炫的3D效果,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • clipse项目迁移到android studio的方法(图文最新版)

    clipse项目迁移到android studio的方法(图文最新版)

    这篇文章主要介绍了clipse项目迁移到android studio(图文最新版),需要的朋友可以参考下
    2015-10-10
  • android实现缓存图片等数据

    android实现缓存图片等数据

    本文给大家分享的是Android采用LinkedHashMap自带的LRU 算法缓存数据的方法和示例,有需要的小伙伴可以参考下。
    2015-07-07
  • Kotlin coroutineContext源码层深入分析

    Kotlin coroutineContext源码层深入分析

    表示一个元素或者是元素集合的接口。它有一个Key(索引)的Element实例集合,每一个Element的实例也是一个CoroutineContext,即集合中每个元素也是集合
    2022-11-11
  • Android如何创建自定义ActionBar

    Android如何创建自定义ActionBar

    这篇文章主要教大家如何创建自定义的ActionBar,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11
  • Android通过startService实现文件批量下载

    Android通过startService实现文件批量下载

    这篇文章主要为大家详细介绍了Android通过startService实现文件批量下载的示例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2015-12-12
  • RecyclerView消除底部分割线的方法

    RecyclerView消除底部分割线的方法

    这篇文章主要为大家详细介绍了RecyclerView消除底部分割线的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-09-09

最新评论