How to use Java on an Android device to check internet access when the IP address never times out?

Networking in Android – Understanding Concepts

Android devices handle the network connectivity by using a set of APIs that enable the application to be constantly aware of, and react to, different types of network connectivity options such as Wi-Fi, cellular (3G, 4G, 5G), or VPN. During runtime, the device may switch between these networks dynamically, and developers should guarantee that applications handle such cases smoothly, for instance, when network is not available for certain moments.

How Android Handles Network Connectivity!

An Android device, at any one time, is constantly observing the state of network interfaces and provides the necessary mechanisms for applications to determine the currently active connectivity. Key concepts include the following:

  • Network interfaces: An Android device is generally equipped with various network interfaces, of which some are Wi-Fi, cellular, Bluetooth, etc.; the system automatically selects the network to be used based on availability or user preference.
  • Network Transitions: Android will automatically switch between Wi-Fi and mobile data depending on the signal strength, availability, and user preference to disable mobile data when on Wi-Fi.
  • Internet reachability check: Sometimes, even though the device is connected with a network, it may not necessarily mean the device has actual access to the Internet – for example, captive portal – so the application should always check both network availability and actual access to the Internet.

Android APIs for Monitoring Network Connectivity in Java

To be able to interact with network connectivity in Android, the developers may use various system services of the Android framework. The main component for this purpose would be a so-called ConnectivityManager, which allows developers to check the device’s current network state and whether or not internet access is available.

ConnectivityManager Role in Checking Network States

Central to monitoring network connectivity on an Android device is the ConnectivityManager class. In summary, this class has methods that can be used to query the status of the network-up or down, if the device is connected to a network, and what type of network Wi-Fi, mobile, etc., among others. Here is an overview of using it:

1. Accessing the ConnectivityManager

To check network connectivity, you need to get an instance of ConnectivityManager. This is typically done by calling the getSystemService() method, passing Context.CONNECTIVITY_SERVICE:

ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

2. Checking Network State with NetworkInfo

In older versions of Android (pre-Android 10), you could use the NetworkInfo class to check detailed information about the network state. The ConnectivityManager would provide a NetworkInfo object that represents the current network:

NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
    // The device is connected to a network (Wi-Fi or mobile data)
}

Here, isConnected() checks if the device is currently connected to an active network. The NetworkInfo object also provides information about the type of network (e.g., Wi-Fi, mobile, etc.) using methods like getType().

3. Checking Network State with Modern APIs (Network and NetworkCapabilities)

In Android 10 (API level 29) and later, NetworkInfo is deprecated in favor of more modern APIs like Network and NetworkCapabilities. You can now use Network objects to represent individual networks and NetworkCapabilities to get detailed information about network capabilities, such as whether the network has internet access.

Here’s an example using the modern APIs:

Network network = connectivityManager.getActiveNetwork();
NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(network);

if (networkCapabilities != null && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
    // The device has internet access
}

In this approach, hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) is used to check if the current network has internet connectivity, which provides a more reliable method than checking just the network connection.

4. Listening for Network Changes

To monitor network changes dynamically, you can register a BroadcastReceiver to listen for connectivity changes. However, in Android 7.0 (API level 24) and higher, you can use NetworkCallback with ConnectivityManager to get real-time updates on network connectivity:

ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

NetworkRequest networkRequest = new NetworkRequest.Builder()
    .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
    .build();

connectivityManager.registerNetworkCallback(networkRequest, new ConnectivityManager.NetworkCallback() {
    @Override
    public void onAvailable(Network network) {
        // Network is available, and internet access is confirmed
    }

    @Override
    public void onLost(Network network) {
        // Network is lost or no longer has internet access
    }
});

Checking for Internet Connectivity Using ConnectivityManager

The ConnectivityManager in Android is a system service that updates the application about the current network connections and their capabilities. As a developer, this class is used to identify whether or not a device is connected to a network, further to know if the network provides internet access.

Here’s how you can use ConnectivityManager to check both network and internet connectivity on Android. We will explore two approaches:

  1. Using deprecated methods (NetworkInfo) for older Android versions.
  2. Using the more modern APIs (Network and NetworkCapabilities) for Android 10 (API level 29) and later.

1. Using Deprecated NetworkInfo API (Pre-Android 10)

In older Android versions, the NetworkInfo class was used to get information about network connections. Here’s how to use NetworkInfo to check whether the device is connected to any network.

// Import necessary classes
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.content.Context;

public boolean isNetworkAvailable(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();

    // Check if any network is connected
    return networkInfo != null && networkInfo.isConnected();
}

Explanation:

  • getActiveNetworkInfo() This method returns a NetworkInfo object representing the currently active default network.
  • isConnected() checks if the device is connected to any network, be it Wi-Fi, mobile data, etc.
  • This approach does not check whether the network the device is connected to actually has access to the internet.

Extra: Dynamic Network-Change Listening

If you want to dynamically monitor the network changes, you can register a NetworkCallback – for it to notify you when the state of the network changes. Here’s how you can do it:

