You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 13及以上版本无法通过代码连接WiFi求助

Android 13+ WiFi连接回调触发但实际未连接的问题解决

问题现象

传入SSID和密码调用WiFi连接函数后,onAvailable回调返回连接可用,但设备实际并未成功连接到目标WiFi;该逻辑在Android 12及以下版本正常运行,在Android 13及以上版本失效。

原连接代码

public void reconnectToWifi(Context context, String password, OnAvailableCallback onAvailableCallback) {
        // Disconnect from the current Wi-Fi network
        wifiManager.disconnect();

        Handler handler = new Handler(Looper.getMainLooper());

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
            // Create a new WifiNetworkSpecifier.Builder for the desired Wi-Fi network
            WifiNetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
                    .setSsid(ssid)
                    .setWpa2Passphrase(password)
                    .build();

            // Create a new NetworkRequest using the specifier
            NetworkRequest request = new NetworkRequest.Builder()
                    .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                    .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                    .setNetworkSpecifier(specifier)
                    .build();

            // Register a NetworkCallback to handle the connection
            ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
                @Override
                public void onAvailable(@NonNull Network network) {
                    super.onAvailable(network);
                    // Connection successful, perform any necessary actions
                    Log.d(TAG, "Connected to the Wi-Fi network: " + ssid);

                    boolean connected = isConnectedToSpecificWifi(context, ssid);

                    if (connected) {
                        Log.d(TAG, "Really connected to the Wi-Fi network: " + ssid);
                        handler.postDelayed(onAvailableCallback::onAvailableCallback, 5000);
                    } else {
                        Log.d(TAG, "Not connected to the Wi-Fi network: " + ssid);
                        reconnectToWifi(context, "pass", onAvailableCallback);
                    }

                    connectivityManager.unregisterNetworkCallback(this);
                }

                @Override
                public void onUnavailable() {
                    super.onUnavailable();
                    // Connection unsuccessful, handle accordingly
                    Log.d(TAG, "Failed to connect to the Wi-Fi network: " + ssid);
                    connectivityManager.unregisterNetworkCallback(this);

                    reconnectToWifi(context, "pass", onAvailableCallback);
                }
            };

            // Request the network using the NetworkRequest and NetworkCallback
            connectivityManager.requestNetwork(request, networkCallback);

            Log.d(TAG, "Connecting to the Wi-Fi network: " + ssid);
        }
    }

已配置权限

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES">

问题分析

Android 13(API 33)对WiFi连接的权限和系统逻辑做了关键调整,原代码的问题集中在:

  1. 权限处理缺失:NEARBY_WIFI_DEVICES权限未在运行时申请,Android 13+要求明确申请该权限才能连接热点;
  2. NetworkRequest配置错误:盲目移除NET_CAPABILITY_INTERNET会导致系统对网络的判断逻辑异常,触发回调但未完成实际连接;
  3. 连接逻辑漏洞:直接调用wifiManager.disconnect()无法确保立即断开当前网络,且递归重试时硬编码密码为"pass"完全错误;
  4. 网络绑定缺失:回调触发后未将应用绑定到目标网络,导致应用仍使用原网络;
  5. 状态判断可能失效:Android 13+获取WiFi SSID的权限要求更严格,原判断函数可能无法正确获取当前连接状态。

解决步骤

1. 修正权限配置与申请

  • 在Manifest中完善NEARBY_WIFI_DEVICES权限声明,添加neverForLocation标记减少权限要求:
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES"
    android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.INTERNET" /> <!-- 若目标WiFi带互联网则添加 -->
  • 在连接前检查并申请NEARBY_WIFI_DEVICES权限:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    if (ContextCompat.checkSelfPermission(context, Manifest.permission.NEARBY_WIFI_DEVICES)
            != PackageManager.PERMISSION_GRANTED) {
        ActivityResultLauncher<String> requestPermissionLauncher =
                ((Activity) context).registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
                    if (isGranted) {
                        reconnectToWifi(context, password, onAvailableCallback);
                    } else {
                        Log.d(TAG, "NEARBY_WIFI_DEVICES权限被拒绝");
                    }
                });
        requestPermissionLauncher.launch(Manifest.permission.NEARBY_WIFI_DEVICES);
        return;
    }
}

2. 调整NetworkRequest配置

根据目标WiFi是否带互联网,决定是否保留NET_CAPABILITY_INTERNET:

NetworkRequest request = new NetworkRequest.Builder()
        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        .setNetworkSpecifier(specifier)
        // 若目标WiFi无互联网,再添加此行:.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
        .build();

