25

I have a question about android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET. According to the JavaDocs this "indicates that this network should be able to reach the internet".

Unfortunately this seems not to work properly - or I do something wrong here. I outputed the value of capabilities for three different Wi-Fi networks:

  1. A Wi-Fi with internet access.

  2. A Wi-Fi without internet access (I manually disabled the internet here).

  3. A public hotspot (the "Telekom" hotspot)

In all three cases the capabilities value is [ Transports: WIFI Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN LinkUpBandwidth>=1048576Kbps LinkDnBandwidth>=1048576Kbps].

This is my code:

ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
boolean capability = capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET

The boolean value is always true when connected with some Wi-Fi.

If it is relevant, the device I've tested is running under Android 5.0.1 (API 21). I compiled the app to API level 23.

Timo Bähr
  • 1,826
  • 2
  • 22
  • 26

2 Answers2

14

For devices with API 23+ you can check flag NET_CAPABILITY_VALIDATED

@RequiresApi(api = Build.VERSION_CODES.M)
private static boolean hasInternetConnectionM(final Context context) {
    final ConnectivityManager connectivityManager = (ConnectivityManager)context.
            getSystemService(Context.CONNECTIVITY_SERVICE);

    final Network network = connectivityManager.getActiveNetwork();
    final NetworkCapabilities capabilities = connectivityManager
            .getNetworkCapabilities(network);

    return capabilities != null
            && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
}

I check it on different devices and it works right. Except Xiaomi Redmi 3S MIUI 8 - it returns NET_CAPABILITY_VALIDATED for Wi-Fi without internet access.

For API < 23 I use ping.

EVIL SnaKe
  • 195
  • 1
  • 10
  • 3
    `capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)` returns true on an Android Wear API 26 emulator even when there is no Internet Connectivity. Is there any way to fix this? – Felipe Ribeiro R. Magalhaes Dec 11 '17 at 16:33
  • 5
    this doesn't work correctly when you switch from wifi to mobile data connection – Ultimo_m Jan 28 '19 at 14:11
  • @Ultimo_m I am using NetworkCapabilities.TRANSPORT_CELLULAR type check and then it works – Andris Feb 06 '20 at 09:10
  • This method seems to work reliably on the emulator even sitting behind a corporate proxy. If the proxy requires a new log in, this code will detect the issue and return false. I observed a bit of delay when this happens though. So, there is a little time window when the system thinks there is Internet, but there is not. To the best of my knowledge, if you need to know about Internet connectivity as soon as possible, then trying to check if a socket connection to a given IP (e.g. 8.8.8.8) is possible would be my recommendation, according to what I observed. – narko Feb 21 '20 at 10:35
  • checked this on Pixel 3 and also have NET_CAPABILITY_VALIDATED but failed with network request – Vadim Eksler Jun 09 '20 at 11:00
6

Unfortunately, you can't rely on NET_CAPABILITY_INTERNET && NET_CAPABILITY_VALIDATED, you can just turn off the internet on your wifi router (by cable or programatically) and check - both of those parameters will be true even after a long delay.

blinker
  • 599
  • 5
  • 18