正如我们所知,谷歌已经更新了他们的政策,新应用程序必须以 Android 11(API 级别 30)或更高版本为目标。如果我使用目标较低的 SDK,我的应用程序将按预期工作,但是当我使用目标 SDK 30 时,它没有按预期工作。
应用程序中有以下主要功能:
- 适用于 Android 6 至 11(最新 Android 版本)的可用 WiFi 应在列表中可见
- 单击任何列表项后,用户应连接到他们尊敬的 WiFi。它可以是 OPEN 或其他。
- 与各自的 WiFi 连接后,如果有,它将重定向到强制页面。Captive 页面将 WebView 放入应用程序。
现在说到重点,我面临着目标 30 SDK 的以下问题。
- 当我使用最新的建议 wifi 连接代码[1]时,它可以部分工作。有一个问题,假设我们已经连接到另一个 WiFi 连接,我正在尝试连接新的 WiFi,那么它没有连接到新的 WiFi,但我需要连接新的 Wifi。
在具有目标 SDK 30 的应用程序中使用的代码(未与新 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)
- 每当我的目标 SDK 为 29 时,我就会使用 WifiNetworkSpecifier [2]方法在 Android 10 和 11 中连接 WiFi。它也可以正常工作。
在应用程序中使用目标 SDK 29 的代码(按预期工作,但目标 SDK 必须为 28 或 29,否则互联网将无法在应用程序中运行)-
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 abd 中使用的代码(按预期工作并且不影响任何目标 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)
}
结论:当我使用WifiNetworkSpecifier连接到具有目标 SDK 30的可用 WiFi 时,我可以连接,但我的 Internet 只能在 App 中工作。当我使用最新的Suggestion wifi连接到具有目标 SDK 30的可用 WiFi 时,我无法连接到新的 WiFi。我在 Android 10 和 Android 11 设备中遇到了这个问题。
请向我建议解决方案。请检查我的 POC 代码[这里]