Android中wifi与数据流量的切换监听详解
最近在做一个wifi和移动数据的监控功能,来来回回折腾了一阵子,这个模块的主要功能是监听整个APP的wifi与数据流量的切换,让用户使用专用流量,而不是用wifi,给一个弹窗,点击确认,自动切换数据流量,关闭wifi。我的思路是写一个静态广播,监听在广播里面进行监听,启用系统弹窗,点击确认,自动切换网络,这里面有一个坑就是弹窗会在广播中多次被调用,其实只调用了一次,但是实际上多次调用系统的弹窗会一个叠加一个,搞了好久,终于搞好了,原来是系统广播导致的叠加,详情看代码:
网络封装类ConnectivityManager:
ConnectivityManager是一个网络连接的管理类,里面封装了网络请求的详细信息,包括WiFi与移动数据流量的开关状态,正在开启与关闭的状态,连接状态等等,很适合做网络监听。还有一个类WifiManager,这个类专门用来做WiFi的监听,他的监听效果比ConnectivityManager更加详细丰富,可以检测但是对流量没法生效。这里使用ConnectivityManager就足够了。
一、注册广播
1、写一个类继承自BroadcastReceiver。
@Override
publicvoidonReceive(Contextcontext,Intentintent){
ConnectivityManagermanager=(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfogprs=manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
NetworkInfowifi=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),要不然会崩溃的。
privatevoidswitchNetwork(finalContextcontext){
AlertDialog.Builderbuilder=newAlertDialog.Builder(context,R.style.AlertDialog);
builder.setTitle("提示");
builder.setMessage("请关闭wifi,打开移动网络");
builder.setCancelable(false);
builder.setPositiveButton("确定",newDialogInterface.OnClickListener(){
@Override
publicvoidonClick(DialogInterfacedialog,intwhich){
//控制网络的开关
controlNetWork(context);
isShow=true;
}
});
AlertDialogdialog=builder.create();
//需要把对话框的类型设为TYPE_SYSTEM_ALERT,否则对话框无法在广播接收器里弹出
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
dialog.show();
isShow=false;
}
三、网络切换
wifi的网络切换比较容易,直接设置setWifiEnabled就可以完成切换,而数据流量的切换比较麻烦,他的方法是私有的,无法调用,我们可以通过反射,找到他的方法进行调用:具体看代码
privatevoidcontrolNetWork(Contextcontext){
WifiManagerwifiManager=(WifiManager)context.getSystemService(Context.WIFI_SERVICE);
//允许流量,阻止wifi
wifiManager.setWifiEnabled(false);//false表示断开WiFi
NetManagernetManager=newNetManager(context);
if(!netManager.getGRPS().isConnected()){
ConnectivityManagergprsCM=(ConnectivityManager)context
.getSystemService(Context.CONNECTIVITY_SERVICE);
ClassconmanClass;
try{
conmanClass=Class.forName(gprsCM.getClass().getName());
finalFieldiConnectivityManagerField=conmanClass.getDeclaredField("mService");
iConnectivityManagerField.setAccessible(true);
finalObjectiConnectivityManager=iConnectivityManagerField.get(gprsCM);
finalClassiConnectivityManagerClass=Class.forName(iConnectivityManager.getClass().getName());
finalMethodsetMobileDataEnabledMethod=iConnectivityManagerClass
.getDeclaredMethod("setMobileDataEnabled",Boolean.TYPE);
setMobileDataEnabledMethod.setAccessible(true);//true表示连接网络
setMobileDataEnabledMethod.invoke(iConnectivityManager,true);
}catch(Exceptione){
e.printStackTrace();
}
}
}
}
2、在清单文件中注册广播
<receiver android:name=".NetChangeReceiver" android:label="NetChangeReceiver"> <intent-filter> <actionandroid:name="android.net.conn.CONNECTIVITY_CHANGE"/> </intent-filter> </receiver>
添加权限:
<uses-permissionAndroid:name="android.permission.INTERNET"/> <uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/>
以上代码很详细的描述了网络切换的实时检测,更加详细丰富的就不在这里写出来了。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持毛票票!