How to check internet connection with GetActiveNetworkInfo?

If you are developing Android devices, you probably faced checking if a user has access to the Internet.

The general use case is when a user has access to the Internet you would call an API and update the local database, but if a user doesn’t have access to the Internet, you would skip the API call and read from the local database?

How does the Android app check Internet connection?

Google thought about that use case so they created the method inside Android framework getActiveNetworkInfo. With getActiveNetworkInfo, you can check if a device is connected to the network interface or not.

Easy, isn’t it? I just wrote this method and whether I have to check if I have to call an API or just load local data, I would call this method.

public static boolean isNetworkAvailable() {  
    ConnectivityManager connectivityManager 
          = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
    return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}

Does it always work? In most cases, yes, but let’s check what official documentation is saying.

Returns details about the currently active default data network. When connected, this network is the default route for outgoing connections. You should always check isConnected() before initiating network traffic. This may return null when there is no default network.

If we read that more carefully, we will see that this method tells us if the device is connected to the network interface. If the device is connected to the network interface, it does not mean the interface is connected to the internet (public network).

Note that having an active network interface doesn’t guarantee that a particular networked service is available. Network issues, server downtime, low signal, captive portals, content filters, and the like can all prevent your app from reaching a server. For instance, you can’t tell if your app can get Twitter until you receive a valid response from the Twitter service. Stack Overflow

This edge use case is often because the device is often connected to WIFI but without public internet access. So if you have a method for checking an internet connection before doing an API call, you will try to call the server because the device thinks it has an Internet connection.

On Stack Overflow, someone said you could ping Google DNS to ensure there is an Internet connection so the method would look like this.

public static boolean isNetworkAvailable () {

    Runtime runtime = Runtime.getRuntime();
    try {

        Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
        int     exitValue = ipProcess.waitFor();
        return (exitValue == 0);

    } catch (IOException e){
          e.printStackTrace();
    } catch (InterruptedException e){
          e.printStackTrace();
    }
    return false;
}

When you run a process within your app, you only are granting the app’s limited permissions to the process. So if ping requires root level permission (on the specific device), that may also be why it does not work. It is ultimately up to the OEM of how they customized Android. Stack Overflow

This method works, and it’s fast. The problem with it is that the process does not work on every device. On devices where the method does not work, it will return false, so we will think there is no Internet connection.

To avoid this problem we decide to write a method that will ping google via HttpURLConnection. That way it should work on every device:

public static boolean isNetworkAvailable () {  
    boolean success = false;
    try {
        URL url = new URL("https://google.com");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setConnectTimeout(10000);
        connection.connect();
        success = connection.getResponseCode() == 200;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return success;
}

With this approach, we still have one problem, which is not the same as in the method before, but the problem is the problem. Can you notice? If we call this, our method will fetch a full Google site, just to check for the connection. It’s not an efficient way, so we made a new one.

public static boolean isNetworkAvailable (Context context) {  
    if (connectedToTheNetwork(context)) {
        try {
            HttpURLConnection urlc = (HttpURLConnection) 
                (new URL("http://clients3.google.com/generate_204")
                .openConnection());
            urlc.setRequestProperty("User-Agent", "Android");
            urlc.setRequestProperty("Connection", "close");
            urlc.setConnectTimeout(1500); 
            urlc.connect();
            return (urlc.getResponseCode() == 204 &&
                        urlc.getContentLength() == 0);
        } catch (IOException e) {
            Log.e(TAG, "Error checking internet connection", e);
        }
    } else {
        Log.d(TAG, "No network available!");
    }
    return false;
}

Using the method above, we will not have to fetch the entire Google page so it’s much better than the method before.

This is a rewrite of my old article that I published on medium a few years ago. You can find it here: What if your Android user doesn’t have access to the Internet