Search code examples
androidandroid-wifi

WifiNetworkSpecifier bypass user selection


I'm trying to implement a WiFi peer to peer network as described in the documentation:

https://developer.android.com/guide/topics/connectivity/wifi-bootstrap

I'm doing this to make the app future proof, older version of app simply added a Wifinetwork without any big deal but that is being deprecated now so I'm trying to use the new method for devices running Android 10.

Here is my code (called from a foreground service):

 if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
            WifiNetworkSpecifier.Builder builder = new WifiNetworkSpecifier.Builder();

            builder.setBssid(MacAddress.fromString("00:08:22:C0:9F:4A"));
            builder.setWpa2Passphrase("password");

            WifiNetworkSpecifier wifiNetworkSpecifier = builder.build();
            NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder();
            networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
            networkRequestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
            networkRequestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED);
            networkRequestBuilder.setNetworkSpecifier(wifiNetworkSpecifier);

            NetworkRequest networkRequest = networkRequestBuilder.build();
            final ConnectivityManager cm = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
            if (cm != null) {
                cm.requestNetwork(networkRequest, new ConnectivityManager.NetworkCallback() {
                    @Override
                    public void onAvailable(@NonNull Network network) {
                        //Use this network object to Send request.
                        //eg - Using OkHttp library to create a service request
                        InetAddress server = cm.getLinkProperties(network).getDnsServers().get(0);
                        Log.d(TAG,"Got the following address: "+server.getHostAddress());



                        super.onAvailable(network);
                    }
                });

            }
        }

This indeed works as expected, it does show the user a dialog with the available network and the user can select it, then I get a callback, and access the network as I need to. As soon as my foreground service stops, the WiFi connection is being teared off which is exactly what it's needed.

However next time when I try to connect, I get the same window asking the user to select the network, but based on the documentation from here: https://developer.android.com/guide/topics/connectivity/wifi-bootstrap#bypass-approval as long as I haven't forget the network while I was connected to it and did not used pattern for BSSID or SSID, this should be remembered and user approval should be bypassed. What am I'm missing, why do I keep getting the user approval window?

I thought it might be something limited to Activity/Service, but I experience the same behaviour even if I call this from an Activity.


Solution

  • Found the problem,issue. Might be my English or might be the documentation which wasn't obvious.

    If the app makes a non-specific request, such as with an SSID or BSSID pattern, then the user must approve the request.

    This means that both SSID and BSSID must be set. Not setting a BSSID is equivalent of setting a BSSID pattern. I realised this when I logged the NetworkRequest builder. In order to have the app automatically connect again to the network, you need to set up both values SSID and BSSID as well.