Oreo Wifi Connectivity
Asked Answered
C

4

13

I am working on an IoT app in which there is an on boarding process where the user connects to an access point, which has not internet connectivity, configure the device and then connects to his home Wifi network.

Android 8 devices have been causing some problems, disconnecting from the access point and reconnecting to a previously configured network. I am assuming this is related to the connectivity update which was introduced in Android 8, from section Seamless Connectivity in this link:

On compatible devices, automatic activation of Wi-Fi when a high quality saved network is nearby.

My question is how to disable this behaviour as I need to stay connected to the access point, without internet connectivity, and finish the on Boarding process.

Censorious answered 19/3, 2018 at 12:38 Comment(4)
@Yvette Colomb I mean that the device automatically switches between the access point network, the one without internet access, and previously configured home network.Censorious
automatic activation of Wi-Fi ??? You are connected with wifi to that accespoint arent you? So wifi is activated already.Luncheon
@DigitalDa did you manage to solve this eventually?Ruggiero
@Ruggiero we didn't, ended working around the situation with a different UX.Censorious
P
2

I had same issue. This is how I fix this issue in Android 8+ devices. 1. Since Android 8+ devices auto switch between WiFI and Cellular devices. I removed below code. i.e. Code to force move to wifi.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    NetworkRequest.Builder request = new NetworkRequest.Builder();
    Log.i("forceCellularConnection","request WIFI enable");
    request.addCapability(NetworkCapabilities.TRANSPORT_WIFI);
    connectivityManager.requestNetwork(request.build(), new ConnectivityManager.NetworkCallback() {
          @Override
          public void onAvailable(Network network) {
               if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                      connectivityManager.setProcessDefaultNetwork(network);

                      connectivityManager.bindProcessToNetwork(network);
                }
           }
     });

}
  1. Also added below code to forget wifi connection before we make new connection. It takes some time for device to disconnect WiFI. So I added delay before connecting to new WIFI SSID.

    this.wifiManager.disableNetwork(configuration.networkId);
    this.wifiManager.removeNetwork(configuration.networkId);
    this.wifiManager.saveConfiguration(); // Not needed in API level 26 and above
    

