27

Ive been trying to do what i thought would be a simple reachability of host test at the beginning of my apps internet ventures, but documentation isnt helping and neither are examples found at various places, ive tried many solutions with no luck, so if anyone could point me in the direction of a definitive way to check a hosts availability with android that be awesome, just need it to toggle a bool to true if the host can be reached

im using API8 if that makes much difference to this process, and must cater for non-rooted devices so the inetaddress.isReachable is out

fury-s12
  • 1,240
  • 3
  • 12
  • 18

4 Answers4

59

It's not pretty but this is how I did it:

boolean exists = false;

try {
    SocketAddress sockaddr = new InetSocketAddress(ip, port);
    // Create an unbound socket
    Socket sock = new Socket();

    // This method will block no more than timeoutMs.
    // If the timeout occurs, SocketTimeoutException is thrown.
    int timeoutMs = 2000;   // 2 seconds
    sock.connect(sockaddr, timeoutMs);
    exists = true;
} catch(IOException e) {
    // Handle exception
}
Community
  • 1
  • 1
ghostbust555
  • 2,040
  • 16
  • 29
  • This worked Perfectly tested using various uri's and deliberately removing and disabling services and it correctly id's if the host is up and running or not – fury-s12 Jan 19 '12 at 00:35
  • Should the socket object be closed after using it ? – Leeeeeeelo Oct 18 '12 at 07:58
  • That depends on what you want to do with it. If your just checking to see if the ip exists then yes close it, if your checking to see if it exists so that you can send information to it you can just write to the socket. – ghostbust555 Oct 22 '12 at 04:57
  • But which port should you try if you just want to know if the host is up? There's no guarantee that a given port will be open (depends on device). Maybe I'm missing something – German Nov 07 '14 at 01:20
  • If a host is up it will have to have at least one static port that it will always have or you would not be able to connect to it for example port 80 for http. You can check multiple ports though if you are not sure that one will be active – ghostbust555 Nov 08 '14 at 17:00
  • Check my answer for a "pretty" solution – winklerrr Sep 11 '17 at 12:25
  • 1
    IP and PORT can be changed by server side. What about resolving by domain address? – Sazzad Hissain Khan Jul 02 '19 at 03:35
24

To check connectivity you could use:

public boolean isOnline(Context context) { 
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);    
    NetworkInfo netInfo = cm.getActiveNetworkInfo();    
    return netInfo != null && netInfo.isConnectedOrConnecting();
}

If it reports a connection, you could also then check via trying to do a http get to an address and then checking the status code that is returned. if no status code is returned it's pretty certain the host is unreachable.

Jon Willis
  • 6,993
  • 4
  • 43
  • 51
Richard Lewin
  • 1,870
  • 1
  • 19
  • 26
  • 14
    if im not mistaken this just checks that the device has the ability to use the internet not check an actual host/website for availability? – fury-s12 Jan 19 '12 at 00:27
  • 4
    yes, the provided code does check for the ability, but then you can then check host reachability by attempting to do a http get on the host. Combining my snippet with ghostbust555 code will provide a very robust checking workflow. I.e. run his code if my code says there is an internet connection. If there is no internet connection available there is no point trying to contact a host. – Richard Lewin Jan 19 '12 at 00:44
  • i thought so thanks i was already in process of doing just what you said :) – fury-s12 Jan 19 '12 at 00:51
  • All the getActiveNetworkInfo can check is that the device has an IP address and is talking to a network. It doesn't check and make sure that network can talk to the Internet or your server. – Astra Feb 12 '13 at 19:20
  • http://desousa.com.pt/blog/2012/01/testing-server-reachability-on-android adds some host reachability to the above – mblackwell8 Jul 04 '13 at 03:51
  • 1
    This code requires the following permission: android.permission.ACCESS_NETWORK_STATE – TheSteve Sep 10 '13 at 02:53
  • It seems that `isConnectedOrConnecting` is deprecated. – Hola Soy Edu Feliz Navidad Jan 07 '20 at 12:43
12

A Faster Solution

