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连接的权限和系统逻辑做了关键调整,原代码的问题集中在:
- 权限处理缺失:
NEARBY_WIFI_DEVICES权限未在运行时申请,Android 13+要求明确申请该权限才能连接热点; - NetworkRequest配置错误:盲目移除
NET_CAPABILITY_INTERNET会导致系统对网络的判断逻辑异常,触发回调但未完成实际连接; - 连接逻辑漏洞:直接调用
wifiManager.disconnect()无法确保立即断开当前网络,且递归重试时硬编码密码为"pass"完全错误; - 网络绑定缺失:回调触发后未将应用绑定到目标网络,导致应用仍使用原网络;
- 状态判断可能失效: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
相关产品推荐
相关产品推荐

