androidwifimanager

How to restore Wi-Fi connection after using requestNetwork on Android


Background: I have an Android app which configures an IoT device's Wi-Fi connection:

  1. The IoT device exposes an Access Point with a specific name
  2. The app connects to the AP
  3. The app sends the SSID & passphrase of the user's Wi-Fi network to the device
  4. Both the device and the smartphone connect to the home Wi-Fi network.

I've had a working solution based on WifiManager.addNetwork & WiFiManager.enableNetwork, but these APIs are unavailable with targetSdkLevel set to 29 or above (which is a hard requirement now on Google Play).

The new API offered by Android is ConnectivityManager.requestNetwork. This works quite well during steps 1-3, but after disconnecting from the temporary network (by removing the network request with ConnectivityManager.unregisterNetworkCallback), the smartphone does not reconnect to the original Wi-Fi network - it stays disconnected from Wi-Fi until the user manually selects a Wi-Fi network in Settings. Even if there is no other data connection available.

Is there a way to force the phone to connect to its preferred Wi-Fi network after using requestNetwork?


Solution

  • It's not really apparent from the documentation, but on Android 10 (API level 29) and higher, you need to always call connectivityManager.unregisterNetworkCallback(networkCallback) when you don't need the Wifi connection anymore. Here is the code sample from the Android documentation:

    val specifier = WifiNetworkSpecifier.Builder()
        .setSsidPattern(PatternMatcher("test", PatternMatcher.PATTERN_PREFIX))
        .setBssidPattern(MacAddress.fromString("10:03:23:00:00:00"), MacAddress.fromString("ff:ff:ff:00:00:00"))
        .build()
    
    val request = NetworkRequest.Builder()
        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
        .setNetworkSpecifier(specifier)
        .build()
    
    val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    
    val networkCallback = object : ConnectivityManager.NetworkCallback() {
        ...
        override fun onAvailable(network: Network?) {
            // do success processing here..
        }
    
        override fun onUnavailable() {
            // do failure processing here..
        }
        ...
    }
    connectivityManager.requestNetwork(request, networkCallback)
    ...
    // Release the request when done.
    connectivityManager.unregisterNetworkCallback(networkCallback)
    

    Please, take into account to always call the method from the last line.