furkanbzkurt
furkanbzkurt

Reputation: 356

Network connection check always return false for some Android devices

I am using this methods for check network connection but some users getting "no internet connection" error even they have connected to internet. Users reviewed with; Huawei Mate 10 Lite, LGE V20, Asus Zenfone, Samsung Galaxy A8

My methods:

private fun isConnectionOn(): Boolean {
    val connectivityManager =
        appContext.getSystemService(Context.CONNECTIVITY_SERVICE) as
                ConnectivityManager

    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        postAndroidMInternetCheck(connectivityManager)
    } else {
        preAndroidMInternetCheck(connectivityManager)
    }
}

@RequiresApi(Build.VERSION_CODES.M)
private fun postAndroidMInternetCheck(
    connectivityManager: ConnectivityManager
): Boolean {
    val network = connectivityManager.activeNetwork
    val connection =
        connectivityManager.getNetworkCapabilities(network)

    return connection != null && (
            connection.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
                    connection.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
}

private fun preAndroidMInternetCheck(
    connectivityManager: ConnectivityManager
): Boolean {
    val activeNetwork = connectivityManager.activeNetworkInfo
    if (activeNetwork != null) {
        return (activeNetwork.type == ConnectivityManager.TYPE_WIFI ||
                activeNetwork.type == ConnectivityManager.TYPE_MOBILE)
    }
    return false
}

Upvotes: 1

Views: 1592

Answers (1)

Always Learning
Always Learning

Reputation: 2713

Validating that you are connected to Wi-Fi or Cellular won't accurately tell you if you have internet connectivity. What if you drive through a tunnel with cellular? What if you connect to a captive portal over Wi-fi to which you don't have access to? You'll still return true in both of these cases even though you don't have internet connectivity. These are just a couple examples but point being, you shouldn't use transport to validate connectivity.

The two capabilities that you should use to validate connectivity would be NET_CAPABILITY_INTERNET and NET_CAPABILITY_VALIDATED.

NET_CAPABILITY_INTERNET Added in API level 21

public static final int NET_CAPABILITY_INTERNET Indicates that this network should be able to reach the internet.

NET_CAPABILITY_VALIDATED Added in API level 23

public static final int NET_CAPABILITY_VALIDATED Indicates that connectivity on this network was successfully validated. For example, for a network with NET_CAPABILITY_INTERNET, it means that Internet connectivity was successfully detected.

Therefore for Android >= M you could update your code like so:

return connection != null && (
            connection.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
                    connection.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))

For Android < M you should use either (based off of your use-case) NetworkInfo#isConnected() or NetworkInfo#isConnectedOrConnecting().

public boolean isConnected ()

Indicates whether network connectivity exists and it is possible to establish connections and pass data.

Always call this before attempting to perform data transactions.

Therefore for Android < M you could update your code like so:

if (activeNetwork != null) {
    return activeNetwork.isConnectedOrConnecting();
}

Upvotes: 3

Related Questions