android – How to know the connected WiFi is Walled Gardened (Captive Portal)?-ThrowExceptions

Exception or error:

I know there is way to find out whether a WiFi network is a captive portal by checking the response of something like "http://clients3.google.com/generate_204".

But my question is somewhat different. We all know that on Android when we connect to a WiFi network the connection cycle goes through a number of state mentioned in the class NetworkInfo.DetailedState, like AUTHENTICATING, OBTAINING_IPADDR, VERIFYING_POOR_LINK etc. Also, one of the states is CAPTIVE_PORTAL_CHECK and android system check whether the network which is being connected is captive or not. For this Android uses the CaptivePortalTracker#isCaptivePortal(InetAddress server) which results in a boolean. So we are certain that Android knows whether the connection is restricted (captive) or not

So, my question is does Android system gives some callback or some state by which we can get to know the Network is captive portal without checking it manually? Since Android system have already checked the network for captive portal, do we need to do the same thing again?

P.S. I’m only targeting API 19 (KitKat 4.4.2).

How to solve:

You can get the networkcapabilities from the network and check if it has the NET_CAPABILITY_CAPTIVE_PORTAL :

API 23

ConnectivityManager connectivityManager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
Network activeNetwork=connectivityManager.getActiveNetwork();
NetworkCapabilities networkCapabilities=connectivityManager.getNetworkCapabilities(activeNetwork);
if(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)){
        //DO SOMETHING
}

http://developer.android.com/intl/es/reference/android/net/NetworkCapabilities.html

NetworkCapabilities was introduced in API 21, so you can do this for

API >= 21

ConnectivityManager connectivityManager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
Network[] activeNetworks=connectivityManager.getAllNetworks();
for(Network network:activeNetworks){
    if(connectivityManager.getNetworkInfo(network).isConnected()){
        NetworkCapabilities networkCapabilities=connectivityManager.getNetworkCapabilities(network);
        if(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)){
           //DO SOMETHING
        }
        break;
    }
}

###

Might be late to the party. But If the documentations hold correct then there is a way to detect captive portal from connectivityManager. https://developer.android.com/reference/android/net/NetworkInfo.DetailedState.html#CAPTIVE_PORTAL_CHECK

ConnectivityManager connectivityManager
                = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
NetworkInfo.DetailedState detailedState = activeNetworkInfo.getDetailedState();
return detailedState == NetworkInfo.DetailedState.CAPTIVE_PORTAL_CHECK;

PS: This is deprecated in API 29

Leave a Reply

Your email address will not be published. Required fields are marked *