import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.content.Context;

public void monitorNetworkChanges(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

    // Build a network request to monitor internet capability
    NetworkRequest networkRequest = new NetworkRequest.Builder()
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            .build();

    // Register the network callback to listen for network changes
    connectivityManager.registerNetworkCallback(networkRequest, new ConnectivityManager.NetworkCallback() {
        @Override
        public void onAvailable(Network network) {
            // Internet is available
            System.out.println("Network is available with internet access");
        }

        @Override
        public void onLost(Network network) {
            // Network is lost or no longer has internet
            System.out.println("Network lost or no internet access");
        }
    });
}

Explanation:

  • A NetworkRequest is built with filtering on networks that have internet capability; i.e., NET_CAPABILITY_INTERNET.
  • The registerNetworkCallback() registers a NetworkCallback that gets called when the network becomes available, or is lost.
  • The onAvailable() and onLost() methods would be called once the network has changed, hence the app can now react dynamically to connectivity changes.

Sample Java Code for Determining Network Accessibility

You would check for internet connectivity in an Android application that uses Java by trying to perform a connection to an external resource – either via the HttpURLConnection or URL class. This will make sure that the network is not just available but also connected to the internet. Below is how you do it with both approaches:

1.Basic Internet Access Using HttpURLConnection

The code below tries to check whether there is an internet access using the HttpURLConnection class by calling the connect method to some address that is known to exist, such as Google’s homepage:

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

public class NetworkUtils {

    // Method to check if internet is available by connecting to a server
    public static boolean isInternetAvailable() {
        try {
            // Specify the URL of a reliable external server
            URL url = new URL("http://www.google.com");
            
            // Open a connection to the URL
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            
            // Set a timeout for establishing the connection
            urlConnection.setConnectTimeout(5000); // 5 seconds
            
            // Attempt to connect
            urlConnection.connect();
            
            // Check for successful HTTP response code (200 OK)
            if (urlConnection.getResponseCode() == 200) {
                return true; // Internet is available
            } else {
                return false; // No internet access
            }
        } catch (IOException e) {
            // Exception occurred, likely indicating no internet access
            e.printStackTrace();
            return false;
        }
    }
}

How It Works:

  • The method attempts to connect to http://www.google.com.
  • A connection timeout of 5 seconds is set to prevent waiting indefinitely for a response.
  • If the response code is 200 (HTTP OK), it means the internet is accessible.

Considerations:

  • You can choose any reliable server to test the connection, such as your own backend server or other trusted services.
  • Make sure that the URL you’re connecting to supports HTTP or HTTPS and is highly available.

2. Using the URL Class for a Simple Connectivity Check

This example uses the URL class and performs a small resource fetch, typically preferred when you want to check for connectivity in the simplest way without worrying about specific HTTP status codes.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;

public class NetworkCheck {

    public static boolean isInternetAvailable() {
        try {
            // Create a URL object with the target resource
            URL url = new URL("http://www.google.com");

            // Open a connection to the URL
            URLConnection connection = url.openConnection();
            
            // Set a timeout for the connection (in milliseconds)
            connection.setConnectTimeout(5000); // 5 seconds

            // Fetch the input stream from the connection
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));

            // Read the response (we only need to check if we can read data)
            String inputLine;
            StringBuilder response = new StringBuilder();
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }

            in.close(); // Close the input stream
            return true; // Internet is available
        } catch (IOException e) {
            // If any error occurs (likely no internet), return false
            e.printStackTrace();
            return false;
        }
    }
}

3. Pinging an External IP (Optional Alternative)

Pinging an external server can sometimes be a lightweight option. However, keep in mind that ICMP (ping) traffic may be blocked on some networks, which could lead to false negatives. Here’s an example:

import java.io.IOException;

public class PingCheck {

    public static boolean isInternetAvailable() {
        try {
            // Execute the ping command to Google's DNS server
            Process process = Runtime.getRuntime().exec("/system/bin/ping -c 1 8.8.8.8");

            // Wait for the ping process to finish
            int returnVal = process.waitFor();
            
            // Check if the ping was successful
            return (returnVal == 0); // 0 means success
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
            return false; // Failure indicates no internet
        }
    }
}

How It Works:

  • The method runs the ping command to Google‘s DNS server (8.8.8.8).
  • If the ping command succeeds (returns 0), the internet is available.
  • However, this approach might not work if ICMP traffic is blocked or restricted.

Discussion: HttpURLConnection vs Ping

HttpURLConnection/URL Advantages:

  • More reliable for checking if actual data can be transmitted, not just network availability.
  • HTTP-based checks are more robust in real-world usage, especially in cases like mobile data or restricted networks.

Ping Method:

  • A quick, lightweight method but can be unreliable due to network restrictions.
  • Some networks may block ICMP (ping) traffic, leading to false negatives.

Determination of Active Internet Connection with NetworkCapabilities

