18

According to the Android developer site, Determining and Monitoring the Connectivity Status, we can check there is an active Internet connection. But this is not working if even only Wi-Fi is connected and not Internet available (it notifies there is an Internet connection).

Now I ping a website and check whether Internet connections are available or not. And this method needs some more processing time. Is there a better method for checking Internet connectivity than this to avoid the time delay in ping the address?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rohith Krishnan
  • 648
  • 8
  • 29
  • Sorry but it is working with Wifi too. Many developers are using this but still no issue. Even I am using the same function since many years and I am not facing any issue with WIFI or Mobile Data connection for internet connectivity. – Andy Developer Jul 05 '17 at 06:32
  • 1
    Yes I am also using same method i.e ping google to check internet connectivity and yes it takes some time, but I think its the only solution we have got at the moment. – Abdul Kawee Jul 05 '17 at 06:38
  • @AbdulKawee I am fully agree with you. – Andy Developer Jul 05 '17 at 06:43
  • 1
    But on the device, we can see (in wifi settings) there is no internet text if there is no internet connection in wifi. Is there any possibility to get that data.Currently, i am checking the GitHub code for wifi settings :) – Rohith Krishnan Jul 05 '17 at 06:50
  • @RohithKrishnan can you share the link? – Abdul Kawee Jul 05 '17 at 06:58
  • @Abdul Kawee Please find the link https://github.com/android/platform_packages_apps_settings/tree/nougat-release . But no luck Google also check connectivity by ping the google.com :) – Rohith Krishnan Jul 05 '17 at 07:01
  • https://stackoverflow.com/a/44919025/4407531 – Ashish Rathee Jul 05 '17 at 07:01
  • 2
    FYI simply pinging Google/Google DNS can result in false positive if the phone is connected to office/hotel/cafe guest wifi where all request are redirected to portal login. A more robust way is to use [Microsoft's NCSI](http://blog.superuser.com/2011/05/16/windows-7-network-awareness/) where you can tell if there's actual internet connection as opposed to portal login page. So either do a dns lookup for dns.msftncsi.com, verify it's 131.107.255.255 or download the www.msftncsi.com and verify you get a text file containing "Microsoft NCSI" – Martheen Jul 05 '17 at 07:57
  • I truly fear the day when some popular address people use for connectivity checks will change... – Florian Castellane Jul 05 '17 at 09:22
  • @Dmitry Grigoryev, I Asked for a better method to overcome the delay in ping the address, the link you provided is too old so added this question to check whether any new methods are there. – Rohith Krishnan Jul 05 '17 at 10:09

10 Answers10

10

Try this:

It's really simple and fast:

public boolean isInternetAvailable(String address, int port, int timeoutMs) {
    try {
        Socket sock = new Socket();
        SocketAddress sockaddr = new InetSocketAddress(address, port);

        sock.connect(sockaddr, timeoutMs); // This will block no more than timeoutMs
        sock.close();

        return true;

    } catch (IOException e) { return false; }
}

Then wherever you want to check just use this:

if (isInternetAvailable("8.8.8.8", 53, 1000)) {
     // Internet available, do something
} else {
     // Internet not available
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
sumit
  • 1,047
  • 1
  • 10
  • 15
  • 3
    Why would you check the availability of Google DNS rather than the actual site you want to interact with? Also, the OP claim they already do this, and are looking for a better method. – Dmitry Grigoryev Jul 05 '17 at 09:18
  • 1
    that's because this way it'll be fast. the actual site might be slow due to heavy traffic sometimes. – sumit Jul 05 '17 at 09:21
  • 3
    If the actual site is slow or unresponsive, the code interacting with it will be slow or unresponsive as well, even if the connectivity check is fast. – Dmitry Grigoryev Jul 05 '17 at 09:26
  • 2
    nop the problem of the user was just to check whether Internet is available or not and that too quickly. As he has mentioned in the question he was also pinging the actual site but that method was slow. I provided the solution just to check whether internet is available or not. – sumit Jul 05 '17 at 09:30
  • 2
    You forgot to close your socket in an error condition, if you code like that, you will get risks of running out of file descriptors – Ferrybig Jul 05 '17 at 10:29
  • @Dmitry Grigoryev . I think that this method is a bit faster than ping a web site :) and this thing suits for my requirement. – Rohith Krishnan Jul 06 '17 at 07:01
  • Thanks sumit , your code is faster than that of normal ping of websites – Rohith Krishnan Jul 06 '17 at 09:45
4

Try the following:

public boolean checkOnlineState() {
    ConnectivityManager CManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo NInfo = CManager.getActiveNetworkInfo();
    if (NInfo != null && NInfo.isConnectedOrConnecting()) {
        return true;
    }
    return false;
}

Don't forget the access:

 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Else:

if (InetAddress.getByName("www.google.com").isReachable(timeout))
{    }
else
{    }
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Atlas_Gondal
  • 2,512
  • 2
  • 15
  • 25
4

The first problem you should make it clear is what do you mean by whether internet is available?

  • Not connected to wifi or cellular network;
  • Connected to a limited wifi: e.g. In a school network, if you connect to school wifi, you can access intranet directly. But you have to log in with school account to access extranet. In this case, if you ping extranet website, you may receive response because some intranet made auto redirect to login page;
  • Connected to unlimited wifi: you are free to access most websites;

The second problem is what do you want to achieve?

As far as I understand your description, you seems want to test the connection of network and remind user if it fails. So I recommend you just ping your server, which is always fine if you want to exchange data with it.


You wonder whether there is a better way to test connectivity, and the answer is no.

The current TCP/IP network is virtual circuit, packet-switched network, which means there is no a fixed 'path' for the data to run, i.e. not like a telephone, we have a real connection between two users, we can know the connection is lost immediately after circuit is broken. We have to send a packet to the destination, and find no response, then we know, we lose the connection (which is what ping -- ICMP protocol -- does).

In conclusion, we have no better way to test the connectivity to a host other than ping it, that is why heartbeat is used in service management.

Tony
  • 5,972
  • 2
  • 39
  • 58
2

On checking this issue it found that We cannot determine whether an active internet connection is there, by using the method specified in the developer site: https://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html

This will only check whther ther active connection of wifi.

So I found 2 methods which will check whether there is an active internet connection

1.Ping a website using below method

URL url = new URL(myUrl);
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
        // 30 second time out.
        httpURLConnection.setConnectTimeout(30000);
        httpURLConnection.connect();
        if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
            isAvailable = true;
        }

