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

如何解决ConnectivityManager连接SAE加密隐藏SSID超时并稳定连接?

问题描述

使用ConnectivityManager连接SAE加密的隐藏SSID时出现超时,无法成功建立连接;但将该SSID设置为非隐藏状态时,连接流程完全正常。

现有代码实现

连接函数

@RequiresApi(Build.VERSION_CODES.R)
fun connectSae(ssid: String, password: String) {
    val suggestion = WifiNetworkSpecifier.Builder().setSsid(ssid).setWpa3Passphrase(password)
        .setIsHiddenSsid(if (hide_ssid.equals(true)) true else false).build()
    val networkRequest = NetworkRequest.Builder().addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        .setNetworkSpecifier(suggestion).build()
    // mCm?.registerNetworkCallback(networkRequest, mNetworkCallback)
    mCm?.requestNetwork(networkRequest, mNetworkCallback)
}

Intent参数处理

if (intent.getBooleanExtra("hide_ssid", false)) {
    // am start -n com.example.wifiConnect/.MainActivity -e ssid SH-AP-006_5G -e passwd 12345678 --ez hide_ssid true -e type SAE
    hide_ssid = intent.getBooleanExtra("hide_ssid", false)
    Log.d(TAG, "intent hide_ssid $hide_ssid")
}
if (intent.hasExtra("type")) {
    type = intent.getStringExtra("type").toString()
    Log.d(TAG, "intent type $type")
}

全局变量

companion object {
    const val TAG = "MainActivity"

    @SuppressLint("StaticFieldLeak")
    lateinit var mContext: Context

    lateinit var mWifiManager: WifiManager
    var mConfig: WifiConfiguration? = null

    lateinit var mCm: ConnectivityManager
    lateinit var myWifiInfo: WifiInfo

    lateinit var scanResult: List<ScanResult>
    var hide_ssid = false
    var type = ""
    var wifi_action = ""
    lateinit var SECURITY_TYPE: String
    lateinit var mNetworkCallback: NetworkCallback
}

onCreate初始化逻辑

mContext = getApplicationContext()
mWifiManager = mContext.getSystemService(WIFI_SERVICE) as WifiManager
mCm = mContext.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
mNetworkCallback = object : ConnectivityManager.NetworkCallback() {
    override fun onUnavailable() {
        super.onUnavailable()
    }

    override fun onLosing(network: Network, maxMsToLive: Int) {
        super.onLosing(network, maxMsToLive)

    }

    override fun onAvailable(network: Network) {
        super.onAvailable(network)
        mCm?.bindProcessToNetwork(network)
    }

    override fun onLost(network: Network) {
        super.onLost(network)

    }
}

解决方案

针对隐藏SSID+SAE加密的连接场景,可通过以下优化实现稳定连接:

1. 优化NetworkSpecifier构建

简化隐藏SSID判断逻辑,同时指定AP工作频段(已知情况下),缩小扫描范围减少超时概率:

@RequiresApi(Build.VERSION_CODES.R)
fun connectSae(ssid: String, password: String) {
    val specifierBuilder = WifiNetworkSpecifier.Builder()
        .setSsid(ssid)
        .setWpa3Passphrase(password)
        .setIsHiddenSsid(hide_ssid)
        // 已知AP频段时添加,二选一
        .setBand(WifiNetworkSpecifier.BAND_5_GHZ) 
        // .setBand(WifiNetworkSpecifier.BAND_2_4_GHZ)

    val suggestion = specifierBuilder.build()
    val networkRequest = NetworkRequest.Builder()
        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        .setNetworkSpecifier(suggestion)
        .build()

    // 先注销旧回调,避免重复注册导致的异常
    mCm?.unregisterNetworkCallback(mNetworkCallback)
    mCm?.requestNetwork(networkRequest, mNetworkCallback)
}

2. 完善回调的错误处理与重试机制

隐藏SSID连接易出现超时,添加重试逻辑提升成功率:

mNetworkCallback = object : ConnectivityManager.NetworkCallback() {
    private var retryCount = 0
    private val maxRetry = 3

    override fun onUnavailable() {
        super.onUnavailable()
        Log.e(TAG, "连接失败,重试 ${retryCount + 1}/$maxRetry")
        if (retryCount < maxRetry) {
            retryCount++
            Handler(Looper.getMainLooper()).postDelayed({
                // 替换为实际传入的ssid和password参数
                connectSae(ssid, password)
            }, 1000)
        } else {
            Log.e(TAG, "重试次数耗尽,连接失败")
        }
    }

    override fun onAvailable(network: Network) {
        super.onAvailable(network)
        retryCount = 0 // 重置重试计数
        mCm?.bindProcessToNetwork(network)
        Log.d(TAG, "成功连接到隐藏SSID")
    }

    override fun onLost(network: Network) {
        super.onLost(network)
        Log.d(TAG, "连接丢失,重新尝试连接")
        connectSae(ssid, password)
    }
}

3. 主动触发WiFi扫描(部分设备适配)

部分设备对隐藏SSID的自动扫描支持不佳,手动触发扫描可提升识别率:

fun triggerWifiScan() {
    // Android 12+ 可替换为 NEARBY_WIFI_DEVICES 权限
    val permission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        Manifest.permission.NEARBY_WIFI_DEVICES
    } else {
        Manifest.permission.ACCESS_FINE_LOCATION
    }

    if (ContextCompat.checkSelfPermission(mContext, permission) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, arrayOf(permission), 1001)
        return
    }
    mWifiManager.startScan()
}

调用connectSae前先执行triggerWifiScan(),确保设备先扫描到目标网络。

4. 备选方案:结合WifiConfiguration预配置

若上述方法仍不稳定,可先通过WifiManager添加隐藏SSID的配置,再发起连接:

fun addHiddenSaeConfig(ssid: String, password: String): WifiConfiguration? {
    val config = WifiConfiguration()
    config.SSID = "\"$ssid\""
    config.hiddenSSID = true
    config.status = WifiConfiguration.Status.ENABLED
    config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE)
    config.preSharedKey = "\"$password\""

    val networkId = mWifiManager.addNetwork(config)
    if (networkId != -1) {
        mWifiManager.enableNetwork(networkId, false)
        return config
    }
    return null
}

在connectSae前调用该方法,确保系统已存在目标网络的配置记录。


关键注意事项
  • 权限要求:Android 10及以下需ACCESS_FINE_LOCATION权限;Android 12+可使用NEARBY_WIFI_DEVICES权限替代位置权限。
  • 硬件兼容性:确保设备支持WPA3 SAE协议,旧款设备可能仅支持WPA2,无法连接SAE加密网络。
  • 频段匹配:若AP仅工作在单一频段,指定频段可避免跨频段扫描的干扰,加快连接速度。

内容的提问来源于stack exchange,提问作者赵小甲

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 17:20:40