You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android:如何准确检测WiFi已完全连接?

解答Android WiFi切换中的状态不一致问题

我来帮你拆解这些WiFi API的异常行为问题,结合你的日志和代码逐一分析:

1. 为什么切换到NET3时会触发NET1的CONNECTED状态?

Android的WiFi状态广播并不是严格按照实时状态顺序触发的,在网络切换的瞬间,系统内部的状态同步存在延迟:

  • 当你调用disconnect()enableNetwork(net3, true)后,系统首先会开始断开当前连接的NET1,但之前NET1的CONNECTED状态事件可能还在广播队列中等待分发,所以会先收到这条旧状态的日志。
  • 后续的DISCONNECTED, "NET1"才是NET1真正断开的事件,这是网络切换流程中的正常状态回调顺序。

2. 为什么NetworkInfo显示NET1,而getConnectionInfo()返回NET3?

这两个API的数据源完全不同:

  • NetworkInfo是当前广播事件对应的网络的状态快照,这里的事件是NET1断开前的收尾状态,所以显示NET1。
  • WifiManager.getConnectionInfo()获取的是系统当前激活的网络配置,当你调用enableNetwork(net3, true)后,系统已经将NET3设为待连接的活跃配置,所以会直接返回NET3的信息,哪怕此时NET3还没真正连接上。
    这种不一致是Android WiFi API设计的正常现象,不能混用来判断当前实际连接的网络。

3. 如何准确检测目标网络的连接状态?能否从NetworkInfo中提取SSID?

准确提取当前事件对应的SSID

你更新的代码思路是对的!不要用WifiManager.getConnectionInfo(),而是直接从广播Intent中获取WifiInfo,它才是当前事件对应的网络信息:

private final BroadcastReceiver mWifiConnectReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context c, Intent intent) {
        // 获取当前事件对应的NetworkInfo
        NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
        // 获取当前事件对应的WifiInfo(关键!)
        WifiInfo wifiInfo = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
        
        if (wifiInfo != null && info != null) {
            String ssid = wifiInfo.getSSID().replaceAll("^\"(.*)\"$", "$1");
            Log.i("MyApp", "--------------------------");
            Log.i("MyApp", info.getDetailedState() + ", SSID: " + ssid);
            
            // 检测目标网络(NET3)是否真正连接完成
            if ("NET3".equals(ssid) && info.getDetailedState() == NetworkInfo.DetailedState.CONNECTED) {
                // 此时可以获取IP地址,连接路由器Socket
                int ipAddress = wifiInfo.getIpAddress();
                String localIp = String.format("%d.%d.%d.%d", 
                    (ipAddress & 0xff), 
                    (ipAddress >> 8 & 0xff), 
                    (ipAddress >> 16 & 0xff), 
                    (ipAddress >> 24 & 0xff));
                Log.i("MyApp", "NET3已连接,本地IP:" + localIp);
                
                // 如果需要路由器网关IP,可以通过DhcpInfo获取
                DhcpInfo dhcpInfo = m_manager.getDhcpInfo();
                String gatewayIp = String.format("%d.%d.%d.%d", 
                    (dhcpInfo.gateway & 0xff), 
                    (dhcpInfo.gateway >> 8 & 0xff), 
                    (dhcpInfo.gateway >> 16 & 0xff), 
                    (dhcpInfo.gateway >> 24 & 0xff));
                Log.i("MyApp", "路由器网关IP:" + gatewayIp);
            }
        }
    }
};

准确检测目标网络连接状态的要点

  • 只处理目标SSID的事件:过滤掉其他SSID的状态回调,避免被旧网络的状态干扰。
  • 等待真正的CONNECTED状态CONNECTED状态出现后,还要确认WifiInfo的IP地址不为0(或者等待OBTAINING_IPADDR之后的CONNECTED),确保网络已经完成IP分配,此时才能正常连接路由器的Socket。
  • 避免依赖全局的WifiManager状态:优先使用广播Intent中携带的WifiInfoNetworkInfo,它们是当前事件的精准快照,不会提前指向新网络。

内容的提问来源于stack exchange,提问作者folibis

火山引擎 最新活动