Android 10 / API 29 : how to connect the phone to a configured network?

给你一囗甜甜゛ 提交于 2020-07-05 03:19:27

问题


I am working on an application in which one the user has to follow these steps :

  1. connect the phone to a wifi ;
  2. 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:

  1. Call requestNetwork. Doesn't matter whether I use the Listener or PendingIntent version
  2. The OS finds the network, connects, onAvailable and friends are called
  3. OS immediately disconnects. I can see "App released request, cancelling NetworkRequest" in logcat
  4. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!