关于ACCESS_WIFI_STATE多次触发COMPLETED状态及替换为ASSOCIATING的咨询
Wi-Fi连接状态判断的问题解答
问题背景
我在广播接收器中使用以下代码判断Wi-Fi的连接与断开状态,该代码运行正常,但在Wi-Fi连接过程中,wifiInfo.getSupplicantState().equals(SupplicantState.COMPLETED)会返回true至少4到7次。请问我是否可以使用仅触发一次的SupplicantState.ASSOCIATING来替代?
原判断代码
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); if(wifiManager.isWifiEnabled()){ WifiInfo wifiInfo = wifiManager.getConnectionInfo(); if( wifiInfo.getSupplicantState().equals(SupplicantState.COMPLETED)){ //Connected ?? //Do Something } else if( wifiInfo.getSupplicantState().equals(SupplicantState.DISCONNECTED)){ //Do Something } } else{ //Wifi Adaptor disabled; }
广播接收器配置
<receiver android:name="WifiReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.net.wifi.STATE_CHANGE"/> </intent-filter> </receiver>
解答
嘿,这个场景我之前做项目时也踩过坑,咱们慢慢梳理清楚哈~
为什么COMPLETED会多次触发?
SupplicantState.COMPLETED只是Wi-Fi协议层面的关联完成状态,但实际连接流程里,系统可能因为多种原因重复上报这个状态:比如网络参数更新、重新校验认证信息、甚至AP信号波动导致的短暂重连,都会让这个状态被多次触发,所以你看到4-7次是很正常的现象。
能不能用ASSOCIATING替代?
非常不建议这么做,核心原因有两个:
ASSOCIATING只是连接过程中的中间状态,代表设备正在和Wi-Fi热点建立关联,但这时候还没完成身份认证、获取IP地址等关键步骤,网络其实还不可用。如果这时候你判定为“已连接”,后续的网络操作(比如接口请求、文件下载)大概率会失败。- 而且
ASSOCIATING也不是绝对只会触发一次,在复杂的网络环境下(比如热点信号不稳定、频繁切换信道),这个状态也可能被重复上报。
更可靠的解决方案
给你两个实用的优化方向,选哪个都能解决重复触发的问题:
方案1:结合NetworkInfo判断真正的可用状态
android.net.wifi.STATE_CHANGE广播中携带了NetworkInfo对象,它的isConnected()方法才是真正代表“Wi-Fi连接完成且网络可用”的状态,而且只会在连接成功/断开时触发极少次数(基本不会重复)。修改后的代码如下:
@Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) { // 获取广播携带的NetworkInfo对象 NetworkInfo networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); if (networkInfo != null) { if (networkInfo.isConnected()) { // 这里才是真正的Wi-Fi连接完成,网络已可用 // Do Something } else if (networkInfo.getState() == NetworkInfo.State.DISCONNECTED) { // Wi-Fi已断开 // Do Something } } } }
方案2:添加状态标记过滤重复触发
如果你一定要基于SupplicantState来判断,可以在广播接收器中维护一个全局变量记录上一次的状态,只有当当前状态和上一次不同时才执行操作:
// 定义全局变量记录上一次的状态 private SupplicantState lastState = null; @Override public void onReceive(Context context, Intent intent) { WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); if(wifiManager.isWifiEnabled()){ WifiInfo wifiInfo = wifiManager.getConnectionInfo(); SupplicantState currentState = wifiInfo.getSupplicantState(); // 只有当前状态和上一次不同时才执行操作 if (!currentState.equals(lastState)) { lastState = currentState; if(currentState.equals(SupplicantState.COMPLETED)){ //Connected //Do Something } else if(currentState.equals(SupplicantState.DISCONNECTED)){ //Do Something } } } else{ //Wifi Adaptor disabled; // 重置状态标记 lastState = null; } }
额外提醒
- 记得在Manifest中声明必要的权限:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>和<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> - 如果你是动态注册广播接收器,一定要在合适的时机(比如Activity的
onDestroy)注销,避免内存泄漏
内容的提问来源于stack exchange,提问作者Yesudass Moses
相关产品推荐
相关产品推荐

