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

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

ConnectivityManager类

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

一、注册广播

写一个类继承自BroadcastReceiver。

 
  1. @Override

  2. public void onReceive(Context context, Intent intent) {

  3. ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

  4. NetworkInfo gprs = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);

  5. NetworkInfo wifi = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);

  6. if (intent.getAction().equals("Android.net.conn.CONNECTIVITY_CHANGE")) {

  7. //移动数据连接上时

  8. if (gprs.isConnected()){

  9. }

  10. //wifi连接上时

  11. if (wifi.isConnected()) {

  12. // 切换网络,关闭wifi,开启流量

  13. if (isShow) {//做一个标记,避免多次弹窗的叠加bug,初始值为true,重要

  14. switchNetwork(context);

  15. }

  16. }

  17. //断网时

  18. if (!netManager.getGRPS().isConnected() || !netManager.getGRPS().isConnected()) {

  19. }

  20. }

二、弹窗

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

1、使用popupwindow

2、使用dialog

3、WindowManager

4、系统弹窗

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

 
  1. private void switchNetwork(final Context context) {

  2. AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.AlertDialog);

  3. builder.setTitle("提示");

  4. builder.setMessage("请关闭wifi,打开移动网络");

  5. builder.setCancelable(false);

  6. builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {

  7. @Override

  8. public void onClick(DialogInterface dialog, int which) {

  9. // 控制网络的开关

  10. controlNetWork(context);

  11. isShow = true;

  12. }

  13. });

  14. AlertDialog dialog = builder.create();

  15. // 需要把对话框的类型设为TYPE_SYSTEM_ALERT,否则对话框无法在广播接收器里弹出

  16. dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

  17. dialog.show();

  18. isShow = false;

  19. }

三、网络切换

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

 
  1. private void controlNetWork(Context context) {

  2. WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

  3. // 允许流量,阻止wifi

  4. wifiManager.setWifiEnabled(false);//false表示断开WiFi

  5. ConnectivityManager conn = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

  6. boolean connected = conn.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isConnected();

  7. if (!connected) {

  8. ConnectivityManager gprsCM = (ConnectivityManager) context

  9. .getSystemService(Context.CONNECTIVITY_SERVICE);

  10. Class conmanClass;

  11. try {

  12. conmanClass = Class.forName(gprsCM.getClass().getName());

  13. final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService");

  14. iConnectivityManagerField.setAccessible(true);

  15. final Object iConnectivityManager = iConnectivityManagerField.get(gprsCM);

  16. final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName());

  17. final Method setMobileDataEnabledMethod = iConnectivityManagerClass

  18. .getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);

  19. setMobileDataEnabledMethod.setAccessible(true);//true表示连接网络

  20. setMobileDataEnabledMethod.invoke(iConnectivityManager, true);

  21. } catch (Exception e) {

  22. e.printStackTrace();

  23. }

  24. }

在清单文件中注册广播

 
  1. <receiver

  2. android:name=".NetChangeReceiver"

  3. android:label="NetChangeReceiver" >

  4. <intent-filter>

  5. <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />

  6. </intent-filter>

  7. </receiver>

添加权限:

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

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

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

猜你喜欢

转载自blog.csdn.net/qq_35114086/article/details/81805064
今日推荐