Android 10及以上用Kotlin通过Wi-Fi Suggestion API连接指定Wi-Fi
Android 程序化连接指定Wi-Fi(适配SDK 29+)
问题梳理
在SDK 28及以下版本中,使用WifiManager可以直接实现Wi-Fi连接,但SDK 29起该API被弃用,官方推出Wi-Fi Suggestion和NetworkRequest两套API分别用于系统自动连接推荐网络和主动请求连接指定网络。你的代码同时混用了这两类API,导致逻辑不够清晰,以下是针对性的修正方案。
核心API区别
WifiNetworkSuggestion:向系统提交可信任的Wi-Fi网络列表,由系统决定何时自动连接,适合长期可用的常用网络。WifiNetworkSpecifier+ConnectivityManager.requestNetwork:主动发起连接指定Wi-Fi的请求,适合临时需要连接特定网络的场景(也是你要实现的程序化连接需求)。
完整适配代码
1. 权限配置(AndroidManifest.xml)
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- SDK 30+ 额外需要 --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
2. Kotlin实现代码
private fun connectToWifi(ssid: String, password: String) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // 检查必要权限 if (ActivityCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission( this, Manifest.permission.CHANGE_WIFI_STATE ) != PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions( this, arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CHANGE_WIFI_STATE ), 1001 ) return } // 构建Wi-Fi网络指定器(匹配目标网络) val wifiSpecifier = WifiNetworkSpecifier.Builder() .setSsid(ssid) .setWpa2Passphrase(password) // WPA3网络改用setWpa3Passphrase .build() // 构建网络请求参数 val networkRequest = NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .setNetworkSpecifier(wifiSpecifier) .build() val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager // 注册网络状态回调 val networkCallback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { super.onAvailable(network) runOnUiThread { Toast.makeText(this@YourActivity, "Wi-Fi连接成功", Toast.LENGTH_SHORT).show() } // 可选:强制应用绑定到该网络(忽略其他网络) // connectivityManager.bindProcessToNetwork(network) } override fun onUnavailable() { super.onUnavailable() runOnUiThread { Toast.makeText(this@YourActivity, "Wi-Fi连接失败", Toast.LENGTH_SHORT).show() } } override fun onLost(network: Network) { super.onLost(network) runOnUiThread { Toast.makeText(this@YourActivity, "Wi-Fi连接断开", Toast.LENGTH_SHORT).show() } // 解绑网络 // connectivityManager.bindProcessToNetwork(null) } } // 发起连接请求 connectivityManager.requestNetwork(networkRequest, networkCallback) // 注意:页面销毁时必须调用unregisterNetworkCallback避免内存泄漏 // connectivityManager.unregisterNetworkCallback(networkCallback) } else { // SDK 28及以下的兼容逻辑 val networkSSID = ssid val networkPass = password val conf = WifiConfiguration() conf.SSID = "\"$networkSSID\"" conf.preSharedKey = "\"$networkPass\"" conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK) val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager val networkId = wifiManager.addNetwork(conf) if (ActivityCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) == PackageManager.PERMISSION_GRANTED ) { wifiManager.disconnect() wifiManager.enableNetwork(networkId, true) wifiManager.reconnect() Toast.makeText(this, "Wi-Fi连接成功", Toast.LENGTH_SHORT).show() } else { ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 1002 ) } } }
关键注意事项
- 权限必须前置:SDK 29+调用Wi-Fi相关API前,必须确保
ACCESS_FINE_LOCATION和CHANGE_WIFI_STATE权限已授予,否则API调用直接失败。 - 回调内存泄漏:调用
requestNetwork后,必须在组件销毁时执行unregisterNetworkCallback,避免内存泄漏。 - 加密类型匹配:根据目标Wi-Fi的加密类型选择对应的密码方法(WPA2用
setWpa2Passphrase,WPA3用setWpa3Passphrase,开放网络无需设置密码)。 - 网络绑定(可选):如果需要强制应用仅使用当前连接的Wi-Fi,可调用
connectivityManager.bindProcessToNetwork(network),不再需要时解绑。
补充:Wi-Fi Suggestion API用法
如果希望系统后续自动连接该Wi-Fi,可在连接成功后添加网络建议:
val wifiSuggestion = WifiNetworkSuggestion.Builder() .setSsid(ssid) .setWpa2Passphrase(password) .setIsAppInteractionRequired(true) // 标记为用户主动添加的信任网络 .build() val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager val status = wifiManager.addNetworkSuggestions(listOf(wifiSuggestion)) when (status) { WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS -> { Toast.makeText(this, "已添加Wi-Fi自动连接建议", Toast.LENGTH_SHORT).show() } else -> { Toast.makeText(this, "添加Wi-Fi建议失败", Toast.LENGTH_SHORT).show() } }
内容的提问来源于stack exchange,提问作者Priyanshu Paliwal
相关产品推荐
相关产品推荐

