Skip to content

Instantly share code, notes, and snippets.

@Farbklex
Created February 18, 2020 13:27
Show Gist options
  • Save Farbklex/f84029889444ee9c52a331a7e2bd10d2 to your computer and use it in GitHub Desktop.
Save Farbklex/f84029889444ee9c52a331a7e2bd10d2 to your computer and use it in GitHub Desktop.
Android: Check if the device has internet access on devices with API level >= 23.
package me.a_hoffmann.gists
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
/**
* Checks if the device has an internet connection.
* NOTE: Works only on android API level 23 and above!
*/
class ConnectivityChecker(private val context: Context){
/**
* Check if the device has an internet connection.
*
* @return True if the device is connected to a network which also gives it access to the internet.
* False otherwise.
*/
fun isInternetAvailable(): Boolean {
val connectivityManager = context.getSystemService(
Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
?: return false
val activeNetwork = connectivityManager.activeNetwork ?: return false
val capabilities = connectivityManager.getNetworkCapabilities(activeNetwork) ?: return false
// If we check only for "NET_CAPABILITY_INTERNET", we get "true" if we are connected to a wifi
// which has no access to the internet. "NET_CAPABILITY_VALIDATED" also verifies that we
// are online
return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
&& capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
}
}
@ArjixWasTaken
Copy link

ArjixWasTaken commented Apr 6, 2023

Here is what I wrote as a util

suspend fun isDnsResolvable(): Boolean {
    return withContext(Dispatchers.IO) {
        try {
            /*
                www.msftconnecttest.com is what windows uses to determine if a network is connected to the internet
                to be fair, windows requests for http://www.msftconnecttest.com/connecttest.txt and checks the content
                but a simple DNS lookup is enough for us, me thinks :^)
            */
            val address = InetAddress.getByName("www.msftconnecttest.com")
            !address.hostAddress.isNullOrEmpty()
        } catch (e: UnknownHostException) {
            false
        }
    }
}

suspend fun hasNetwork(context: Context): Boolean {
    val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

    val network = connectivityManager.activeNetwork ?: return false
    val activeNetwork = connectivityManager.getNetworkCapabilities(network) ?: return false

    return activeNetwork.hasCapability(NET_CAPABILITY_VALIDATED) && isDnsResolvable()
}

I recommend using kotlinx.coroutines.flow.flow to check at an interval. (The network listener is not reliable)

var connectedToInternet = false;

flow {
    while (true) {
        if (connectedToInternet) {
            delay(4.seconds)
        } else {
            delay(1.seconds)
        }

        connectedToInternet = hasNetwork(this@MainActivity)
        delay(1.seconds)
        emit(Unit)
    }
}.launchIn(scope)

Taken from here.

You might want to use this for notifying the user about the network connectivity just like YouTube and TikTok do

@iabhijeet08
Copy link

iabhijeet08 commented Feb 5, 2024

private boolean hasNetworkCapability(NetworkCapabilities networkCapabilities) {
   boolean hasCapability = false;

   /*
   if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
      hasCapability =  networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)       // API >= 21
                   &&  networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)      // API >= 23
                   && (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)  // API >= 28
                   ||  networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOREGROUND));   // API >= 28

don't we need both network not suspended as well as foreground network is available for use by apps?

   } else if (android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.M) {
      hasCapability = networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)        // API >= 21
                   && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);      // API >= 23
   } else if (android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
      hasCapability = networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);       // API >= 21
   }

   return hasCapability;
   */

   if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      hasCapability = networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);

      if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
         hasCapability = hasCapability || networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
      }
   }

   return hasCapability;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment