On Android, 'Sign in to network' uses strange IP routing?

336 Views Asked by At

I am trying to have an IoT device (ESP32) use Wifi AP mode, so that I can connect my cellphone to it and visit a webpage hosted on the device in order to see some data.

By doing some DNS shenanigans, I do get the "Sign in to network" pop-up to appear.

When I tap on the 'sign in' popup, a page from my IoT device appears correctly.

If I use any regular browser to visit the devices IP, my phone refuses to connect.

If I disable mobile data, I can connect to my device using browsers.

It seems that Android refuses to route traffic to a wifi network that doesn't appear to offer internet connectivity.

I looked at the routing tables (ip route show table 0) and the default route does seem to be to my device, but all the browsers seem to ignore it.

I am assuming that this is some anti-spoofing protection against rogue wifi hotspots - but how does the webview in the 'sign in' popup circumvent this?

Would i have to hack together some custom webview wrapper in order to be able to connect to the IoT device (over a LAN IP over Wifi) and the internet (3G/4G) simultaneously?

I tried telling the IoT device to hand out 0.0.0.0 as the default gw, but this only had the effect of disabling the sign-in pop-up.

1

There are 1 best solutions below

3
Jeffrey Blattman On

Look into using ConnetivityManager.requestNetwork(). This allows you to bind a process to a particular network interface. Something like,

   NetworkRequest.Builder request = new NetworkRequest.Builder();
   request.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
   request.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);

   connectivityManager.requestNetwork(request.build(), ...);

Look at the docs, but the second argument is a callback for when the network is available. Something like,

        @Override
        public void onAvailable(Network network) {
            if (connectivityManager.bindProcessToNetwork(network)) {
                // success
            } else {
                // fail
            }
        }

Undo the binding with ConnectivityManager.unregisterNetworkCallback() and .bindProcessToNetwork(null). E.g.,

protected void releaseTransport() {
    if (requestTransportCallback != null) {
        connectivityManager.unregisterNetworkCallback(requestTransportCallback);
        requestTransportCallback = null;
        connectivityManager.bindProcessToNetwork(null);
    }
}

Good luck.