Instead of opening a complete socket connection you could use inetAddress.isReachable(int timeout). That would make the check faster but also more imprecise because this method just builds upon an echo request:

A typical implementation will use ICMP ECHO REQUESTs if the privilege can be obtained, otherwise it will try to establish a TCP connection on port 7 (Echo) of the destination host.

For my use case I had to establish a connection to a web server. Therefore it was necessary to me that the service on the server was up and running. So a socket connection was my preferred choice over a simple echo request.


Standard Solution

Java 7 and above

That's the code that I'm using for any Java 7 and above project:

/**
 * Check if host is reachable.
 * @param host The host to check for availability. Can either be a machine name, such as "google.com",
 *             or a textual representation of its IP address, such as "8.8.8.8".
 * @param port The port number.
 * @param timeout The timeout in milliseconds.
 * @return True if the host is reachable. False otherwise.
 */
public static boolean isHostAvailable(final String host, final int port, final int timeout) {
    try (final Socket socket = new Socket()) {
        final InetAddress inetAddress = InetAddress.getByName(host);
        final InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, port);

        socket.connect(inetSocketAddress, timeout);
        return true;
    } catch (java.io.IOException e) {
        e.printStackTrace();
        return false;
    }
}

Below Java 7

The try-catch-resource block from the code above works only with Java 7 and a newer version. Prior to version 7 a finally-block is needed to ensure the resource is closed correctly:

public static boolean isHostAvailable(final String host, final int port, final int timeout) {
    final Socket socket = new Socket();
    try {
        ... // same as above
    } catch (java.io.IOException e) {
        ... // same as above
    } finally {
        if (socket != null) {
            socket.close(); // this will throw another exception... just let the function throw it
        }
    }
}

Usage

host can either be a machine name, such as "google.com", or an IP address, such as "8.8.8.8".

if (isHostAvailable("google.com", 80, 1000)) {
    // do you work here
}

Further reading

Android Docs:

Stackoverflow:

winklerrr
  • 13,026
  • 8
  • 71
  • 88
  • how would it run in Android Studio it there is unhandled exception? – vikas devde Feb 25 '18 at 18:23
  • I don't exactly understand what you are asking for? What do you mean by 'unhandled exception'? All exceptions that could be thrown by the underlining code will get caught, imho. – winklerrr Mar 07 '18 at 19:28
2

Try this one:

boolean reachable = false;

try {
    reachable = InetAddress.getByName("www.example.com").isReachable(2000);
} catch (IOException e) {
    e.printStackTrace();
    reachable = false;
}

if (reachable) { 
    // do your work here 
} 

But this could fail even if the web server is up and running perfectly because of the way how isReachable(int timeout) is implemented:

Test whether that address is reachable. Best effort is made by the implementation to try to reach the host, but firewalls and server configuration may block requests resulting in a unreachable status while some specific ports may be accessible. A typical implementation will use ICMP ECHO REQUESTs if the privilege can be obtained, otherwise it will try to establish a TCP connection on port 7 (Echo) of the destination host.

winklerrr
  • 13,026
  • 8
  • 71
  • 88
eismi
  • 111
  • 2
  • 9
  • 7
    It's important to note that isReachable tries ICMP ping and then TCP echo (port 7). These are often closed down on HTTP servers. So a prefectly good working API with a web server on port 80 will be reported as unreachable if ICMP and TCP port 7 are filtered out! – Maciej Swic Oct 24 '13 at 15:59
  • 1
    I don't think so. Actually far from "often", such echo services are SELDOM closed in web servers. Indeed, no major website closed them, and doing so is a bad practice, but that's another discussion. – Fran Marzoa Dec 02 '14 at 11:14
  • Unluckily this won't work in Android unless the device is rooted. See this: http://stackoverflow.com/questions/2935325/android-debugging-inetaddress-isreachable/2935468#2935468 – Fran Marzoa Dec 04 '14 at 14:17
  • You can omit the check for true. Just write: `if (reachable) { ... }` – winklerrr Sep 11 '17 at 12:30