Explain Codes LogoExplain Codes Logo

How to check internet access on Android? InetAddress never times out

android
connectivity-check
network-programming
async-programming
Nikita BarsukovbyNikita BarsukovΒ·Aug 31, 2024
⚑TLDR

Swiftly determinate if your Android device has internet access by executing the ConnectivityManager for a network connection inspection and confirming real internet connectivity via an HTTP request.

Unfolded code snippet:

// Step 1: Get the ConnectivityManager ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); // Step 2: Is there a connection? boolean isConnected = cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnected(); // Step 3: If connected, let's hit Google for a swift and reliable check if (isConnected) { try { // Creating a friendly HTTP handshake with Google HttpURLConnection urlc = (HttpURLConnection) (new URL("http://clients3.google.com/generate_204").openConnection()); // We're in a hurry, so let's timeout after 1 second urlc.setConnectTimeout(1000); // TODO: Increase if you're on a snail network 🐌 urlc.connect(); // If Google sends back a lovely 204 and no content, we're onto a winner! return urlc.getResponseCode() == 204 && urlc.getContentLength() == 0; } catch (IOException e) { // Oopsie! Handle the exception here } } // Looks like we're not online. Bummer! return false;

This non-UI blocking approach is more than simply checking if you are connected to a network, it actually checks if the internet is truly reachable.

Shaking hands with ConnectivityManager

The downfalls of the often unreliable InetAddress.isReachable are well documented and it's time to shift towards more dependable options. For efficiently checking connectivity, ConnectivityManager proves to be a better friend.

The sock(et) to Google DNS trick

One robust method you can implement is by leveraging the Socket class and attempting a real Internet connection to a reliable DNS server, such as Google's 8.8.8.8 on port 53. A real connection speaks more volume about internet connectivity than a true return from isConnected().

AsyncTask disambiguation

AsyncTask being deprecated in API level 30, you're now better off embracing alternatives like Kotlin Coroutines or RxJava that are designed to handle tasks asynchronously more efficiently.

Why InetAddress.isReachable is a false god

While InetAddress.isReachable may seem like a handy way to check internet access, it often fails due to reasons such as firewalls disallowing ICMP packets and default timeout being too lengthy, leading to a sluggish user experience.

Guidelines for handling the unexpected

The landscape of network conditions can be diverse and unpredictable. Here's how you can gear up for varying connectivity scenarios:

  • Multiple network types: Diversify your tests to include ConnectivityManager.TYPE_MOBILE/WIFI for a comprehensive internet connectivity check.
  • Zero signal zones: Take care of a scenario where there's a connection but no internet access, by cross-verifying via HTTP requests to dependable endpoints like Google's generate_204 marketing endpoint.
  • Handling UI freeze: Always keep your eye on the main UI thread and avoid heavy operations that could lead it to become unresponsive. This especially holds true when dealing with socket connections.

Oozing future readiness

Keeping up-to-date with current technology trends and future-proofing your solutions is the name of the game in the world of software development:

  • Stay API-wise: Remember, different Android versions may have different API limitations and capabilities, code defensively for a wider audience.
  • Library love: Libraries like Volley or OkHttp make networking tasks a breeze providing sophisticated features like auto retries, caching, and timeout failovers.
  • Asynchronous allure: Leverage from modern asynchronous programming models to keep your app responsive even during network operations.