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

Target SDK 30的Android应用WiFi连接与跨应用网络异常求解

Android 目标SDK 30 WiFi连接适配问题

众所周知,Google已更新应用分发政策,要求新应用必须将目标SDK版本设置为Android 11(API level 30)及以上。我的应用在目标SDK版本低于30时运行正常,但将目标SDK升级到30后出现功能异常。

应用核心功能

  • 适配Android 6到11全版本,展示当前可用WiFi列表
  • 用户点击列表项后可连接对应WiFi,支持开放网络、加密网络等所有类型
  • 连接WiFi后,若存在认证门户则跳转至应用内嵌WebView的认证页面

当前问题及相关实现代码

问题1:WiFi网络建议方案切换网络失败

目标SDK 30下使用官方推荐的WiFi网络建议方案连接WiFi时,若设备此前已连接其他WiFi,尝试切换连接新WiFi时会失败,无法成功切换到目标新WiFi,对应实现代码如下:

val suggestion = WifiNetworkSuggestion.Builder()
    .setSsid(SSID) // SSID of network
    .setWpa2Passphrase(wifiPassword) // password is network is not open
    //.setIsAppInteractionRequired(true) // Optional (Needs location permission)
    .build()

val suggestionsList = listOf(suggestion)

val wifiManager =
    applicationContext.getSystemService(WIFI_SERVICE) as WifiManager

if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
    // do error handling here
    Log.e("NETWORK", "Error")
}

// Optional (Wait for post connection broadcast to one of your suggestions)
val intentFilter =
    IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);

val broadcastReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        Log.e("NETWORK", "broadcastReceiver")

        if (!intent.action.equals(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
            return;
        }
        // do post connect processing here
        Log.e("NETWORK", "post connect")
    }
};
registerReceiver(broadcastReceiver, intentFilter)

问题2:WifiNetworkSpecifier方案仅本应用可访问网络

此前目标SDK为29时,使用WifiNetworkSpecifier方案实现Android 10、11版本的WiFi连接功能运行正常,但如果目标SDK升级到30,使用该方案连接WiFi后仅当前应用可访问网络,应用外其他进程无法使用该WiFi网络,对应实现代码如下:

private fun android10andMoreVersionsWithoutOuterInternet(
  scanResult: ScanResult,
  wifiSSID: String,
  wifiPassword: String,
  capabilities: String
) {
    // Android 10 (API level 29) -- Android Q (Android 10)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        val wifiManager =
            this.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager

        val wifiNetworkSpecifier = WifiNetworkSpecifier.Builder()
            .setSsid(wifiSSID)
            //.setSsidPattern(PatternMatcher(wifiSSID, PatternMatcher.PATTERN_PREFIX))
            .setWpa2Passphrase(wifiPassword)
            .build()

        val networkRequest = NetworkRequest.Builder()
            .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
            //.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            //.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            //.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
            .setNetworkSpecifier(wifiNetworkSpecifier)
            .build()
        val connectivityManager =
            this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager


        val networkCallback = object : ConnectivityManager.NetworkCallback() {
            override fun onAvailable(network: Network) {
                Log.d("NETWORK", "Network available")
                super.onAvailable(network)

                // To make sure that requests don't go over mobile data
                connectivityManager.bindProcessToNetwork(network)

                //unregister network callback
                //connectivityManager.unregisterNetworkCallback(this)
               // connectivityManager.bindProcessToNetwork(null)

                gotoNextScreen(scanResult, wifiManager)

            }

            override fun onUnavailable() {
                Log.d("NETWORK", "Network unavailable")
                super.onUnavailable()
            }

            override fun onLosing(network: Network, maxMsToLive: Int) {
                Log.d("NETWORK", "onLosing")
                super.onLosing(network, maxMsToLive)
            }

            override fun onLost(network: Network) {
                Log.d("NETWORK", "onLost")
                super.onLost(network)

                //connectivityManager.bindProcessToNetwork(null)
                //connectivityManager.unregisterNetworkCallback(this)
            }

        }
        connectivityManager.requestNetwork(networkRequest, networkCallback)
        val builder = NetworkRequest.Builder()
        builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        connectivityManager.registerNetworkCallback(builder.build(), networkCallback)
        //connectivityManager.registerNetworkCallback(networkRequest, networkCallback) // For listen
    }

}

Android 9及以下版本实现(无适配问题)

Android 9及更低版本使用已废弃的WifiConfiguration相关旧API实现,功能完全正常,不受目标SDK版本影响,对应实现代码如下:

private fun android9AndPreviousVersion(
  scanResult: ScanResult,
  wifiSSID: String,
  wifiPassword: String,
  capabilities: String
   ) {
  val conf = WifiConfiguration()
  conf.SSID =
      "\"" + wifiSSID + "\"" // Please note the quotes. String should contain ssid in quotes
  conf.status = WifiConfiguration.Status.ENABLED
  conf.priority = 40

  if (Common.checkWifiType(capabilities) == "WEP") {
      Log.e("NETWORK", "Configuring WEP")
      conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)
      conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN)
      conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA)
      conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN)
      conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED)
      conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP)
      conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP)
      conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40)
      conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104)
      if (wifiPassword.matches(Regex("^[0-9a-fA-F]+$"))) {
          conf.wepKeys[0] = wifiPassword
      } else {
          conf.wepKeys[0] = "\"" + wifiPassword + "\""
      }
      conf.wepTxKeyIndex = 0
  } else if (Common.checkWifiType(capabilities) == "WPA") {
      Log.e("NETWORK", "Configuring WPA")
      conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN)
      conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA)
      conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK)
      conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP)
      conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP)
      conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40)
      conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104)
      conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP)
      conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP)
      conf.preSharedKey = "\"" + wifiPassword + "\""
  } else {
      Log.e("NETWORK", "Configuring OPEN network")
      conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)
  }
  val wifiManager =
      this.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
  val networkId = wifiManager.addNetwork(conf)
  Log.e("NETWORK", "Add result $networkId")

  if (ActivityCompat.checkSelfPermission(
          this,
          Manifest.permission.ACCESS_FINE_LOCATION
      ) != PackageManager.PERMISSION_GRANTED
  ) {
      return
  }

  val list = wifiManager.configuredNetworks
  for (i in list) {
      if (i.SSID != null && i.SSID == "\"" + wifiSSID + "\"") {
          Log.e("NETWORK", "WifiConfiguration SSID " + i.SSID)
          val isDisconnected = wifiManager.disconnect()
          Log.e("NETWORK", "isDisconnected : $isDisconnected")
          val isEnabled = wifiManager.enableNetwork(i.networkId, true)
          Log.e("NETWORK", "isEnabled : $isEnabled")
          val isReconnected = wifiManager.reconnect()
          Log.e("NETWORK", "isReconnected : $isReconnected")
          break
      }
  }
  //val connectionInfo: WifiInfo = wifiManager.getConnectionInfo()
  gotoNextScreen(scanResult, wifiManager)
}

问题总结

目标SDK为30时,使用WifiNetworkSpecifier连接WiFi可成功,但仅当前应用可访问网络,其他应用无法使用该WiFi网络;使用WiFi网络建议方案连接WiFi时,无法从已连接的其他WiFi切换到新的目标WiFi,该问题在Android 10、11设备上均可复现。

需求

需要适配目标SDK 30的解决方案,覆盖Android 6到11全版本,连接WiFi后全设备所有应用均可正常访问该网络。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 03:36:03