Android - Detect if Wifi Requires Browser Login

2019-02-03 05:21发布

问题:

My university has an open wifi access point, however it requires you to enter your e-mail before it allows you to use the web. My problem is that the Wifi is stupid in that it seems to drop my connection and force me to enter my e-mail again every 10 minutes.

I wanted to create my own app that I can use to automatically do this step for me, but I cannot seem to find any documentation for a nice and easy way to detect if a Wifi access point has a browser login page. Is there a way in Android to get this information, or is it just to see if my connection to something is always redirected to 1.1.1.1?

回答1:

See the "Handling Network Sign-On" section of the HttpUrlConnection documentation:

Some Wi-Fi networks block Internet access until the user clicks through a sign-on page. Such sign-on pages are typically presented by using HTTP redirects. You can use getURL() to test if your connection has been unexpectedly redirected. This check is not valid until after the response headers have been received, which you can trigger by calling getHeaderFields() or getInputStream().

They have a snippet of sample code there. Whether this will cover your particular WiFi AP, I can't say, but it is worth a shot.



回答2:

Ping an external IP address (like google.com) to see if it responds.

    try {
        Runtime runtime = Runtime.getRuntime();
        Process proc = runtime.exec("ping -c 1 " + "google.com");
        proc.waitFor();     
        int exitCode = proc.exitValue();
        if(exitCode == 0) {
            Log.d("Ping", "Ping successful!";
        } else {
            Log.d("Ping", "Ping unsuccessful.");
        }
    } 
    catch (IOException e) {}
    catch (InterruptedException e) {}

The only downside is this would also indicate that a web login is required when there is simply no internet connectivity on the WiFi access point.

@CommonsWare I believe this is a better answer than opening a UrlConnection and checking the host, since the host doesn't always change even when displaying the redirect page. For example, I tested on a Belkin router and it leaves whatever you typed in the browser as is, but still displays its own page. urlConnection.getUrl().getHost() returns what it should because of this.



回答3:

I think @FlyWheel is on the right path, but I would use http://clients1.google.com/generate_204 and if you don't get a 204, you know you are behind a captive portal. You can run this in a loop until you do get a 204 in which case you know you are not behind a captive portal anymore.

@FlyWheel wrote: The only downside is this would also indicate that a web login is required when there is simply no internet connectivity on the WiFi access point.

You can solve this by registering a receiver to android.net.conn.CONNECTIVITY_CHANGE. You can check if Wifi is ON and is connected by looking at the Supplicant State of the connection.

Here is a snippet, but I didn't run it:

WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wm.getConnectionInfo();
SupplicantState suppState = wifiInfo.getSupplicantState();

if (wm.isWifiEnabled()) {
   if (suppState == SupplicantState.COMPLETED){
      // TODO - while loop checking generate_204 (FlyWheels code)Using intent service.
   }
}

I can't remember if the SupplicantState is COMPLETED or ASSOCIATED, you will have to check that. You should use an IntentService for checking the generate_204 since broadcast receivers have a short lifetime.



回答4:

The issue might rather be - today at least - that newer Android versions (5.1+?) keep the 3G/4G connection up and running until the wifi login actually leads to a fully functional wifi connection.

I haven't tried it, but maybe with the enum value CAPTIVE_PORTAL_CHECK of NetworkInfos DetailedState one can try to detect such a mode properly?