2.Check the availability of Google DNS using socket

  try {
        Socket sock = new Socket();
        SocketAddress sockaddr = new InetSocketAddress("8.8.8.8", 53);

        sock.connect(sockaddr, 1000); // this will block no more than timeoutMs
        sock.close();

        return true;
} 

The second method is little faster than 2nd method (Which suits for my requirement)

Thanks all for the answers and support.

Rohith Krishnan
  • 648
  • 8
  • 29
2

I wanted to comment, but not enough reputation :/

Anyways, an issue with the accepted answer is it doesn't catch a SocketTimeoutException, which I've seen in the wild (Android) that causes crashes.

public boolean isInternetAvailable(String address, int port, int timeoutMs) {
    try {
        Socket sock = new Socket();
        SocketAddress sockaddr = new InetSocketAddress(address, port);

        sock.connect(sockaddr, timeoutMs); // This will block no more than timeoutMs
        sock.close();

        return true;

    } catch (IOException e) { 
        return false; 
    } catch (SocketTimeoutException e) {
        return false;
    }
}
2

//***To verify internet access

public static Boolean isOnline(){

    boolean isAvailable = false;
    try {

        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
        URL url = new URL("https://stackoverflow.com/");
        HttpURLConnection httpURLConnection = null;
        httpURLConnection = (HttpURLConnection) url.openConnection();

        // 2 second time out.
        httpURLConnection.setConnectTimeout(2000);
        httpURLConnection.connect();
        if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
            isAvailable = true;
        } else {
            isAvailable = false;
        }
    } catch (IOException e) {
        e.printStackTrace();
        isAvailable = false;
    }

    if (isAvailable){
        return true;
    }else {
        return false;
    }
}
1

