ChatGPT解决这个技术问题 Extra ChatGPT

How to check internet access on Android? InetAddress never times out

I got a AsyncTask that is supposed to check the network access to a host name. But the doInBackground() is never timed out. Anyone have a clue?

public class HostAvailabilityTask extends AsyncTask<String, Void, Boolean> {

    private Main main;

    public HostAvailabilityTask(Main main) {
        this.main = main;
    }

    protected Boolean doInBackground(String... params) {
        Main.Log("doInBackground() isHostAvailable():"+params[0]);

        try {
            return InetAddress.getByName(params[0]).isReachable(30); 
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;       
    }

    protected void onPostExecute(Boolean... result) {
        Main.Log("onPostExecute()");

        if(result[0] == false) {
            main.setContentView(R.layout.splash);
            return;
        }

        main.continueAfterHostCheck();
    }   
}
To check for an internet connection, probably the most reliable way would be to ping one of the major name servers, this could be done for example with if(Runtime.getRuntime().exec("/system/bin/ping -c 1 8.8.8.8").waitFor()==0) .... See my answer for a nicer implementation of this. Btw the accepted answer (and many others here) just check for a network connection, not the internet.
Do not use the ping method, use a HTTP check instead. ICMP is blocked on some networks, so ping will not work. E.g.: it works perfectly on my home wifi, but it does not when I am using mobile data on Vodafone's network (in Hungary). Or combine the 2 methods as a fallback, but be careful because waitFor() will wait about 20 seconds even if -w or -W is used.

B
Bhargav Rao

If the device is in airplane mode (or presumably in other situations where there's no available network), cm.getActiveNetworkInfo() will be null, so you need to add a null check.

Modified (Eddie's solution) below:

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

Also add the following permission to the AndroidManifest.xml:

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

One other small point, if you absolutely need a network connection at the given point in time, then it might be better to use netInfo.isConnected() rather than netInfo.isConnectedOrConnecting. I guess this is up to the individual use-case however.


imo you still should and need to check for http timeout exceptions since there might be situations when a network is connected but there would no actual internet connection because the only way to access it is through, for instance, VPN - this way u have, for instance, WI-FI connection but no actual internet traffic. Another situation is a server hang-on. These are 2 issues that I've run recently and connection manager isn't gonna help there.
I agree with midnight and Pintu, this answer should not be the accepted answer, it has nothing to do with checking wether you're on the internet. For example, if the phone is connected to a WiFi network with a captive portal, like at a hotel, this function will incorrectly return true. The correct answer is to ping a server on the public internet.
when there is no working internet for my router, if I connect to router through wifi, then the above code is returning true. But, It is not supposed to be, right? Can you help me
I had to add the Context, in context.getSystemService or it doesn't work. I got my clue here androidhive.info/2012/07/…
Nice way to check network availability. But how to check internet access?
A
Aryeetey Solomon Aryeetey

Network connection / Internet access

isConnectedOrConnecting() (used in most answers) checks for any network connection

To know whether any of those networks have internet access, use one of the following

A) Ping a Server (easy)

// ICMP 
public boolean isOnline() {
    Runtime runtime = Runtime.getRuntime();
    try {
        Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
        int     exitValue = ipProcess.waitFor();
        return (exitValue == 0);
    }
    catch (IOException e)          { e.printStackTrace(); }
    catch (InterruptedException e) { e.printStackTrace(); }

    return false;
}

+ could run on main thread

- does not work on some old devices (Galays S3, etc.), it blocks a while if no internet is available.

B) Connect to a Socket on the Internet (advanced)

// TCP/HTTP/DNS (depending on the port, 53=DNS, 80=HTTP, etc.)
public boolean isOnline() {
    try {
        int timeoutMs = 1500;
        Socket sock = new Socket();
        SocketAddress sockaddr = new InetSocketAddress("8.8.8.8", 53);

        sock.connect(sockaddr, timeoutMs);
        sock.close();

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

+ very fast (either way), works on all devices, very reliable

- can't run on the UI thread

This works very reliably, on every device, and is very fast. It needs to run in a separate task though (e.g. ScheduledExecutorService or AsyncTask).

Possible Questions

Is it really fast enough? Yes, very fast ;-)

Is there no reliable way to check internet, other than testing something on the internet? Not as far as I know, but let me know, and I will edit my answer.

What if the DNS is down? Google DNS (e.g. 8.8.8.8) is the largest public DNS in the world. As of 2018 it handled over a trillion queries a day [1]. Let 's just say, your app would probably not be the talk of the day.

Which permissions are required? Just internet access - surprise ^^ (Btw have you ever thought about, how some of the methods suggested here could even have a remote glue about internet access, without this permission?)

Extra: One-shot RxJava/RxAndroid Example (Kotlin)

fun hasInternetConnection(): Single<Boolean> {
  return Single.fromCallable {
    try {
      // Connect to Google DNS to check for connection
      val timeoutMs = 1500
      val socket = Socket()
      val socketAddress = InetSocketAddress("8.8.8.8", 53)
    
      socket.connect(socketAddress, timeoutMs)
      socket.close()
  
      true
    } catch (e: IOException) {
      false
    }
  }
  .subscribeOn(Schedulers.io())
  .observeOn(AndroidSchedulers.mainThread())
}

///////////////////////////////////////////////////////////////////////////////////
// Usage

    hasInternetConnection().subscribe { hasInternet -> /* do something */}

Extra: One-shot RxJava/RxAndroid Example (Java)

public static Single<Boolean> hasInternetConnection() {
    return Single.fromCallable(() -> {
        try {
            // Connect to Google DNS to check for connection
            int timeoutMs = 1500;
            Socket socket = new Socket();
            InetSocketAddress socketAddress = new InetSocketAddress("8.8.8.8", 53);

            socket.connect(socketAddress, timeoutMs);
            socket.close();

            return true;
        } catch (IOException e) {
            return false;
        }
    }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}

///////////////////////////////////////////////////////////////////////////////////
// Usage

    hasInternetConnection().subscribe((hasInternet) -> {
        if(hasInternet) {

        }else {

        }
    });

Extra: One-shot AsyncTask Example

Caution: This shows another example of how to do the request. However, since AsyncTask is deprecated, it should be replaced by your App's thread scheduling, Kotlin Coroutines, Rx, ...

class InternetCheck extends AsyncTask<Void,Void,Boolean> {

    private Consumer mConsumer;
    public  interface Consumer { void accept(Boolean internet); }

    public  InternetCheck(Consumer consumer) { mConsumer = consumer; execute(); }

    @Override protected Boolean doInBackground(Void... voids) { try {
        Socket sock = new Socket();
        sock.connect(new InetSocketAddress("8.8.8.8", 53), 1500);
        sock.close();
        return true;
    } catch (IOException e) { return false; } }

    @Override protected void onPostExecute(Boolean internet) { mConsumer.accept(internet); }
}

///////////////////////////////////////////////////////////////////////////////////
// Usage

    new InternetCheck(internet -> { /* do something with boolean response */ });

This is great peace of code! I found it very useful on devices that use prepaid cards! When they run out of money, they have internet access available, but no internet. So just checking for connectivity would not do. THANK YOU!
Keep in mind this approach is a blocking one so you shouldn't execute it in the UI therad
@Levit This should be the accepted answer. Above answer just checks Network n NOT INTERNET CONNECTION. And yes this is very fast. Thanks. Hence upvote.
This solution is not working for all devices. Some devices are always returning 2 as @Salmaan stated. The devices I tested had internet connection and the ping target is the Google DNS server - which is responding to ping requests. I think some vendors are not permitting ping requests. For example, I tested with a Samsung 10.1 tablet (4.3), and the solution is not working. When I run the ping command through the command line utility, I get a permission error. The command is also not working on emulators. Be careful using this solution.
This approach does not work on all phones. It fails for example on Samsung Galaxy S3. See here: Why does ping works on some devices and not others?
J
Jeff Axelrod

No need to be complex. The simplest and framework manner is to use ACCESS_NETWORK_STATE permission and just make a connected method

public boolean isOnline() {
    ConnectivityManager cm =
        (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

    return cm.getActiveNetworkInfo() != null && 
       cm.getActiveNetworkInfo().isConnectedOrConnecting();
}

You can also use requestRouteToHost if you have a particualr host and connection type (wifi/mobile) in mind.

You will also need:

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

in your android manifest.


it is better to do a null check at cm.getActiveNetworkInfo() level it threw a null if no active network was available.
see stackoverflow.com/a/11691676/1979773 for a deeper exaplanation about requestRouteToHost()
I had to add the Context, in context.getSystemService or it doesn't work. I got my clue here androidhive.info/2012/07/…
This solution will return true if you are connected to a WiFi hotspot, even if this hotspot does NOT have internet connectivity.
J
Jeff Axelrod

To get getActiveNetworkInfo() to work you need to add the following to the manifest.

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

This one should be definitely under the correct answer (wasted too much time figuring out what the hell is wrong).
The INTERNET permission is NOT needed for this, just ACCESS_NETWORK_STATE. INTERNET is only needed if you are actually making connections to remote locations, not querying the state of the device's radio.
Your answer is currently not really an answer, it's just a relatively minor addition to other answers. If all the other answers were not here, would your answer make sense? Not really. Because if that it is better to expand your answer with code on how to use it, or remove your answer and add the info in another answer (you will not lose any reputation)
Be careful getActiveNetworkInfo() is deprecated in API level 29.
F
Freewind

Take a look at the ConnectivityManager class. You can use this class to get information on the active connections on a host. http://developer.android.com/reference/android/net/ConnectivityManager.html

EDIT: You can use

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .getNetworkInfo(ConnectivityManager.TYPE_MOBILE) 

or

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .getNetworkInfo(ConnectivityManager.TYPE_WIFI) 

and parse the DetailedState enum of the returned NetworkInfo object

EDIT EDIT: To find out whether you can access a host, you can use

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .requestRouteToHost(TYPE_WIFI, int hostAddress)

Obviously, I'm using Context.getSystemService(Context.CONNECTIVITY_SERVICE) as a proxy to say

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

Not sure, but this seems like code to test what kind of network connection im currently on. E.g im on WiFi, there is no guarantee that you home wifi router is connected to internett... to check that you actually need to do a request to a internetserver...
There was a mistake in the EDIT EDIT section, I'd left out the requestRouteToHost() call. Re-read the answer now :)
requestRouteToHost has been deprecated.
M
Melquiades

check this code... it worked for me :)

public static void isNetworkAvailable(final Handler handler, final int timeout) {
    // ask fo message '0' (not connected) or '1' (connected) on 'handler'
    // the answer must be send before before within the 'timeout' (in milliseconds)

    new Thread() {
        private boolean responded = false;   
        @Override
        public void run() { 
            // set 'responded' to TRUE if is able to connect with google mobile (responds fast) 
            new Thread() {      
                @Override
                public void run() {
                    HttpGet requestForTest = new HttpGet("http://m.google.com");
                    try {
                        new DefaultHttpClient().execute(requestForTest); // can last...
                        responded = true;
                    } 
                    catch (Exception e) {
                    }
                } 
            }.start();

            try {
                int waited = 0;
                while(!responded && (waited < timeout)) {
                    sleep(100);
                    if(!responded ) { 
                        waited += 100;
                    }
                }
            } 
            catch(InterruptedException e) {} // do nothing 
            finally { 
                if (!responded) { handler.sendEmptyMessage(0); } 
                else { handler.sendEmptyMessage(1); }
            }
        }
    }.start();
}

Then, I define the handler:

Handler h = new Handler() {
    @Override
    public void handleMessage(Message msg) {

        if (msg.what != 1) { // code if not connected

        } else { // code if connected

        }   
    }
};

...and launch the test:

isNetworkAvailable(h,2000); // get the answser within 2000 ms

What is Google is down? That also requires the INTERNET permission, which is unnecessary for the given task. Finally, that consumes data (even if insignificant). This just seems like such a kludge.
@Tom to be fair, this is probably the only correct answer. The other examples merely show if a network connection is available and / or if there's a connection to that network, but don't answer the question if that network can actually also make a remote connection (for example to a website). So this answers the posters Q, and the other answers don't
@dmmh Yeah, that's unfortunately true from what I've seen with the Android APIs. Perhaps a simple ping might be better, stackoverflow.com/questions/3905358/…. If you were really concerned you could even include a list of IPs to ping, because while there is a very small chance Google will ever go down, there is an even smaller chance that Google, Bing, AND Yahoo will be down on the same day. Just my thoughts.
There is no point in doing this check. If you are going to spend the system time and network resources to connect to Google, you could have spent them instead connecting to the resource you actually care about.
In China Google was blocked!!
V
Vladtn

Found at and modified (!) from this link :

In your manifest file add at least:

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

You probably already have the INTERNET permission if you are accessing it. Then a boolean function that allows to test for connectivity is:

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 {
        Log.v(TAG, "Internet Connection Not Present");
        return false;
    }
}

D
Dediqated

I made this code, it is the simplest and it is just a boolean. by asking if(isOnline()){

You get if there is a connection and if it can connect to a page the status code 200 (stable connection).

Make sure to add the correct INTERNET and ACCESS_NETWORK_STATE permissions.

public boolean isOnline() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    if (netInfo != null && netInfo.isConnected()) {
        try {
            URL url = new URL("http://www.google.com");
            HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
            urlc.setConnectTimeout(3000);
            urlc.connect();
            if (urlc.getResponseCode() == 200) {
                return new Boolean(true);
            }
        } catch (MalformedURLException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    return false;
}

Maybe you should replace 200 by HttpURLConnection.HTTP_OK
What if Google is down?
M
Musculaa

It does works for me:

To verify network availability:

private Boolean isNetworkAvailable() {
ConnectivityManager connectivityManager 
      = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnectedOrConnecting();}

To verify internet access:

public Boolean isOnline() {
    try {
        Process p1 = java.lang.Runtime.getRuntime().exec("ping -c 1 www.google.com");
        int returnVal = p1.waitFor();
        boolean reachable = (returnVal==0);
        return reachable;
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return false;
}

this is a great solution to check if a server si up, works really fine. thanks!
the isOnline() shouldn't run on main thread at all, as if there is wi-fi signal but no internet it will take too long and block the main thread.
M
Mohamed Embaby

There's more than one way

First, shortest but Inefficient way

Network State Permission only needed

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

Then this method,

 public boolean activeNetwork () {
        ConnectivityManager cm =
                (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        boolean isConnected = activeNetwork != null &&
                activeNetwork.isConnected();

        return isConnected;

    }

As seen in answers ConnectivityManager is a solution, I just added it within a method this is a simplified method all use
ConnectivityManager returns true if there is a network access not Internet access, means if your WiFi is connected to a router but the router has no internet it returns true, it check connection availability

Second, Efficient way

Network State and Internet Permissions needed

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

Then this class,

 public class CheckInternetAsyncTask extends AsyncTask<Void, Integer, Boolean> {

        private Context context;

        public CheckInternetAsyncTask(Context context) {
            this.context = context;
        }

        @Override
        protected Boolean doInBackground(Void... params) {

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

            assert cm != null;
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            boolean isConnected = activeNetwork != null &&
                    activeNetwork.isConnected();


            if (isConnected) {
                try {
                    HttpURLConnection urlc = (HttpURLConnection)
                            (new URL("http://clients3.google.com/generate_204")
                                    .openConnection());
                    urlc.setRequestProperty("User-Agent", "Android");
                    urlc.setRequestProperty("Connection", "close");
                    urlc.setConnectTimeout(1500);
                    urlc.connect();
                    if (urlc.getResponseCode() == 204 &&
                            urlc.getContentLength() == 0)
                        return true;

                } catch (IOException e) {
                    Log.e("TAG", "Error checking internet connection", e);
                    return false;
                }
            } else {
                Log.d("TAG", "No network available!");
                return false;
            }


            return null;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
            Log.d("TAG", "result" + result);

            if(result){
                // do ur code
            }

        }


    }

Call CheckInternetAsyncTask

new CheckInternetAsyncTask(getApplicationContext()).execute();

Some Explanations :-

you have to check Internet on AsyncTask, otherwise it can throw android.os.NetworkOnMainThreadException in some cases

ConnectivityManager used to check the network access if true sends request (Ping)

Request send to http://clients3.google.com/generate_204, This well-known URL is known to return an empty page with an HTTP status 204 this is faster and more efficient than http://www.google.com , read this. if you have website it's preferred to put you website instead of google, only if you use it within the app

Timeout can be changed range (20ms -> 2000ms), 1500ms is commonly used


Great question, its sad you dont have more points. This must be the correct answer.
I am new to android. though, This is well covered answer and it get more attention @7569106
best and complete answer, thank you. if someone have a website notice that condition must like this urlc.getResponseCode() == 200 and not need to check urlc.getContentLength() == 0
your second option get crash i dont know why
it freezes application
C
Community

Here is the method I use:

public boolean isNetworkAvailable(final Context context) {
    return ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo() != null;
}

Even better, check to make sure it is "connected":

public boolean isNetworkAvailable(final Context context) {
    final ConnectivityManager connectivityManager = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE));
    return connectivityManager.getActiveNetworkInfo() != null && connectivityManager.getActiveNetworkInfo().isConnected();
}

Here is how to use the method:

if (isNetworkAvailable(context)) {
    // code here
} else {
    // code
}

Permission needed:

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

https://stackoverflow.com/a/16124915/950427


H
Hawklike

Kotlin and coroutines

I have placed the function in a ViewModel, which has the viewModelScope. Using an observable LiveData I inform an activity about the connection.

ViewModel

 fun checkInternetConnection(timeoutMs: Int) {
        viewModelScope.launch(Dispatchers.IO) {
            try {
                val socket = Socket()
                val socketAddress = InetSocketAddress("8.8.8.8", 53)

                socket.connect(socketAddress, timeoutMs)
                socket.close()

                _connection.postValue(true)
            }
            catch(ex: IOException) {
                _connection.postValue(false)
            }
        }
    }
 private val _connection = MutableLiveData<Boolean>()
 val connection: LiveData<Boolean> = _connection

Activity

 private fun checkInternetConnection() {
     viewModel.connection.observe(this) { hasInternet ->
         if(!hasInternet) {
             //hasn't connection
         }
         else {
            //has connection
         }
     }
  }

Din't work, not calling again
@AnshulTyagi What's not working? Did you actually call the method from the view model in your activity? If you want to check the internet connection multiple times, add a loop in the view model (while, repeat, etc.) and update the _connection variable accordingly.
N
Nickolaus

Of everything I have seen so far shortest and cleanest way should be:

public final static boolean isConnected( Context context )
{   
   final ConnectivityManager connectivityManager = 
         (ConnectivityManager) context.getSystemService( Context.CONNECTIVITY_SERVICE );  
   final NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();    
   return networkInfo != null && networkInfo.isConnected();
}

PS: This does not ping any host, it just checks the connectionstatus, so if your router has no internet connection and your device is connected to it this method would return true although you have no internet. For an actual test I would recommend execuding a HttpHead request (e.g. to www.google.com) and check the status, if its 200 OK everything is fine and your device has an internet connection.


I wanted to put this method in a global class so I had to use this version so I could pass the Context from the Activity I was calling it from. Thanks!
u
user1528493

One important use case on mobile devices to it ensure an actual connection exists. This is a common problem when a mobile user enters a Wifi network with a "Captive Portal", in which they need to sign in. I use this blocking function in the background to ensure a connection exists.

/*
 * Not Thread safe. Blocking thread. Returns true if it
 * can connect to URL, false and exception is logged.
 */
public boolean checkConnectionHttps(String url){
    boolean responded = false;
    HttpGet requestTest = new HttpGet(url);
    HttpParams params = new BasicHttpParams();
    HttpConnectionParams.setConnectionTimeout(params, 3000);
    HttpConnectionParams.setSoTimeout(params, 5000);
    DefaultHttpClient client = new DefaultHttpClient(params);
    try {
        client.execute(requestTest);
        responded = true;
    } catch (ClientProtocolException e) {
        Log.w(MainActivity.TAG,"Unable to connect to " + url + " " + e.toString());
    } catch (IOException e) {
        Log.w(MainActivity.TAG,"Unable to connect to " + url + " " + e.toString());
        e.printStackTrace();
    }
    return responded;
}

+1 for actually checking end-to-end connectivity. For the "Captive Portal" situation, however, I've found that many will pass the above test even if you haven't signed in - you get the login page and a 200 response no matter what url you ask for. So I attempt to hit a page on my own domain that I know does not exist, and make sure that I get a 404. Alternately, you could hit a known existing page, make sure that you get a 200, and check the content that is returned to make sure that it's what you expect.
V
Vidar Vestnes

Im using this code instead of the InetAddress :

    try {

        URL url = new URL("http://"+params[0]);

        HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
        urlc.setRequestProperty("User-Agent", "Android Application:"+Z.APP_VERSION);
        urlc.setRequestProperty("Connection", "close");
        urlc.setConnectTimeout(1000 * 30); // mTimeout is in seconds
        urlc.connect();
        if (urlc.getResponseCode() == 200) {
            Main.Log("getResponseCode == 200");
            return new Boolean(true);
        }
    } catch (MalformedURLException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

It would be great if you had clarified if the IOException means no internet connection and how reliable it could be.
It works for me but I have to convert "http://" to "https://". If I don't convert it will occur the error "Cleartext HTTP traffic to www.yourSite.com not permitted".
E
Emre Yazici

You can iterate over all network connections and chek whether there is at least one available connection:

public boolean isConnected() {
    boolean connected = false;

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

    if (cm != null) {
        NetworkInfo[] netInfo = cm.getAllNetworkInfo();

        for (NetworkInfo ni : netInfo) {
            if ((ni.getTypeName().equalsIgnoreCase("WIFI")
                    || ni.getTypeName().equalsIgnoreCase("MOBILE"))
                    && ni.isConnected() && ni.isAvailable()) {
                connected = true;
            }

        }
    }

    return connected;
}

l
laplasz

For me it was not a good practice to check the connection state in the Activity class, because

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

should be called there, or you need to push down your Activity instance (context) to the connection handler class to able to check the connection state there When no available connection (wifi, network) I catch the UnknownHostException exception:

JSONObject jObj = null;
Boolean responded = false;
HttpGet requestForTest = new HttpGet("http://myserver.com");
try {
    new DefaultHttpClient().execute(requestForTest);
    responded = true;
} catch (UnknownHostException e) {
    jObj = new JSONObject();
    try {
        jObj.put("answer_code", 1);
        jObj.put("answer_text", "No available connection");
    } catch (Exception e1) {}
    return jObj;
} catch (IOException e) {
    e.printStackTrace();
}

In this way I can handle this case along with the other cases in the same class (my server always response back with a json string)


L
Lo Juego

Best approach:

public static boolean isOnline() {
    try {
    InetAddress.getByName("google.com").isReachable(3);

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

I like this approach but I have to point out some things. isReachable() returns a boolean, therefore instead of returning true in the try section, you could do it like boolean connected = InetAddress.getByName("google.com").isReachable(3); then return connected. Also, isReacheable throws IOException and IllegalArgumentException exceptions, therefore itll be a good idea of replacing UnknownHostException with IllegalArgumentException and including a third catch: catch (Exception E).
But then, isReachable uses ICMP which might require root privileges and uses port 7 which usually has no running services on the latest systems. Therefore the best way to check the route to an online service is by regular TCP; hence a down vote.
s
selva_pollachi

It's works for me. Try it out.

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    try {
        URL url = new URL("http://stackoverflow.com/posts/11642475/edit" );
        //URL url = new URL("http://www.nofoundwebsite.com/" );
        executeReq(url);
        Toast.makeText(getApplicationContext(), "Webpage is available!", Toast.LENGTH_SHORT).show();
    }
    catch(Exception e) {
        Toast.makeText(getApplicationContext(), "oops! webpage is not available!", Toast.LENGTH_SHORT).show();
    }
}

private void executeReq(URL urlObject) throws IOException
{
    HttpURLConnection conn = null;
    conn = (HttpURLConnection) urlObject.openConnection();
    conn.setReadTimeout(30000);//milliseconds
    conn.setConnectTimeout(3500);//milliseconds
    conn.setRequestMethod("GET");
    conn.setDoInput(true);

    // Start connect
    conn.connect();
    InputStream response =conn.getInputStream();
    Log.d("Response:", response.toString());
}}

This answer can not work now, since we can not access network on main thread now.
I mean from API level 11, this doesn't work. Reason: developer.android.com/reference/android/os/…. If it works for you, it means you're running this code on old android device. (prior to GB).
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder() .permitAll().build(); StrictMode.setThreadPolicy(policy); add these two lines two your program for avoiding network main thread exception
Ok, I should not say this cannot work, I should say it can work (by target old version or Strictmode setup) but is discouraged. This may cause ANR easily. (With so high timeout configuration in httpurlconnection)
ya..you are right.. just i put this because this is also one of the way.
A
Akshay Paliwal

You can use this method to detect network availability-

public static boolean isDeviceOnline(Context context) {
        boolean isConnectionAvail = false;
        try {
            ConnectivityManager cm = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo netInfo = cm.getActiveNetworkInfo();
            return netInfo.isConnected();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return isConnectionAvail;
    }

W
WonderWorker

This method gives you the option for a really fast method (for real time feedback) or a slower method (for one off checks that require reliability)

public boolean isNetworkAvailable(bool SlowButMoreReliable) {
    bool Result = false; 
    try {
        if(SlowButMoreReliable){
            ConnectivityManager MyConnectivityManager = null;
            MyConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

            NetworkInfo MyNetworkInfo = null;
            MyNetworkInfo = MyConnectivityManager.getActiveNetworkInfo();

            Result = MyNetworkInfo != null && MyNetworkInfo.isConnected();

        } else
        {
            Runtime runtime = Runtime.getRuntime();
            Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");

            int i = ipProcess.waitFor();

            Result = i== 0;

        }

    } catch(Exception ex)
    {
        //Common.Exception(ex); //This method is one you should have that displays exceptions in your log
    }
    return Result;
}

C
Chilledrat

It is not complex to check Android network / internet connectivity status. The below DetectConnection class will help you to check this status:

import android.content.Context;
import android.net.ConnectivityManager;

public class DetectConnection {
    public static boolean checkInternetConnection(Context context) {
        ConnectivityManager con_manager = (ConnectivityManager) context
                                .getSystemService(Context.CONNECTIVITY_SERVICE);

        if (con_manager.getActiveNetworkInfo() != null
            && con_manager.getActiveNetworkInfo().isAvailable()
            && con_manager.getActiveNetworkInfo().isConnected()) {
                return true;
        } else {
            return false;
        }
    }
}

For more details visit How to Check Android Network / Internet Connectivity Status


M
Mahendra Liya

Following is the code from my Utils class:

public static boolean isNetworkAvailable(Context context) {
        ConnectivityManager connectivityManager 
              = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}

k
kleopatra
public class Network {

Context context;

public Network(Context context){
    this.context = context;
}

public boolean isOnline() {
    ConnectivityManager cm =
            (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);

    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    return activeNetwork != null &&
                          activeNetwork.isConnectedOrConnecting();
}

}

As all the other which didn't read the problem through, this does not solve the problem, since it does not really check for a connection to the internet. A connection to a local wifi hotspot will return true, even if the hotspot will not allow you to go through to the internet.
k
kreker

This is covered in android docs http://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html


But the method described there does not really check for Internet connection, it just checks if a connection is established (whether is has access to the Internet or not). The title of that official doc is really misleading.
Giving an answer to the question is better than just posting a link to information. What if the link goes dead? We will have no answer.
J
Jorgesys

Very important to check if we have connectivity with isAvailable() and if is possible to establish a connection with isConnected()

private static ConnectivityManager manager;

public static boolean isOnline(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    return networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected();
}

and you can derterminate the type of network active WiFi :

public static boolean isConnectedWifi(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    return networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI;
}

or mobile Móvil :

public static boolean isConnectedMobile(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    return networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE;
}

don´t forget the permissions:

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

Nice summary of the device connectivity components, just need to wrap them in try/catch statements to avoid crashes. Similarly, just make your routine HttpURLConnection calls, as long as they're wrapped in error handling, you'll soon know whether or not you have an internet connection
J
Jaymin Panchal

I have applied the solution provided by @Levit and created function that will not call the extra Http Request.

It will solve the error Unable to Resolve Host

public static boolean isInternetAvailable(Context context) {
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    if (activeNetwork == null) return false;

    switch (activeNetwork.getType()) {
        case ConnectivityManager.TYPE_WIFI:
            if ((activeNetwork.getState() == NetworkInfo.State.CONNECTED ||
                    activeNetwork.getState() == NetworkInfo.State.CONNECTING) &&
                    isInternet())
                return true;
            break;
        case ConnectivityManager.TYPE_MOBILE:
            if ((activeNetwork.getState() == NetworkInfo.State.CONNECTED ||
                    activeNetwork.getState() == NetworkInfo.State.CONNECTING) &&
                    isInternet())
                return true;
            break;
        default:
            return false;
    }
    return false;
}

private static boolean isInternet() {

    Runtime runtime = Runtime.getRuntime();
    try {
        Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
        int exitValue = ipProcess.waitFor();
        Debug.i(exitValue + "");
        return (exitValue == 0);
    } catch (IOException | InterruptedException e) {
        e.printStackTrace();
    }

    return false;
}

Now call it like,

if (!isInternetAvailable(getActivity())) {
     //Show message
} else {
     //Perfoem the api request
}

H
Has AlTaiar

Update 29/06/2015 If you are using Xamarin.Android and want to check for connectivity, you can use a Nuget package that would give you this functionality on multiple platforms. Good candidates are here and here. [End of Update]

The Answers above are quite good, but they are all in Java, and almost all of them check for a connectivity. In my case, I needed to have connectivity with a specific type of connection and I am developing on Xamarin.Android. Moreover, I do not pass a reference to my activities Context in the Hardware layer, I use the Application Context. So here is my solution, in case somebody comes here with similar requirements. I have not done full testing though, will update the answer once I am done with my testing

using Android.App;
using Android.Content;
using Android.Net;

namespace Leopard.Mobile.Hal.Android
{
    public class AndroidNetworkHelper
    {
        public static AndroidNetworkStatus GetWifiConnectivityStatus()
        {
            return GetConnectivityStatus(ConnectivityType.Wifi);
        }

        public static AndroidNetworkStatus GetMobileConnectivityStatus()
        {
            return GetConnectivityStatus(ConnectivityType.Mobile);
        }

        #region Implementation

        private static AndroidNetworkStatus GetConnectivityStatus(ConnectivityType connectivityType)
        {
            var connectivityManager = (ConnectivityManager)Application.Context.GetSystemService(Context.ConnectivityService);
            var wifiNetworkInfo = connectivityManager.GetNetworkInfo(connectivityType);
            var result = GetNetworkStatus(wifiNetworkInfo);
            return result;
        }

        private static AndroidNetworkStatus GetNetworkStatus(NetworkInfo wifiNetworkInfo)
        {
            var result = AndroidNetworkStatus.Unknown;
            if (wifiNetworkInfo != null)
            {
                if (wifiNetworkInfo.IsAvailable && wifiNetworkInfo.IsConnected)
                {
                    result = AndroidNetworkStatus.Connected;
                }
                else
                {
                    result = AndroidNetworkStatus.Disconnected;
                }
            }
            return result;
        } 

        #endregion
    }

    public enum AndroidNetworkStatus
    {
        Connected,
        Disconnected,
        Unknown
    }

m
miguel

The other answers that use ConnectivityManager are wrong because having a network connection doesn't mean you have internet access. For example, the user might be connected to a coffee shop's WiFi portal but can't get to the internet. To check that the internet is accessible you have to try to connect to an actual server. Normally when you want to do this you have a specific server in mind that you want to connect to, so go ahead and check if you can connect to that server. Here's a simple method for checking connectivity to a server.

private boolean isOnTheInternet() {
    try {
        URLConnection urlConnection = new URL("http://yourserver").openConnection();
        urlConnection.setConnectTimeout(400);
        urlConnection.connect();
        return true;
    } catch (Exception e) {
        return false;
    }
}

The reason for setting the ConnectTimeout is that otherwise it defaults to the TCP timeout which can be many seconds long.

Note also that Android won't let you run this on your main thread.


R
Rajesh

I have gone through all the answers and i come up with my own answer which first check whether Internet is available and if Internet is available then it check whether it is active or not.

I have included all necessary method and classes to check for active Internet connection.

NetworkUtils.class

public class NetworkUtils {

    public static final int STATUS_CONNECTED = 0 ;

    public static boolean isInternetAvailable(Context ctx){
        ConnectivityManager cm = (ConnectivityManager)ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
    }

    public static int isInternetActiveWithPing() {
        try {
            Runtime runtime = Runtime.getRuntime();
            Process process = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
            int exitValue = process.waitFor();
            return exitValue;
        } catch (Exception ex) {
            return -1;
        }
    }

    public static boolean isInternetActiveWithInetAddress() {
        try {
            InetAddress inetAddress = InetAddress.getByName("www.google.com");
            return inetAddress != null && !inetAddress.toString().equals("");
        } catch (Exception ex) {
            return false;
        }
    }

    public static void displayInternetConnectionMessage(Context ctx){
        Toast.makeText(ctx, "Check Internet Connection", Toast.LENGTH_SHORT).show();
    }
}

You can check whether Internet is active using below code:

 private void checkInternetConnection() {
        if (NetworkUtils.isInternetAvailable(this)) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    if (NetworkUtils.isInternetActiveWithPing() == NetworkUtils.STATUS_CONNECTED) {
                        performNetworkingOperations();
                    } else {
                        if (NetworkUtils.isInternetActiveWithInetAddress()) {
                            performNetworkingOperations();
                        } else {
                            displayConnectionMessage();
                        }
                    }
                }
            }).start();

        } else {
            displayConnectionMessage();
        }
    }

    private void performNetworkingOperations() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, "Internet is Available", Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void displayConnectionMessage() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                NetworkUtils.displayInternetConnectionMessage(MainActivity.this);
            }
        });
    }

Better pack threading in your NetworkUtils and therefore "force" developer not to mis use your method
To remove one extra if condition. if ((NetworkUtils.isInternetActiveWithPing() == NetworkUtils.STATUS_CONNECTED) || NetworkUtils.isInternetActiveWithInetAddress()) { //Do Network Operation } else { //Error Message }