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 实时感知网络可用性 WIFI_STATE_CHANGED_ACTION 监听WiFi开关变化 RSSI_CHANGED_ACTION 监听信号强度变化 三者结合,实现完整的WiFi状态感知

这张图很清楚地展示了三个维度的关系。你想想看,如果只监听连接状态,那用户关掉WiFi时你就不知道了。如果只监听开关状态,那信号变差时你也感知不到。所以,实际项目中我建议三个都监听,但要注意频率控制。

好了,关于WiFi网络状态监听就讲到这里。核心就是记住:连接状态用NetworkCallback,开关状态用广播,信号强度用RSSI广播加防抖。下一章我们会聊更进阶的内容,先把基础打牢。


公众号:蓝海资料掘金营,微信deep3321