Workaround which I tried and helped me making connection work are below: In my case also I have to connect WiFi which doesn't have internet on it. Its a peer to peer connection.

  1. I Made 2-3 attempts for connection

    new CountDownTimer(16000, 2000) {
    
  2. Also I have written below broadcast receiver to check the state of WiFI. And then made the connection.

    private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() 
    {
        @Override
        public void onReceive(Context context, Intent intent) {
    
            final String action = intent.getAction();
    
            Log.d("WifiReceiver", ">>>>SUPPLICANT_STATE_CHANGED_ACTION<<<<<<");
            SupplicantState supl_state = ((SupplicantState) intent
                    .getParcelableExtra(WifiManager.EXTRA_NEW_STATE));
            switch (supl_state) {
            case ASSOCIATED:
                Log.i("SupplicantState", "ASSOCIATED");
                // authMsg = "ASSOCIATED";
                break;
            case ASSOCIATING:
                // authMsg = "ASSOCIATING";
                Log.i("SupplicantState", "ASSOCIATING");
                break;
            case AUTHENTICATING:
                // authMsg = "AUTHENTICATING";
                Log.i("SupplicantState", "Authenticating...");
                break;
            case COMPLETED:
                authMsg = "CONNECTED";
                Log.i("SupplicantState", "Connected");
                 final ConnectivityManager connection_manager =
                 (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    
                NetworkRequest.Builder request = new NetworkRequest.Builder();
                request.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
    
                connection_manager.registerNetworkCallback(request.build(), new ConnectivityManager.NetworkCallback() {
    
                    @Override
                    public void onAvailable(Network network) {
                        ConnectivityManager.setProcessDefaultNetwork(network);
                    }
                });
                break;
            case DISCONNECTED:
    
Propagandist answered 21/8, 2018 at 19:24 Comment(0)
R
1

I had the same issue. What I did is adding a step to the boarding process where I invite the user to go to there settings, add manually this network with no data and accept the popup shown by the system.

I have not found a real solution yet. However, I've seen an app called eWeLink where they manage to do it, but it is not an open source project.

Resemble answered 28/3, 2018 at 9:44 Comment(2)
The issue is that Android O introduced a "smart" mechanism to switch between networks, letting the OS decide what's good for you. I've tried hacking the wifi configuration with reflection as well as registering network callback to prefer networks without internet connectivity and use their socket factory. My attempts have not been successful and I chose the same solution you did. From reading the WifiConfiguration Android sources it seems this is the best way to go. There is also another option which I have yet to try and that is to bind a socket to the specific network.Censorious
I would be interested if you succeed doing it to see your solution if you're willing to share it. I had no more time to spend on it...Resemble
S
1

I am currently facing the same issue right now for the newer phone with Android 8.+. I am using WifiManager call bindProcessToNetwork here this will allows data traffic go through the wifi with no internet access,

here how I connect my phone to the access point

//Method to connect to WIFI Network
public boolean connectTo(String networkSSID, String key) {
    WifiConfiguration config = new WifiConfiguration();
    WifiInfo info = wifi.getConnectionInfo(); //get WifiInfo
    int id = info.getNetworkId(); //get id of currently connected network

    config.SSID = "\"" + networkSSID + "\"";
    if (key.isEmpty()) {
        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
    }
    int netID = wifi.addNetwork(config);

    int tempConfigId = getExistingNetworkId(config.SSID);

    if (tempConfigId != -1) {
        netID = tempConfigId;
    }

    boolean disconnect = wifi.disconnect();
    wifi.disableNetwork(id); //disable current network
    boolean enabled = wifi.enableNetwork(netID, true);
    boolean connected = wifi.reconnect();

if (((Build.VERSION.SDK_INT >= Build.VERSION_CODES.M))
                    || ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
                            && !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M))) {

                final ConnectivityManager manager = (ConnectivityManager) context
                        .getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkRequest.Builder builder;
                builder = new NetworkRequest.Builder();
                //set the transport type do WIFI
                builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);

                manager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() {
                    @Override
                    public void onAvailable(Network network) {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            manager.bindProcessToNetwork(network);
                        } else {
                            ConnectivityManager.setProcessDefaultNetwork(network);
                        }
                        try {
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        manager.unregisterNetworkCallback(this);
                    }
                });
            }

after connecting to the access point created by the device, it will constantly drop off from it.

Schargel answered 24/4, 2018 at 0:10 Comment(0)
L
1

Just wanted to add a bit to the discussion. I've been using bindProcessToNetwork for a while and it does fix the loss of WiFi when connected to one without a network as described by Shawn Chen. This is a heavy handed solution that makes it difficult to use Mobile network at the same time. However, the routing layer is rather broken on Android somewhere around 6 where they started forcing request to mobile even though the routing table indicates the wifi device.

Anyway, you can actually bind at a socket level which I describe below. This may help when the process has been bound to the WiFi network and you still want to use mobile. Instead of looking up WiFi (which is what I was experimenting with instead of binding the process), you look up the mobile 'Network' object and build a socket to it.

What we need is something that indicates to android not to drop the WiFi connection.

HttpUrlConnection doesn't allow you to get the socket so you can use okhttp to do it at the per-connection level. I'm using 2.7.5 of OkHttp but it is very similar for the 3+ version of OkHttp.

You get the current networks then process each to find WiFi network.

Network[] networks = connectivityManager.getAllNetworks();

Then you build the url like:

String url = "http://someurl";
HttpUrlConnection uconn = new OkUrlFactory( new OkHttpClient().setSocketFactory(network.getSocketFactory())).open(url)

This all works fine for a few connections and sometimes it works for the series of connections I used. Android is using the knowledge that activity is happening over the network but any pauses and it jumps back to using mobile. Android 9 wifi is just flawed and haven't figured out how to make it sticky using the socket solution. There may be one.

Langland answered 16/11, 2018 at 7:38 Comment(1)
on Android 9 i found out that the System Dialog WifiNoInternetDialog android.googlesource.com/platform/packages/apps/Settings/+/… can solve this Problem... but you can't open it without root, if you do you just get a SeuritiyException (as expected)Schonfeld

© 2022 - 2024 — McMap. All rights reserved.