4

I'm using the new API 29 for connecting the device to a wifi network in an Android 10 device:

    private val connectivityManager: ConnectivityManager by inject()

    override fun connectToNetwork(ssid: String, password: String) {
        val networkRequest = buildNetworkRequest(ssid, password)

        val networkCallback =
            object : NetworkCallback() {
                override fun onAvailable(network: Network) {
                    super.onAvailable(network)
                    Timber.d("Connected to network $ssid")
                }

                override fun onUnavailable() {
                    super.onUnavailable()
                    Timber.e("Unable to connect to network $ssid")
                }
            }

        connectivityManager.requestNetwork(networkRequest, networkCallback, CONNECTION_TIME_OUT)

    }

    private fun buildNetworkRequest(ssid: String, password: String) =
        NetworkRequest.Builder()
            .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
            .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            .setNetworkSpecifier(buildWifiNetworkSpecifier(ssid, password))
            .build()

    private fun buildWifiNetworkSpecifier(ssid: String, password: String) =
        WifiNetworkSpecifier.Builder()
            .setSsid(ssid)
            .setWpa2Passphrase(password)
            .build()

A dialog appears with a "Device to use with " with the specified wifi network listed. The dialog has two buttons for "cancel" and "connect". When I click "connect", the device connects to the wifi network (I can see that in the system settings) and the connect button is disabled.

But the dialog does not go away and none of the methods in the requestNetwork callback is invoked. Eventually I reach the specified timeout and another dialog comes with "Something came up. The application has cancelled the request to choose a device".

What is happening here? I want to connect to a network and have the 'onAvailable' or 'onUnavailable' methods in the callback invoked.

Rui
  • 936
  • 10
  • 21

2 Answers2

2

After trying almost everything, I finally managed to make this work as expected. Don't know why, but when I went to the device's system settings and forgot the wifi network that I was trying to connect programatically, this started to work.

I'm glad I got rid of the problem, but I don't know what was causing it, and it's a risk that the same thing happens to a future user.

Rui
  • 936
  • 10
  • 21
2

I had the same problem. By trial and error, I found out that this is due to the fact that the request occurs earlier than the network is finally connected. If you send a request after network availability, then everything works. Here is an example of code that solved my problem:

override fun onAvailable(network: Network) {                
            GlobalScope.launch(Dispatchers.IO) {
                while (!isNetworkAvailable(ctx)) {
                    delay(200)
                }
                launch(Dispatchers.Main) {
                    // begin request....
                }
            }
            cm.unregisterNetworkCallback(this)
        }

and

 private fun isNetworkAvailable(ctx: Context): Boolean {
    val connectivityManager = ctx.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        val nw = connectivityManager.activeNetwork ?: return false
        val actNw = connectivityManager.getNetworkCapabilities(nw) ?: return false
        return actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
    } else {
        val nwInfo = connectivityManager.activeNetworkInfo ?: return false
        return nwInfo.isConnected
    }
}

Also, before connecting, you have to clear ssid for the correct connection:

private fun removeSsid(ctx : Context, ssid : String, pass : String){
    val suggestion = WifiNetworkSuggestion.Builder()
        .setSsid(ssid)
        .setWpa2Passphrase(pass)
        .build()
    val wifiManager = ctx.getSystemService(WIFI_SERVICE) as WifiManager
    val sList = ArrayList<WifiNetworkSuggestion>()
    sList.add(suggestion)
    wifiManager.removeNetworkSuggestions(sList)
}