3. 修复连接逻辑

  • 先解除当前网络绑定再断开WiFi;
  • 替换硬编码的重试密码,改用传入的password参数;
  • 限制重试次数,避免无限循环;
  • 回调触发后绑定应用到目标网络:
// 解除当前网络绑定
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    connectivityManager.bindProcessToNetwork(null);
}
// 断开当前WiFi
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
wifiManager.disconnect();

// 回调内添加绑定逻辑
@Override
public void onAvailable(@NonNull Network network) {
    super.onAvailable(network);
    // 绑定应用到目标网络
    connectivityManager.bindProcessToNetwork(network);
    // ...后续逻辑
}

4. 修正连接状态判断函数

适配Android 13+的网络状态获取方式,处理SSID的双引号问题:

public boolean isConnectedToSpecificWifi(Context context, String ssid) {
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        Network network = cm.getActiveNetwork();
        if (network != null) {
            NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
            if (capabilities != null && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                String currentSsid = wifiInfo.getSSID().replace("\"", "");
                return ssid.equals(currentSsid);
            }
        }
    } else {
        NetworkInfo networkInfo = cm.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
            WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            String currentSsid = wifiInfo.getSSID().replace("\"", "");
            return ssid.equals(currentSsid);
        }
    }
    return false;
}

完整修正后的代码

public void reconnectToWifi(Context context, String password, OnAvailableCallback onAvailableCallback) {
    // 处理Android 13+权限
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.NEARBY_WIFI_DEVICES)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityResultLauncher<String> requestPermissionLauncher =
                    ((Activity) context).registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
                        if (isGranted) {
                            reconnectToWifi(context, password, onAvailableCallback);
                        } else {
                            Log.d(TAG, "NEARBY_WIFI_DEVICES权限被拒绝");
                        }
                    });
            requestPermissionLauncher.launch(Manifest.permission.NEARBY_WIFI_DEVICES);
            return;
        }
    }

    Handler handler = new Handler(Looper.getMainLooper());
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

    // 解除当前网络绑定
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        connectivityManager.bindProcessToNetwork(null);
    }

    // 断开当前WiFi
    WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    wifiManager.disconnect();

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        WifiNetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
                .setSsid(ssid)
                .setWpa2Passphrase(password)
                .build();

        NetworkRequest request = new NetworkRequest.Builder()
                .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                // 根据目标WiFi是否带互联网决定是否移除该能力
                // .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                .setNetworkSpecifier(specifier)
                .build();

        ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
            private int retryCount = 0;
            private static final int MAX_RETRY = 3;

            @Override
            public void onAvailable(@NonNull Network network) {
                super.onAvailable(network);
                Log.d(TAG, "回调触发:尝试连接" + ssid);

                // 绑定应用到目标网络
                connectivityManager.bindProcessToNetwork(network);

                handler.postDelayed(() -> {
                    boolean connected = isConnectedToSpecificWifi(context, ssid);
                    if (connected) {
                        Log.d(TAG, "成功连接到" + ssid);
                        onAvailableCallback.onAvailableCallback();
                    } else {
                        Log.d(TAG, "未实际连接,正在重试...");
                        if (retryCount < MAX_RETRY) {
                            retryCount++;
                            reconnectToWifi(context, password, onAvailableCallback);
                        } else {
                            Log.d(TAG, "重试次数耗尽,连接失败");
                        }
                    }
                    connectivityManager.unregisterNetworkCallback(this);
                }, 2000);
            }

            @Override
            public void onUnavailable() {
                super.onUnavailable();
                Log.d(TAG, "无法连接到" + ssid);
                if (retryCount < MAX_RETRY) {
                    retryCount++;
                    reconnectToWifi(context, password, onAvailableCallback);
                } else {
                    Log.d(TAG, "重试次数耗尽,连接失败");
                }
                connectivityManager.unregisterNetworkCallback(this);
            }
        };

        connectivityManager.requestNetwork(request, networkCallback);
        Log.d(TAG, "开始连接" + ssid);
    }
}

// 修正后的连接状态判断函数
public boolean isConnectedToSpecificWifi(Context context, String ssid) {
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        Network network = cm.getActiveNetwork();
        if (network != null) {
            NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
            if (capabilities != null && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                String currentSsid = wifiInfo.getSSID().replace("\"", "");
                return ssid.equals(currentSsid);
            }
        }
    } else {
        NetworkInfo networkInfo = cm.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
            WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            String currentSsid = wifiInfo.getSSID().replace("\"", "");
            return ssid.equals(currentSsid);
        }
    }
    return false;
}

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 00:05:56