Maybe this can help you:

private boolean checkInternetConnection() {
        ConnectivityManager cm = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
        // Test for connection
        if (cm.getActiveNetworkInfo() != null
            && cm.getActiveNetworkInfo().isAvailable()
            && cm.getActiveNetworkInfo().isConnected()) {
        return true;
    } 
    else {
        return false;
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
callmejeevan
  • 1,040
  • 1
  • 9
  • 18
  • 2
    This will only tell that there's a working active connection (wifi/mobile data), but not whether that connection actually provide internet access. It could be connected to a router without ISP connection, mobile data with no data credit, hotel wifi with no valid credential, restricted school/office lan, etc – Martheen Jul 05 '17 at 07:53
  • Then you should make an HTTP request either using volley or any other way and handle the response based on the response you check whether network is available or not. – callmejeevan Jul 05 '17 at 08:20
1

Try this method, this will help you:

public static boolean isNetworkConnected(Context context)
{
    ConnectivityManager connectivityManager = (ConnectivityManager)
            context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (connectivityManager != null)
    {
        NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
        if (netInfo != null && netInfo.isConnected())
        {
            return true;
        }
    }
    return false;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
vikas singh
  • 241
  • 1
  • 10
  • 10
    You didn't get his point, this method will return `true` when WI-FI is connected with no internet connectivity i.e even on a Limited connection. Read Question carefully – Abdul Kawee Jul 05 '17 at 06:36
1

You can try this for check Internet connectivity:

/**
 * Check Connectivity of network.
 */
public static boolean isOnline(Context context) {
    try {
        if (context == null)
            return false;

        ConnectivityManager cm = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);

        if (cm != null) {
            if (cm.getActiveNetworkInfo() != null) {
                return cm.getActiveNetworkInfo().isConnected();
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
    catch (Exception e) {
        Log.error("Exception", e);
        return false;
    }
}

In your activity you call this function like this.

if(YourClass.isOnline(context))
{
  // Do your stuff here.
}
else
{
  // Show alert, no Internet connection.
}

Don't forget to add ACCESS_NETWORK_STATE PERMISSION:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Try this if you want to just ping the URL:

public static boolean isPingAvailable(String myUrl) {
    boolean isAvailable = false;
    try {
        URL url = new URL(myUrl);
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
        // 30 second time out.
        httpURLConnection.setConnectTimeout(30000);
        httpURLConnection.connect();
        if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
            isAvailable = true;
        }
    } catch (Exception e) {
        isAvailable = false;
        e.printStackTrace();
    }
    return isAvailable;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Andy Developer
  • 3,071
  • 1
  • 19
  • 39
1

ConnectivityManager will not be able to tell you if you have active connection on WIFI.

The only option to check if we have active Internet connection is to ping the URL. But you don't need to do that with every HTTP request you made from your App.

What you can do:

  1. Use below code to check connectivity

    private boolean checkInternetConnection()
    {
        ConnectivityManager cm = (ConnectivityManager) 
        getSystemService(Context.CONNECTIVITY_SERVICE);
        // test for connection
        if (cm.getActiveNetworkInfo() != null
            && cm.getActiveNetworkInfo().isAvailable()
            && cm.getActiveNetworkInfo().isConnected())
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    
  2. And while making rest call using HTTP client set timeout like 10 seconds. If you don't get response in 10 seconds means you donot have active internet connection and exception will be thrown (Mostly you get response within 10 seconds). No need to check active connection by pinging everytime (if you are not making Chat or VOIP app)

Andy Developer
  • 3,071
  • 1
  • 19
  • 39
Ashish Rathee
  • 449
  • 3
  • 16