0
votes

I wrote an Android app for Android 9 that displays the user a list of available wifi networks and lets the user connect to them. Connecting to networks that offer internet connection works fine. But in most of the cases I have to connect to networks without internet connection. For my project I have to create my own access points/hotspots on a linux machine and therefore want my app to be able to connect to it.

If I pick one of my created networks, I am reconnected to a known and already configured wifi my device knows of that it offers internet connectivity (our office wifi for example).

I've already had a detailed look on stackoverflow but most people with this problem seemed to be working with Android Marshmallow or Lollipop and actually rather had the problem that their device was using mobile data to send/receive data while being connected to the non-internet wifi.

AFAIK Android likely rejects wifi networks that do not offer internet access. How can I tell the system to connect to them anyway? Connecting to these networks through the settings app works fine. It just doesn't work out of my app.

Here's my connect code so far:

private fun connectToSelectedNetwork(networkSSID: String){
    try {
        val conf = WifiConfiguration()
        conf.SSID = "\"" + networkSSID + "\""
        conf.preSharedKey = "\"" + PASSPHRASE + "\""

        val network = wifiManager?.addNetwork(conf)
        wifiManager?.disconnect()
        wifiManager?.enableNetwork(network!!, true)
        wifiManager?.reconnect()
    } catch (ex: Exception) {
        println(Arrays.toString(ex.stackTrace))
    }
}

Thanks!

1

1 Answers

0
votes

To anyone who may have the same problem, here is how I could solve it:

  1. In order to make sure that your device won't reconnect to your last connected wifi network, simply disable the current connected network before trying to connect to the new (possibly non-internet capable) wifi network. Also, I first check if the network I want to connect is already known to the device which saves us from creating a new wifi configuration.

  2. Sometimes though, connecting to a network may take over a minute. I honestly don't know why but I found a workaround for that, too. Whenever I try to connect to a new network using the above solution, I start a timer which timeouts after a certain time period (5 secs in my case). Once a connection establishment succeeded I stop the timer. But if there hasn't been a connection establishment after the timeout, I simply retry to connect to my desired network. In most of the cases (>95%) connecting succeeds within <10 secs.

Here's my working code:

    private lateinit var timeoutCoroutine: Job

    private fun connectToSelectedNetwork(SSID: String) {
        // Figure out if the network is known to the device and in this case connect to it
        if (!connectToKnownNetwork(SSID)){
            // If the network is unknown, we first have to configure it before connecting
            val network = configureNetwork(SSID)
            connect(network)
        }
        startConnectionEstablishmentTimeoutCoroutine(SSID)
    }

    private fun connectToKnownNetwork(SSID: String): Boolean {
        for (c in wifiManager.configuredNetworks) {
            if (SSID == c.SSID.removeSurrounding("\"")){
                if (connect(c.networkId)){
                    return true
                }
            }
        }
        return false
    }

    private fun configureNetwork(SSID: String): Int {
        val conf = WifiConfiguration()
        conf.SSID = "\"" + SSID + "\""
        conf.preSharedKey = "\"" + PASSPHRASE + "\""
        conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK)
        return wifiManager.addNetwork(conf)
    }

    private fun connect(network: Int): Boolean {
        wifiManager.disableNetwork(wifiManager.connectionInfo.networkId)
        wifiManager.disconnect()
        val success = wifiManager.enableNetwork(network, true)
        wifiManager.reconnect()
        wifiManager.reassociate()
        return success
    }

    // For unknown reasons connecting to a network takes up to a minute when the user has not
    // interacted with the device for a while (>~15 seconds).
    // To prevent this we set a timeout after which the connection establishment shall be retried.
    private fun startConnectionEstablishmentTimeoutCoroutine(SSID: String){
        timeoutCoroutine = CoroutineScope(IO).launch {
            delay(CONNECTION_ESTABLISHMENT_TIMEOUT)
            connectToNetwork(SSID)
        }
    }