10、WiFi网络状态监听:监听WiFi连接状态(NetworkCallback)、监听WiFi开关状态、监听WiFi信号变化
各位同学,今天我们来聊聊WiFi网络状态监听。说实话,这块内容在实际开发中非常实用。你想想看,一个App如果连网络状态都感知不到,那用户体验肯定好不到哪去。我个人习惯把WiFi状态监听分为三个维度:连接状态、开关状态、信号强度。咱们一个一个来拆解。
10.1 监听WiFi连接状态:NetworkCallback
先说说连接状态。Android 5.0之后,官方推荐用ConnectivityManager.NetworkCallback来监听网络变化。为什么?因为老的广播方式(WifiManager.NETWORK_STATE_CHANGED_ACTION)有延迟,而且不够精准。
我在项目中遇到过一个问题:用户从WiFi切换到移动网络时,App还在用WiFi的IP发请求,结果全部超时。后来改用NetworkCallback,问题就解决了。
核心思路:NetworkCallback能实时感知网络可用性,而不是仅仅知道“WiFi连上了”。
来看代码:
// 注册NetworkCallback
ConnectivityManager connectivityManager =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkCallback networkCallback = new NetworkCallback() {
@Override
public void onAvailable(Network network) {
// 网络可用,但不一定是WiFi
Log.d("WiFiMonitor", "网络可用");
}
@Override
public void onLost(Network network) {
// 网络断开
Log.d("WiFiMonitor", "网络断开");
}
@Override
public void onCapabilitiesChanged(Network network,
NetworkCapabilities capabilities) {
// 网络能力变化,这里可以判断是否是WiFi
if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
Log.d("WiFiMonitor", "当前是WiFi网络");
}
}
};
// 注意:需要指定NetworkRequest
NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build();
connectivityManager.registerNetworkCallback(request, networkCallback);
小提示:别忘了在onDestroy()或页面销毁时调用unregisterNetworkCallback(),否则会造成内存泄漏。我曾经因为这个被QA提过bug,印象很深。
10.2 监听WiFi开关状态
接下来是WiFi开关状态。说白了,就是用户有没有在设置里打开WiFi。这个监听相对简单,用WifiManager的广播就行。
嗯,这里要注意:Android 10之后,直接读取WiFi开关状态需要ACCESS_FINE_LOCATION权限。为什么?因为Google认为WiFi扫描可以定位用户位置。所以,如果你只是想知道开关状态,建议用WifiManager.isWifiEnabled()配合广播。
我曾经遇到一个坑:在Android 12上,isWifiEnabled()返回false,但WiFi其实是开的。后来发现是权限问题。所以,我建议你同时监听广播和检查状态,双重保险。
// 注册广播接收器
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
registerReceiver(wifiStateReceiver, filter);
// 广播接收器
private BroadcastReceiver wifiStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN);
switch (wifiState) {
case WifiManager.WIFI_STATE_ENABLED:
Log.d("WiFiMonitor", "WiFi已开启");
break;
case WifiManager.WIFI_STATE_DISABLED:
Log.d("WiFiMonitor", "WiFi已关闭");
break;
case WifiManager.WIFI_STATE_ENABLING:
Log.d("WiFiMonitor", "WiFi正在开启...");
break;
case WifiManager.WIFI_STATE_DISABLING:
Log.d("WiFiMonitor", "WiFi正在关闭...");
break;
}
}
};
注意事项:广播接收器记得在onPause()或onDestroy()中注销。另外,Android 8.0之后,静态注册的广播接收器对隐式广播有限制,建议动态注册。
10.3 监听WiFi信号变化
最后是信号强度。这个需求很常见,比如显示WiFi信号格数,或者在信号弱时提示用户。Android提供了WifiManager.RSSI_CHANGED_ACTION广播,但说实话,这个广播触发频率很高,处理不好容易卡顿。
我个人习惯用ScanResult.level来获取信号强度,单位是dBm。数值越大(越接近0),信号越好。一般范围是-100到-55。
来看一个简单的信号等级划分:
| 信号强度 (dBm) | 等级 | 说明 |
|---|---|---|
| -50 以上 | 优秀 | 满格,体验极佳 |
| -60 到 -50 | 良好 | 正常使用,无明显卡顿 |
| -70 到 -60 | 一般 | 可能偶尔掉线 |
| -80 到 -70 | 较差 | 连接不稳定,建议靠近路由器 |
| -80 以下 | 极差 | 基本无法正常使用 |
代码实现也很直接:
// 注册信号变化广播
IntentFilter rssiFilter = new IntentFilter();
rssiFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
registerReceiver(rssiReceiver, rssiFilter);
private BroadcastReceiver rssiReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// 获取当前连接的WiFi信息
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
int rssi = wifiInfo.getRssi(); // 单位dBm
// 转换为信号等级(0-4格)
int level = WifiManager.calculateSignalLevel(rssi, 5);
Log.d("WiFiMonitor", "当前信号强度: " + rssi + " dBm, 等级: " + level);
// 信号太弱时提醒用户
if (rssi < -80) {
// 这里可以弹出提示或切换网络
Log.w("WiFiMonitor", "信号极差,建议检查网络");
}
}
};
避坑指南:我曾经在信号变化广播里做网络请求,结果手机发烫严重。后来加了防抖处理,比如1秒内只处理一次。另外,calculateSignalLevel的第二个参数是等级数,一般用5(对应5格信号)。
10.4 知识体系总览
为了让你更直观地理解这三个监听维度的关系,我画了一张图:
这张图很清楚地展示了三个维度的关系。你想想看,如果只监听连接状态,那用户关掉WiFi时你就不知道了。如果只监听开关状态,那信号变差时你也感知不到。所以,实际项目中我建议三个都监听,但要注意频率控制。
好了,关于WiFi网络状态监听就讲到这里。核心就是记住:连接状态用NetworkCallback,开关状态用广播,信号强度用RSSI广播加防抖。下一章我们会聊更进阶的内容,先把基础打牢。
公众号:蓝海资料掘金营,微信deep3321