私たちが知っているように、Google は新しいアプリが Android 11 (API レベル 30) 以上をターゲットにする必要があるというポリシーを更新しました。下位のターゲット SDK を使用している場合、アプリは期待どおりに動作しますが、ターゲット SDK 30 を使用している場合、期待どおりに動作しません。
アプリには次の主な機能があります。
- 利用可能な WiFi は、Android 6 から 11 (最新の Android バージョン) のリストに表示されます。
- リスト項目をクリックした後、ユーザーはそれぞれの Wi-Fi に接続する必要があります。OPEN またはその他のいずれかです。
- それぞれの WiFi に接続した後、キャプティブ ページがあればそのページにリダイレクトされます。キャプティブ ページは、アプリへの WebView になります。
要点を言えば、対象の 30 SDK で次の問題に直面しています。
- 最新の提案wifi接続コード[1]を使用している場合、部分的に機能しています。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 のときはいつでも、 Android 10 と 11 で WiFi を接続するために WifiNetworkSpecifier [2]アプローチを使用しています。これも機能していました。
ターゲット 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)
}
結論:ターゲット SDK 30で利用可能な WiFi に接続するためにWifiNetworkSpecifierを使用している場合、接続できますが、私のインターネットはアプリでのみ機能します。ターゲット SDK 30で利用可能な WiFi に接続するために最新の提案 WiFiを使用している場合、新しい WiFi に接続できません。Android 10 および Android 11 デバイスでこの問題に直面しています。
解決策を教えてください。POC コードを確認してください[こちら]