The Android class NetworkCapabilities provides a better way to determine whether internet access is available. Mere checking if a device is connected to a network is not good enough to ensure real internet connectivity because the device may be connected to a local network without real internet connectivity-for example, captive portals or firewalled networks. Using NetworkCapabilities, you are now able to validate the network connection and further verify that the network can access the internet.

How to Check for Internet Access:

  • Connectivity: Permit the app to check the network connectivity via ConnectivityManager as to what is the active network.
  • Capability Check: From getting the active network, fetch its NetworkCapabilities and check for internet capability.

Code Example:

Here’s a Java code example for checking whether the device has an active network with internet access using NetworkCapabilities.

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;

public class NetworkUtils {

    public static boolean isInternetAvailable(Context context) {
        // Get ConnectivityManager from system services
        ConnectivityManager connectivityManager = 
            (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

        // Get the current active network
        Network activeNetwork = connectivityManager.getActiveNetwork();

        if (activeNetwork != null) {
            // Get the capabilities of the active network
            NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(activeNetwork);

            // Check if the network has internet capability
            return networkCapabilities != null &&
                   networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
        }

        return false; // No active network
    }
}

Explanation:

(I) ConnectivityManager:

  • This system service provides access to the current network connection status of the device.
  • The getActiveNetwork() method retrieves the currently active network.

(II)NetworkCapabilities:

  • Represents the capabilities of the active network. You can check whether the network supports different features, like internet access, Wi-Fi, or cellular data.
  • The hasCapability() method checks if the network has a specific capability, like NET_CAPABILITY_INTERNET to confirm if the active network supports internet access.

Dealing with “No Timeout”:

The fact that an IP address never times out creates an illusion in that it is technically connected to a network, but there is no actual access to the internet. Such situations may arise when one is connected to a router without access to the internet or in a captive portal, where all traffic is routed so that authentication can be made. Here is how you will handle such scenarios:

1. Ping a Known External Server:

One common approach is to ping a well-known, reliable server, like Google DNS at 8.8.8.8, or any other trusted service that has a good uptime record. This check ensures that the device is not just connected to a local network but also has access to the internet.

Java Code Example:

public boolean isInternetAvailable() {
    try {
        // Ping Google DNS server
        Process process = Runtime.getRuntime().exec("/system/bin/ping -c 1 8.8.8.8");
        int returnVal = process.waitFor();
        return (returnVal == 0); // 0 indicates success
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}

Drawbacks:

  • Pinging IP addresses might still not guarantee full internet access.
  • Some networks may block ICMP traffic (ping), which could result in false negatives.

2. HTTP Request to a Small Resource:

Rather than depend on pings that may be blocked or otherwise unreliable, do an HTTP request to download a small file at a known URL; at least this would prove that actual data is being transmitted across a network.

Java Code Example:

public boolean isInternetAvailable() {
    try {
        URL url = new URL("http://www.google.com"); // or any reliable external server
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setConnectTimeout(5000); // Set a timeout in case of no response
        urlConnection.connect();
        int responseCode = urlConnection.getResponseCode();
        return (responseCode == 200); // HTTP_OK
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}

Advantages:

  • This method ensures that data is flowing to/from the internet, not just a connection to the local network.
  • More reliable than pinging, especially for Android apps where you want to ensure the app has proper connectivity before making API calls.

3. Check Captive Portal Status:

Android has built-in detection for captive portals (networks that require authentication). You can leverage the NetworkCapabilities class to detect this.

ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
Network network = connectivityManager.getActiveNetwork();
NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);

boolean isCaptivePortal = capabilities != null && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);

If a captive portal is detected, you can prompt the user to authenticate.

4. Specify Custom Timeout for IP Connection:

You can, in the case of an IP address that never times out-say, a local router-set a timeout to connect so that after a certain amount of time it will fail, rather than you waiting forever.

public boolean isReachable(String ipAddress, int timeout) {
    try {
        InetAddress inetAddress = InetAddress.getByName(ipAddress);
        return inetAddress.isReachable(timeout); // Specify the timeout in milliseconds
    } catch (IOException e) {
        e.printStackTrace();
    }
    return false;
}

5. Using NetworkCapabilities for Precise Network State:

The Android API provides the NetworkCapabilities class to check if the current network supports internet connectivity, rather than simply checking if a network is present.

ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
Network activeNetwork = cm.getActiveNetwork();
NetworkCapabilities nc = cm.getNetworkCapabilities(activeNetwork);

boolean hasInternet = nc != null && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);

This method helps confirm the device’s ability to access the internet, even when the IP doesn’t timeout.

In Conclusion:

When one IP address never times out, it may cause problems with determining actual internet access. Solutions like pinging external servers, performing small HTTP requests, and using Android’s NetworkCapabilities class can assist in making the checks for internet connectivity in your Java-based Android application sound.

Share The Tutorial With Your Friends
Twiter
Facebook
LinkedIn
Email
WhatsApp
Skype
Reddit

Check Our Ebook for This Online Course

Advanced topics are covered in this ebook with many practical examples.