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

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
            )
        }
    }
}

关键注意事项

  1. 权限必须前置:SDK 29+调用Wi-Fi相关API前,必须确保ACCESS_FINE_LOCATION和CHANGE_WIFI_STATE权限已授予,否则API调用直接失败。
  2. 回调内存泄漏:调用requestNetwork后,必须在组件销毁时执行unregisterNetworkCallback,避免内存泄漏。
  3. 加密类型匹配:根据目标Wi-Fi的加密类型选择对应的密码方法(WPA2用setWpa2Passphrase,WPA3用setWpa3Passphrase,开放网络无需设置密码)。
  4. 网络绑定(可选):如果需要强制应用仅使用当前连接的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 04:02:01