问题
I am working on an application in which one the user has to follow these steps :
- connect the phone to a wifi ;
- connect the phone to a dedicated hotspot from a connected object.
When the user is connected to the dedicated hotspot of the connected object, the application does some HTTP requests in order to configure it. Then, I would like to reconnect automatically the application to the global wifi of the step 1.
From API 21 to API 28 this feature is very easy to implement because I know the SSID I want to reconnect the phone to. It can be done with few line of code:
private fun changeCurrentWifiNetworkLegacy(ssidToConnect: String) {
val wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
var ssidIdentifier: Int? = null
wifiManager.configuredNetworks?.forEach { config ->
Log.d("SSID", config.SSID)
if (config.SSID == "\"${ssidToConnect}\"") {
ssidIdentifier = config.networkId
}
}
ssidIdentifier?.let { id ->
wifiManager.enableNetwork(id, true)
}
}
On API 29 this simple code does not work anymore according to this article : https://developer.android.com/about/versions/10/privacy/changes#configure-wifi
According to the article, now, I should use 2 classes : WifiNetworkSpecifier
and/or WifiNetworkSuggestion
.
Unfortunately, I cannot find a working example using these classes in order to connect the user to a previous configured SSID.
Does someone already achieve that ?
Thank you in advance for your help.
回答1:
You can set which network to connect to with the following code:
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkRequest = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.setNetworkSpecifier(
WifiNetworkSpecifier.Builder()
.setSsid("My ssid")
.build()
)
.build()
cm.requestNetwork(networkRequest, object: ConnectivityManager.NetworkCallback() {
override fun onUnavailable() {
Log.d("TEST", "Network unavailable")
}
override fun onAvailable(network: Network) {
Log.d("TEST", "Network available")
}
})
}
This uses the ConnectivityManager's networkRequest method to request a network with a specific SSID.
This method requires the caller to hold either the Manifest.permission.CHANGE_NETWORK_STATE
permission or the ability to modify system settings as determined by Settings.System.canWrite(Context)
.
See the NetworkCallback class for more documentation about what info you can get.
(edit: Missed adding Transport type.)
Further edit: I needed to use .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
to get it to work properly. Because in WifiNetworkSpecifier
can only be used to request a local wifi network (i.e no internet capability)
According to the docs
This gives me a request for devices popup, but then eventually shows me the Wifi network I asked for.
回答2:
Just in case any poor soul encounters this, it's completely possible the API is just broken on your device. On my OnePlus 5, Android 10, Build 200513, this happens:
- Call requestNetwork. Doesn't matter whether I use the Listener or PendingIntent version
- The OS finds the network, connects, onAvailable and friends are called
- OS immediately disconnects. I can see "App released request, cancelling NetworkRequest" in logcat
- This is however, not true - the request was not cancelled, which Android relizes, and starts the process of connecting to the network again. Go to 2. and repeats forever.
Created an Android bug for this: https://issuetracker.google.com/issues/158344328
Additionally, you can get the OS into state when it will no longer show the "Device to use with " dialog if you don't terminate your app and the dialogs in the correct order, and only reboot helps.
Just save yourself the trouble, target Android 9 and use the WifiManager APIs (that are helpfully broken if you target 10). It even has better user experience than the new requestNetwork APIs.
来源:https://stackoverflow.com/questions/58769623/android-10-api-29-how-to-connect-the-phone-to-a-configured-network