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

64

723

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();
    }   
}
Olympian answered 13/10, 2009 at 14:59 Comment(5)
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.Ochre
see-> https://mcmap.net/q/11338/-detect-whether-there-is-an-internet-connection-available-on-android-duplicateAmsden
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.Calutron
getAllNetworkInfo() is deprecated in API level 29Procumbent
check https://mcmap.net/q/11456/-helper-class-best-approach-androidCorsiglia
O
685

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?

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

    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 */ });
Ochre answered 5/12, 2014 at 9:20 Comment(51)
@Salmaan: manpagez.com/man/8/ping states: The ping utility exits with one of the following values: (0) At least one response was heard from the specified host. (2) The transmission was successful but no responses were received. (any other value) An error occurred. These values are defined in <sysexits.h>. ... in short it means that the ping worked, but the server did not respond, or in other words: no internet connection (If the device you are trying this on is connected to the internet: Did you set the android.permission.INTERNET permission?)Ochre
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!Francoise
I ran this code and then I am checking its returned value ..this is getting true even if I have mobile data connection and no internet connection (because mobile data has expired and I cannot connect google from browser) and it is not running many times..what if I start my app and after some time there is no internet connection will it run again?Buskined
@therealprashant: This really is an interesting case then. Seems like - with your provider - you are still connected to the internet (although your data has expired)! It might just block HTTP and others, or probably redirect those to their (the providers) homepage. But technically you have internet access (since it is possible to ping "the internet")! In your case additional checks might be necessary, like requesting a file from your own webserver, if that is what you want to make sure your app is able to do. You might need to do that in a different threat though, because of the time it takes.Ochre
Keep in mind this approach is a blocking one so you shouldn't execute it in the UI theradDisprize
@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.Quicksilver
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.Vermouth
This is causing my app to ANR on some devicesBergin
Thx for the feedback, just the obvious question first: "You have INTERNET permission set, right?"... because even android.com uses the ping command as example in developer.android.com/reference/java/lang/Process.html . The emulator blocking it makes sense, but other than that it worked pretty well for me so far; and seems to be the only reliable way to check it ... Also if you know of any other, I will be happy to edit my answer accordingly.Ochre
While this code CAN run from the UI thread (as the answer states), it really SHOULD NOT. If the connection is slow or down for some seconds, you might freeze the UI and even get an ANR message. And yes, these situations do happen in the real world.Mariner
@Tiago (& Sergii): Yes, you are right! It is best practice to not have any network stuff on the UI thread (even though in most cases(!) this should be fine). This answer is just about the "how to do it", not the "where" - just giving a starting point to those looking for the best way of doing this. I also will recommend using a different thread! I just wanted to keep this answer simple and focused on the main problem ... because the solution is actually very simple.Ochre
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?Paries
@AdilHussain: Good point! As far as I see it, this is mainly concerns older(!) devices. Even Samsung's S4 and Note2, are working fine with this method! But if you/others know of any problematic devices, plz let me know, and I will add a list of those to my answer. Especially if they are newer than the S3!Ochre
I challenge the point made, "Let 's just say, your app not responding would probably not be the talk of the day." We have no business thinking this way. Google grew from modest roots, and I believe that it's in all our interests to keep the market competetive, and to do this we need to be impartial to all software developers. Let's not fall into the trap of allowing Google to claim ownership of the internet.Madly
Keep in mind that this will not work on Android default emulators because they use Qemu user networking mode where you cant ping a serverElectrosurgery
I can't use this for every REST request like for OkHttp3 caching interceptors. This will add up to my response time.Rushing
This is not device wide and it should NOT be used or trusted for production.Jacobite
@Levit : Is there any way to set timeout for this request or is it required to set timeout for this?Gotland
@0xAliHn: You could try the interval switch /system/bin/ping -i 0.2 -c 1 8.8.8.8, which now waits for 0.2 seconds after the request, instead of the default 1 second (lower values than 200ms are only allowed for super users). Other than that you could also build your own timeout routine. Having it on a different thread would be generally the first step though. From there you could send feedback after a specified time, in case the ping request was not yet finished, for example.Ochre
this is an excellent answer but when i tested this method it is not always returning a correct value as when device may be on a paid meter network but no actual internet connection .Also this should be done on a background thread yes it may fast but on some devices it causes the main thread to halt or wait until it finishes which stops other processes so i suggest you to use a threadLida
ping with a timeout flag to avoid anrIts
Thanks for all the feedback, I added "socket connections" as primary solution, to tackle most of the issues at hand (timeouts, privileges on older devices, etc.). @oathkeeper: It is highly unlikely that Google Public DNS might migrate or permanently go down; there might be the issue with IPv4 being shut off one day, but well ... ^^Ochre
The only real answer on this particular question. Most of the answers i've seen (even the accepted ones) only check if the wifi or the mobile internet are turned on, but not if they are actually transferring any data.Gradatim
In case in the future, when people would travel other planets, Google's DNS will be different than 8.8.8.8 on other planets for sure. Boom! You need to recompile your app for every different planet. Case 2: Your ping has just ate the last 16 bytes of your pre-payed traffic. Boom! The code has just said that internet is connected but it's not true anymore. Case 3: One moment a ping breaks through, but the next millisecond a connection is lost. Boom! I hope yall got my point. If i were you I'd just check a connectivity and let your request fail. No need to do over-engineering here.Snodgrass
@mykolaj: Lol, I hope you were kidding ^^ Case 1: If you reach internet 8.8.8.8 should be reachable as well ;-) Case 2 & 3: Are true for connection checks as well. Sure checking for any connection suffices in a lot of scenarios, but if you really want to know whether there is internet ...Ochre
Your solutions depend on remote servers that when they are down, wrong reports will raise. Is there any independent solution that checks internet access itself by the device?Abranchiate
@MohammadAfrashteh: As stated in the answer: "Not as far as I know, but let me know ..." The internet is "just" a system of interlinked networks, there is no single best way to be a 100% sure. Testing one of those ips that is relied upon this much, and has such immense failover power seems bretty close though. It is also a common way; have you ever visited google.com or similar to see if you had internet?Ochre
you can use 'ping -c 1 -w 1 8.8.8.8'; -w means a timeout, in seconds, before ping exits regardless of how many packets have been sent or received.Kuhlmann
This returns always true, even if a cellphone has no credit , the only way it returns false is when all internet providers like wifi or 3g,4g are disabled.Afrikander
your app would probably not be the talk of the day Can't stop laughing. :DMcdaniels
WARNING: I just implemented the solution B of this answer and I'm warning you it's not reliable solution. After publishing the app, I started reeving complains about users that they are connected with the internet but the app still showing internet not available error. I increased the timeout to 3000 milliseconds and still some users complaining about wrong error. I asked for screenshots and prove and they where right. This solution is not accurate.Mcdaniels
@MuhammadSaqib: How did you implement it? Did you call it in from a separate thread (e.g. AsyncTask) as described (which is necessary for it to work)? Or Could you provide the code within the stackoverflow chat for us to check? Thanks.Ochre
@Ochre I implemented it in a separate thread (i.e AsyncTask) I followed the codes exactly and during testing on multiple devices (real and emulators) it was working perfectly. I also tested this with a signed apk just before uploading it on google. But, as soon as update becomes available, we start receiving complains from our users. Not all users may be every 1 out of 10 users was facing this issue. We removed this and implemented diff solution and ask those effected users to update the app and check again. They did the same and reported problem resolved for all.Mcdaniels
@Ochre I'm pretty much sure that this solution does not support some android versions or may be some mobile companies. As it was not a crash, so I don't have details exactly what android versions and what mobile companies were effected.Mcdaniels
RxJava approach is the only valid here. Can be also used in Java, Kotlin is not required. I wonder why Android api does not expose actual internet connection availability, system itself is informed about that - it's indicated by exclamation mark on wifi/4g icon.Tippets
@Tippets Once it exposes it, this answer will be drastically shortened. Maybe this is because the system also can't guarantee that (it has internet) via its similar checks. The first examples are primarily to understand what's going on (answer the actual question), but out of intererst: why would you consider e.g. the AsyncTask example not to be valid?Ochre
Because AsyncTask itself should be avoided. Never use AsyncTask. It's even deprecated now in api 30: developer.android.com/reference/android/os/AsyncTask This class was deprecated in API level 30. Use the standard java.util.concurrent or Kotlin concurrency utilities instead. I know this answer is old, but today you should forget AsyncTaskTippets
@Tippets Thank you for the feedback, I added a deprecation notice and reordered die "extra-examples". While deleting it would remove a helpful part of the answer, you are free to change this example to e.g. use concurrent or ScheduledFuture<?>.schedule(...) to still offer a fully valid vanilla Android example.Ochre
The argument -c was replaced by -n: "ping -n 1 google.com"Convention
Doesn't work on my phone. Both easy And advanced. Galaxy J7 MaxKipper
@MuhammadSaqib What was your solution ?Gamester
@Gamester I placed a static text file on my server returns 1. Mobile app first check internet availability with the help of native functions then it try to read that internet file.Mcdaniels
@MuhammadSaqib So basically you are making an api call to your server, if it is returning, you are assuming it is connected ?? How long you are waiting for your server file response ? 2 sec ? 3 sec ? We too are following the same approach now and we have decided to keep 3 sec for our api to respond, if not responding we will assume it is not connected truelyGamester
@Gamester 3 seconds aren't enough. I have set 10 seconds timeout with error message Unable to connect with our servers instead of You are not connected with internet and don't forget to check internet connection locally first.Mcdaniels
@Gamester again, It's totally depends on your needs.Mcdaniels
This approach (with pining a server) always returns false in my case even if I have Internet connection. I get the error "qemu_pipe_open_ns:62: Could not connect to the 'pipe:qemud:network' service: Invalid argument". Any idea how to fix this?Irredentist
The "ping" approach does not work on some devices, as mentioned in the answer. However, if these are new devices as well (previously only quite old ones like S3 etc.), I consider removing this approach completely, which were they? @MuhammadSaqib has the even better solution (here in comments), with not just establishing a connection, but getting a resource. Will be worked into the answer when I have time, or feel free to edit this answer, seems like quite good an improvement.Ochre
Don't forget about China blocing each and everything related to Google; Tests show they even force their own DNS servers, which intentionally returns wrong IP (for anything in their black-list).Landmeier
this solved our production app problem. Some of our drivers use hotspots and our sync process would throw errors before they were logged into the hotspotMonocycle
Using this solution can lead you to unexpected problems, pinging google server for internet connection at specific port can be prevented from device vendor, router you are connected to or even internet service provider.Gobioid
Should sock.close() be in a finally block?Downall
A
1048

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.

Amalburga answered 24/10, 2010 at 16:28 Comment(11)
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.Atomicity
i used isConnected and isConnectedOrConnection() and it always giving me true its taking more time than i expected any advice "my app uses google cloud messaging and web service"Rame
@Atomicity u right same thing i am facing my internet is on but data packet are not sending nd recievint then in this situation what ca we do?Nanoid
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.Shingle
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 meImpignorate
I had to add the Context, in context.getSystemService or it doesn't work. I got my clue here androidhive.info/2012/07/…Aerobic
Nice way to check network availability. But how to check internet access?Calutron
You say " if you absolutely need a network connection at the given time" which sounds kinda vague. Better say: "if you want to read or write data" use isConnected(..) instead. More in the docs here developer.android.com/reference/android/net/…Consolata
getAllNetworkInfo() is deprecated in API level 29Procumbent
This sollution is deprecated n Api +28 . visit : #53532906Nourishment
Your code checks only if a connection to a Network interface (WIFI, LTE, etc...) has been established! It will not tell if that connection can reach an Internet server.Agram
O
685

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?

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

    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 */ });
Ochre answered 5/12, 2014 at 9:20 Comment(51)
@Salmaan: manpagez.com/man/8/ping states: The ping utility exits with one of the following values: (0) At least one response was heard from the specified host. (2) The transmission was successful but no responses were received. (any other value) An error occurred. These values are defined in <sysexits.h>. ... in short it means that the ping worked, but the server did not respond, or in other words: no internet connection (If the device you are trying this on is connected to the internet: Did you set the android.permission.INTERNET permission?)Ochre
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!Francoise
I ran this code and then I am checking its returned value ..this is getting true even if I have mobile data connection and no internet connection (because mobile data has expired and I cannot connect google from browser) and it is not running many times..what if I start my app and after some time there is no internet connection will it run again?Buskined
@therealprashant: This really is an interesting case then. Seems like - with your provider - you are still connected to the internet (although your data has expired)! It might just block HTTP and others, or probably redirect those to their (the providers) homepage. But technically you have internet access (since it is possible to ping "the internet")! In your case additional checks might be necessary, like requesting a file from your own webserver, if that is what you want to make sure your app is able to do. You might need to do that in a different threat though, because of the time it takes.Ochre
Keep in mind this approach is a blocking one so you shouldn't execute it in the UI theradDisprize
@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.Quicksilver
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.Vermouth
This is causing my app to ANR on some devicesBergin
Thx for the feedback, just the obvious question first: "You have INTERNET permission set, right?"... because even android.com uses the ping command as example in developer.android.com/reference/java/lang/Process.html . The emulator blocking it makes sense, but other than that it worked pretty well for me so far; and seems to be the only reliable way to check it ... Also if you know of any other, I will be happy to edit my answer accordingly.Ochre
While this code CAN run from the UI thread (as the answer states), it really SHOULD NOT. If the connection is slow or down for some seconds, you might freeze the UI and even get an ANR message. And yes, these situations do happen in the real world.Mariner
@Tiago (& Sergii): Yes, you are right! It is best practice to not have any network stuff on the UI thread (even though in most cases(!) this should be fine). This answer is just about the "how to do it", not the "where" - just giving a starting point to those looking for the best way of doing this. I also will recommend using a different thread! I just wanted to keep this answer simple and focused on the main problem ... because the solution is actually very simple.Ochre
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?Paries
@AdilHussain: Good point! As far as I see it, this is mainly concerns older(!) devices. Even Samsung's S4 and Note2, are working fine with this method! But if you/others know of any problematic devices, plz let me know, and I will add a list of those to my answer. Especially if they are newer than the S3!Ochre
I challenge the point made, "Let 's just say, your app not responding would probably not be the talk of the day." We have no business thinking this way. Google grew from modest roots, and I believe that it's in all our interests to keep the market competetive, and to do this we need to be impartial to all software developers. Let's not fall into the trap of allowing Google to claim ownership of the internet.Madly
Keep in mind that this will not work on Android default emulators because they use Qemu user networking mode where you cant ping a serverElectrosurgery
I can't use this for every REST request like for OkHttp3 caching interceptors. This will add up to my response time.Rushing
This is not device wide and it should NOT be used or trusted for production.Jacobite
@Levit : Is there any way to set timeout for this request or is it required to set timeout for this?Gotland
@0xAliHn: You could try the interval switch /system/bin/ping -i 0.2 -c 1 8.8.8.8, which now waits for 0.2 seconds after the request, instead of the default 1 second (lower values than 200ms are only allowed for super users). Other than that you could also build your own timeout routine. Having it on a different thread would be generally the first step though. From there you could send feedback after a specified time, in case the ping request was not yet finished, for example.Ochre
this is an excellent answer but when i tested this method it is not always returning a correct value as when device may be on a paid meter network but no actual internet connection .Also this should be done on a background thread yes it may fast but on some devices it causes the main thread to halt or wait until it finishes which stops other processes so i suggest you to use a threadLida
ping with a timeout flag to avoid anrIts
Thanks for all the feedback, I added "socket connections" as primary solution, to tackle most of the issues at hand (timeouts, privileges on older devices, etc.). @oathkeeper: It is highly unlikely that Google Public DNS might migrate or permanently go down; there might be the issue with IPv4 being shut off one day, but well ... ^^Ochre
The only real answer on this particular question. Most of the answers i've seen (even the accepted ones) only check if the wifi or the mobile internet are turned on, but not if they are actually transferring any data.Gradatim
In case in the future, when people would travel other planets, Google's DNS will be different than 8.8.8.8 on other planets for sure. Boom! You need to recompile your app for every different planet. Case 2: Your ping has just ate the last 16 bytes of your pre-payed traffic. Boom! The code has just said that internet is connected but it's not true anymore. Case 3: One moment a ping breaks through, but the next millisecond a connection is lost. Boom! I hope yall got my point. If i were you I'd just check a connectivity and let your request fail. No need to do over-engineering here.Snodgrass
@mykolaj: Lol, I hope you were kidding ^^ Case 1: If you reach internet 8.8.8.8 should be reachable as well ;-) Case 2 & 3: Are true for connection checks as well. Sure checking for any connection suffices in a lot of scenarios, but if you really want to know whether there is internet ...Ochre
Your solutions depend on remote servers that when they are down, wrong reports will raise. Is there any independent solution that checks internet access itself by the device?Abranchiate
@MohammadAfrashteh: As stated in the answer: "Not as far as I know, but let me know ..." The internet is "just" a system of interlinked networks, there is no single best way to be a 100% sure. Testing one of those ips that is relied upon this much, and has such immense failover power seems bretty close though. It is also a common way; have you ever visited google.com or similar to see if you had internet?Ochre
you can use 'ping -c 1 -w 1 8.8.8.8'; -w means a timeout, in seconds, before ping exits regardless of how many packets have been sent or received.Kuhlmann
This returns always true, even if a cellphone has no credit , the only way it returns false is when all internet providers like wifi or 3g,4g are disabled.Afrikander
your app would probably not be the talk of the day Can't stop laughing. :DMcdaniels
WARNING: I just implemented the solution B of this answer and I'm warning you it's not reliable solution. After publishing the app, I started reeving complains about users that they are connected with the internet but the app still showing internet not available error. I increased the timeout to 3000 milliseconds and still some users complaining about wrong error. I asked for screenshots and prove and they where right. This solution is not accurate.Mcdaniels
@MuhammadSaqib: How did you implement it? Did you call it in from a separate thread (e.g. AsyncTask) as described (which is necessary for it to work)? Or Could you provide the code within the stackoverflow chat for us to check? Thanks.Ochre
@Ochre I implemented it in a separate thread (i.e AsyncTask) I followed the codes exactly and during testing on multiple devices (real and emulators) it was working perfectly. I also tested this with a signed apk just before uploading it on google. But, as soon as update becomes available, we start receiving complains from our users. Not all users may be every 1 out of 10 users was facing this issue. We removed this and implemented diff solution and ask those effected users to update the app and check again. They did the same and reported problem resolved for all.Mcdaniels
@Ochre I'm pretty much sure that this solution does not support some android versions or may be some mobile companies. As it was not a crash, so I don't have details exactly what android versions and what mobile companies were effected.Mcdaniels
RxJava approach is the only valid here. Can be also used in Java, Kotlin is not required. I wonder why Android api does not expose actual internet connection availability, system itself is informed about that - it's indicated by exclamation mark on wifi/4g icon.Tippets
@Tippets Once it exposes it, this answer will be drastically shortened. Maybe this is because the system also can't guarantee that (it has internet) via its similar checks. The first examples are primarily to understand what's going on (answer the actual question), but out of intererst: why would you consider e.g. the AsyncTask example not to be valid?Ochre
Because AsyncTask itself should be avoided. Never use AsyncTask. It's even deprecated now in api 30: developer.android.com/reference/android/os/AsyncTask This class was deprecated in API level 30. Use the standard java.util.concurrent or Kotlin concurrency utilities instead. I know this answer is old, but today you should forget AsyncTaskTippets
@Tippets Thank you for the feedback, I added a deprecation notice and reordered die "extra-examples". While deleting it would remove a helpful part of the answer, you are free to change this example to e.g. use concurrent or ScheduledFuture<?>.schedule(...) to still offer a fully valid vanilla Android example.Ochre
The argument -c was replaced by -n: "ping -n 1 google.com"Convention
Doesn't work on my phone. Both easy And advanced. Galaxy J7 MaxKipper
@MuhammadSaqib What was your solution ?Gamester
@Gamester I placed a static text file on my server returns 1. Mobile app first check internet availability with the help of native functions then it try to read that internet file.Mcdaniels
@MuhammadSaqib So basically you are making an api call to your server, if it is returning, you are assuming it is connected ?? How long you are waiting for your server file response ? 2 sec ? 3 sec ? We too are following the same approach now and we have decided to keep 3 sec for our api to respond, if not responding we will assume it is not connected truelyGamester
@Gamester 3 seconds aren't enough. I have set 10 seconds timeout with error message Unable to connect with our servers instead of You are not connected with internet and don't forget to check internet connection locally first.Mcdaniels
@Gamester again, It's totally depends on your needs.Mcdaniels
This approach (with pining a server) always returns false in my case even if I have Internet connection. I get the error "qemu_pipe_open_ns:62: Could not connect to the 'pipe:qemud:network' service: Invalid argument". Any idea how to fix this?Irredentist
The "ping" approach does not work on some devices, as mentioned in the answer. However, if these are new devices as well (previously only quite old ones like S3 etc.), I consider removing this approach completely, which were they? @MuhammadSaqib has the even better solution (here in comments), with not just establishing a connection, but getting a resource. Will be worked into the answer when I have time, or feel free to edit this answer, seems like quite good an improvement.Ochre
Don't forget about China blocing each and everything related to Google; Tests show they even force their own DNS servers, which intentionally returns wrong IP (for anything in their black-list).Landmeier
this solved our production app problem. Some of our drivers use hotspots and our sync process would throw errors before they were logged into the hotspotMonocycle
Using this solution can lead you to unexpected problems, pinging google server for internet connection at specific port can be prevented from device vendor, router you are connected to or even internet service provider.Gobioid
Should sock.close() be in a finally block?Downall
Z
297

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.

Zeta answered 4/1, 2010 at 20:1 Comment(5)
it is better to do a null check at cm.getActiveNetworkInfo() level it threw a null if no active network was available.Shackleton
see https://mcmap.net/q/11463/-can-you-explain-the-functionality-of-requestroutetohost-in-android for a deeper exaplanation about requestRouteToHost()Holofernes
I had to add the Context, in context.getSystemService or it doesn't work. I got my clue here androidhive.info/2012/07/…Aerobic
This solution will return true if you are connected to a WiFi hotspot, even if this hotspot does NOT have internet connectivity.Wellspring
getAllNetworkInfo() is deprecated in API level 29Procumbent
A
63

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

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Aristocrat answered 27/9, 2010 at 10:5 Comment(4)
This one should be definitely under the correct answer (wasted too much time figuring out what the hell is wrong).Matchboard
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.Toyatoyama
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)Appling
Be careful getActiveNetworkInfo() is deprecated in API level 29.Disconcert
B
48

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();
Booboo answered 13/10, 2009 at 15:38 Comment(3)
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...Olympian
There was a mistake in the EDIT EDIT section, I'd left out the requestRouteToHost() call. Re-read the answer now :)Booboo
requestRouteToHost has been deprecated.Washroom
G
47

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
Groceryman answered 27/4, 2011 at 11:41 Comment(17)
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.Toyatoyama
I like this method best since i can read the exception message to find out what exactly is going wrong. thanks.Carbuncle
@Toyatoyama 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'tSelfmastery
@dmmh Yeah, that's unfortunately true from what I've seen with the Android APIs. Perhaps a simple ping might be better, #3905858. 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.Toyatoyama
@Toyatoyama yeah, I've run into the issue as well. And sadly ping requires root privileges on most devices, so ugly solutions like the above are required. Really odd if you ask me...I am curious what the reason is for blocking such a common protocol, do you perhaps know?Selfmastery
@dmmh Wait, INetAddress requires root or the ping command? The later makes sense... sort of. Generally speaking, apps should NOT be allowed to execute commands. On Android 4.1 Jelly Bean and up apps cannot even read the system logs even with the READ_LOGS permission. I'll have to test this and see.Toyatoyama
ping is, see the first answer in your link :) Probably you are right about the command part, but that doesn't mean there couldn't have been other ways to send similar command via a interface, maybe the interface/ method/ class could limit the amount of ping commands requested in a certain timeframe, for a certain website or IP address. But Google seems to be a fan of blocking access to normal features (APIs, like GPS, NFC, mobile data, etc) in weird ways, instead of investigating an alternative waySelfmastery
the best answer for me. this one really checks if there is access to a specific host not like in the above answers just check if the device is connected to a network. this can still mean there is no internet connectionLumbricoid
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.Baiel
for this sentence's sake : "that is supposed to check the network access to a host name." this post should mark as answer.Locale
In China Google was blocked!!Tolentino
This gets executed only one. How to run this every 30secsBuskined
@therealprashant: You could make it recursive(ish), and also put isNetworkAvailable(h,30000); right at the end of the run() part of the code (meaning, after requesting network availability, it does the same 30s later. Some thoughts: 1) Probably better to rename it to something like regularNetworkAvailabilityCheck() to clarify what it is doing. 2) Check/Test for side effects, threating problems, etc. (at least try it with 3 or 4 secs requests and see what happens - memory usage, etc.) 3) possibly try some other page than m.google.com (which requests 34950 unicode chars atm).Ochre
@therealprashant: Oh sry, I just realised that the time variable in isNetworkAvailable was a timeout, and not a delay, .. Better do something separate like this: private Handler mHandler = new Handler(); private Runnable mRunnable = new Runnable() { @Override public void run() { isNetworkAvailable(h, 2000); mHandler.postDelayed(this, 30000); }}; and also kick it of with something like mHandler.postDelayed(mRunnable, 30000);Ochre
Done the same Thing..basically I need two Handler right?Buskined
@therealprashant: Yes, that is how I would do it. You could probably pack it into one handler, I would just make sure it is readable as well as "thread-safe" in this case though.Ochre
This works perfectly. This should be the accepted answer, since all the other solutions check network availibilty instead of internet connection. This is even better than the ping method, because ping doesn't work on certain networks because ICMP is disabled (e.g. mobile networks).Calutron
M
27

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;
    }
}
Macmacabre answered 11/1, 2011 at 10:29 Comment(0)
M
18

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;
}
Metaplasm answered 19/7, 2012 at 13:27 Comment(2)
Maybe you should replace 200 by HttpURLConnection.HTTP_OKGalvano
What if Google is down?Janellajanelle
D
13

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;
}
Duiker answered 7/3, 2014 at 16:57 Comment(2)
this is a great solution to check if a server si up, works really fine. thanks!Peyton
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.Keg
Q
13

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

Quintan answered 26/12, 2017 at 0:51 Comment(6)
Great question, its sad you dont have more points. This must be the correct answer.Driblet
I am new to android. though, This is well covered answer and it get more attention @7569106Floyfloyd
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() == 0Limicoline
your second option get crash i dont know whyWehrmacht
it freezes applicationWehrmacht
@nafeesahmed what does the error say when crash(see it in logcat)Quintan
O
11

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
         }
     }
  }
Oversell answered 31/3, 2020 at 18:35 Comment(5)
Din't work, not calling againZoophyte
@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.Oversell
@Oversell I didn't use it with ViewModel or LiveData but using simple coroutines even if you use repeat or while loop after an exception it seems this code is going to cancel the parent coroutine context.Ertha
simply do https://mcmap.net/q/11456/-helper-class-best-approach-androidCorsiglia
Can't Google just call this every few seconds in some shared process and notify all app via a BroadcastReceiver or something? It's crazy that we still have to do this in 2024.Welton
C
9

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://mcmap.net/q/11530/-android-check-internet-connection-duplicate

Claus answered 11/7, 2013 at 0:50 Comment(0)
K
8

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.

Kepner answered 19/9, 2012 at 8:10 Comment(1)
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!Seaborne
H
8

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;
}
Handyman answered 13/6, 2013 at 16:36 Comment(1)
+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.Wundt
T
7

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());
}}
Towns answered 25/7, 2012 at 3:56 Comment(5)
This answer can not work now, since we can not access network on main thread now.Sapphirine
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).Sapphirine
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder() .permitAll().build(); StrictMode.setThreadPolicy(policy); add these two lines two your program for avoiding network main thread exceptionTowns
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)Sapphirine
ya..you are right.. just i put this because this is also one of the way.Towns
O
6

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();
    }
Olympian answered 13/10, 2009 at 16:8 Comment(2)
It would be great if you had clarified if the IOException means no internet connection and how reliable it could be.Faint
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".Sauropod
C
6

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;
}
Campfire answered 13/2, 2012 at 7:34 Comment(0)
L
6

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)

Loser answered 25/11, 2012 at 11:59 Comment(0)
A
6

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;
    }
    }
Align answered 27/1, 2013 at 11:12 Comment(2)
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).Galvano
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.Galvano
M
6

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;
}
Madly answered 5/3, 2014 at 16:44 Comment(0)
C
6

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;
    }
Casiano answered 4/2, 2015 at 8:21 Comment(0)
L
6

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

Luigi answered 16/3, 2015 at 15:42 Comment(2)
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.Mariner
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.Consternate
B
6

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" />
Barnstorm answered 2/1, 2017 at 18:23 Comment(1)
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 connectionMannuela
F
5

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

Forgetful answered 18/7, 2012 at 17:6 Comment(0)
P
5

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();
}
Pignus answered 11/6, 2013 at 9:22 Comment(0)
P
5
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();
}

}
Paris answered 24/10, 2013 at 15:42 Comment(1)
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.Philps
C
5

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
}
Coburg answered 9/1, 2017 at 6:57 Comment(0)
K
4

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
    }
Kathernkatheryn answered 6/1, 2014 at 5:31 Comment(0)
S
4

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.

Shingle answered 31/1, 2014 at 2:55 Comment(0)
C
4

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);
            }
        });
    }
Commissionaire answered 6/9, 2016 at 10:47 Comment(2)
Better pack threading in your NetworkUtils and therefore "force" developer not to mis use your methodFilipino
To remove one extra if condition. if ((NetworkUtils.isInternetActiveWithPing() == NetworkUtils.STATUS_CONNECTED) || NetworkUtils.isInternetActiveWithInetAddress()) { //Do Network Operation } else { //Error Message }Copalite
H
4

Use this Kotlin Extension:

/**
 * Check whether network is available
 *
 * @param context
 * @return Whether device is connected to Network.
 */
fun Context.isNetworkAvailable(): Boolean {
    with(getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            //Device is running on Marshmallow or later Android OS.
            with(getNetworkCapabilities(activeNetwork)) {
                return hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || hasTransport(
                    NetworkCapabilities.TRANSPORT_CELLULAR
                )
            }
        } else {
            activeNetworkInfo?.let {
                // connected to the internet
                @Suppress("DEPRECATION")
                return listOf(ConnectivityManager.TYPE_WIFI, ConnectivityManager.TYPE_MOBILE).contains(it.type)
            }
        }
    }
    return false
}
Hexa answered 25/12, 2019 at 14:14 Comment(0)
A
3

Just create the following class which checks for an internet connection:

public class ConnectionStatus {

    private Context _context;

    public ConnectionStatus(Context context) {
        this._context = context;
    }

    public boolean isConnectionAvailable() {
        ConnectivityManager connectivity = (ConnectivityManager) _context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivity != null) {
            NetworkInfo[] info = connectivity.getAllNetworkInfo();
            if (info != null)
                for (int i = 0; i < info.length; i++)
                    if (info[i].getState() == NetworkInfo.State.CONNECTED) {
                        return true;
                    }
        }
        return false;
    }
}

This class simply contains a method which returns the boolean value of the connection status. Therefore in simple terms, if the method finds a valid connection to the Internet, the return value is true, otherwise false if no valid connection is found.

The following method in the MainActivity then calls the result from the method previously described, and prompts the user to act accordingly:

public void addListenerOnWifiButton() {
        Button btnWifi = (Button)findViewById(R.id.btnWifi);

        iia = new ConnectionStatus(getApplicationContext());

        isConnected = iia.isConnectionAvailable();
        if (!isConnected) {
            btnWifi.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
                    Toast.makeText(getBaseContext(), "Please connect to a hotspot",
                            Toast.LENGTH_SHORT).show();
                }
            });
        }
        else {
            btnWifi.setVisibility(4);
            warning.setText("This app may use your mobile data to update events and get their details.");
        }
    }

In the above code, if the result is false, (therefore there is no internet connection, the user is taken to the Android wi-fi panel, where he is prompted to connect to a wi-fi hotspot.

Aggy answered 4/9, 2014 at 11:51 Comment(0)
S
3

If you are using API 23 or above, you can now check whether or not internet is active using NetworkCapabilities.NET_CAPABILITY_VALIDATED, which is backed by Google's own ping service.

ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
    @Override
    public void onLost(Network network) {
        // handle network lost
    }

    @Override
    public void onAvailable(Network network) {
        ConnectivityManager cm = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = cm.getNetworkInfo(network);
        boolean isConnected = (info != null && info.isConnectedOrConnecting());

        if (isConnected) {
            NetworkCapabilities nc = cm.getNetworkCapabilities(network);
            if (nc != null) {
                boolean isInternetValid = nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
                if (isInternetValid) {
                    // internet is valid
                }
            }
        }
    }
};

NetworkRequest request = new NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build();
ConnectivityManager connectivityManager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
connectivityManager.registerNetworkCallback(request, networkCallback);
Sharpshooter answered 15/4, 2017 at 0:9 Comment(3)
I've tried this and although the call to onAvailable and isConnected is true, NetworkCapabilities is returning false. I think there is a timing issue if you do it this way. However, if this worked, then it would be the right way to check that your network is actually connected to the internet.Phenice
Yes, it seems there is a timing issue, as I described in one of the comments here: #36359031Discovert
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.Discovert
C
3

The most Simplest solution would be

In most cases one will only check internet connection if he/she wants to connect to the remote server so the simple and best solution would be pinging your server as following.

public boolean isConnected() {
    final String command = "ping -c 1 yourExmapleDomain.com";
    boolean isConnected = false;
    try {
        isConnected = Runtime.getRuntime().exec(command).waitFor() == 0;
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return isConnected;
}
Carycaryatid answered 29/3, 2019 at 17:54 Comment(1)
Can you tell me what is -c 1 meaning?Pearle
L
2
public boolean isOnline() {
    boolean var = false;
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    if ( cm.getActiveNetworkInfo() != null ) {
        var = true;
    }
    return var;
} 

I have done it this way. A little bit shorter and more readable I guess.

Cheers!

Saiyan

Lorenz answered 19/11, 2011 at 3:4 Comment(3)
How come you don't call .isConnectedOrConnecting() ?Guilford
I just didn´t do it :) I just check if the ConectivityManager has some network info. If it doesn´t, its because it is not connected.Lorenz
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.Philps
T
2
public static boolean isNetworkAvailable(Context ctx) {
ConnectivityManager connMgr = (ConnectivityManager)ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
if(connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected() ||
    connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isConnected()){
        return true;
}

return false;
 } 

user this

Tropophilous answered 3/10, 2013 at 10:22 Comment(0)
A
2

Its so great to have more then one way to code. Here is my example.

ConnectivityManager icheck = getSystemService(Context.CONNECTIVITY_SERVICE);

TextView tv = findViewById(R.id.textView1);

boolean wifi = icheck.getActiveNetworkInfo() != null;
        if(wifi) {
        tv.setText("Internet is on.");  
        } else {
             tv.setText("Internet is off.");    
        }

Good luck.

Anapest answered 30/6, 2014 at 11:23 Comment(0)
G
2

I have tried with almost 5+ different android approaches and found this is the best solution provided by google especially for android:

  try {
  HttpURLConnection urlConnection = (HttpURLConnection)
  (new URL("http://clients3.google.com/generate_204")
  .openConnection());
  urlConnection.setRequestProperty("User-Agent", "Android");
  urlConnection.setRequestProperty("Connection", "close");
  urlConnection.setConnectTimeout(1500);
  urlConnection.connect();
  if (urlConnection.getResponseCode() == 204 &&
  urlConnection.getContentLength() == 0) {
  Log.d("Network Checker", "Successfully connected to internet");
  return true;
  }
  } catch (IOException e) {
  Log.e("Network Checker", "Error checking internet connection", e);
  }

It's faster , efficient and accurate than any other available solution.

Gotland answered 29/9, 2016 at 9:27 Comment(0)
K
2

As Android doc suggest, after

getActiveNetworkInfo() was deprecated in Android 10. Use NetworkCallbacks instead for apps that target Android 10 (API level 29) and higher.

So below is the way which we are using to check network connection Currently:

val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val activeNetwork: NetworkInfo? = cm.activeNetworkInfo
val isConnected: Boolean = activeNetwork?.isConnectedOrConnecting == true

The new way for checking internet connection using NetworkCallbacks

Step 1:

    private lateinit var connectivityManager:ConnectivityManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...
        connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    }

Step 2: Create Callback:

private val callback = object : ConnectivityManager.NetworkCallback() {
    override fun onAvailable(network: Network) {
        super.onAvailable(network)
        Timber.e("Network:onAvailable")
    }

    override fun onLost(network: Network) {
        super.onLost(network)
        Timber.e("Network:onLost")
    }

}

Step 3: Register and UnRegister CallBack:

private fun registerNetworkCallback() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        connectivityManager.registerDefaultNetworkCallback(callback)
    } else {
        // Old way to check network connection
    }
}

override fun onStop() {
    unRegisterNetworkCallback()
    super.onStop()
}

private fun unRegisterNetworkCallback() {
    connectivityManager.unregisterNetworkCallback(callback)
}

Checkout update details on below link:

https://developer.android.com/training/monitoring-device-state/connectivity-status-type

Katzenjammer answered 17/12, 2019 at 5:19 Comment(0)
A
2

I see a lot of outdated answers here, so I decided to add mine to the mix.

As of Android 10 (API level 29) getActiveNetworkInfo() was deprecated and Google recommends that we use NetworkCallbacks instead for apps that target Android 10 and higher.

The documentation on Reading network state gives some info on how to use the NetworkCallback but I didn't manage to find a good code example with the whole thing working, so here's the code I came up with, that we use in our app:

import android.content.Context
import android.net.ConnectivityManager
import android.net.LinkProperties
import android.net.Network
import android.net.NetworkCapabilities
import com.fieldontrack.kmm.common.network.ConnectivityMonitor
import com.fieldontrack.kmm.entities.connectivity.NetworkType
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow

class ConnectivityMonitorImpl(appContext: Context) : ConnectivityMonitor {
    private val connectivityManager = appContext.getSystemService(ConnectivityManager::class.java)
    private val networkCallback = object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) =
            connectivityManager.getNetworkCapabilities(network)?.let { networkCapabilities ->
                updateConnectionStatus(networkCapabilities = networkCapabilities)
                updateNetworkType(networkCapabilities = networkCapabilities)
            } ?: run {
                _isConnectedState.value = true
            }

        override fun onLost(network: Network) {
            // Do not check for NetworkCapabilities here, as they might be wrong.
            // If we get this callback, we're certain that we've lost connection.
            _isConnectedState.value = false
            _networkTypeState.value = NetworkType.Unknown
        }

        override fun onCapabilitiesChanged(
            network: Network,
            networkCapabilities: NetworkCapabilities
        ) {
            updateConnectionStatus(networkCapabilities = networkCapabilities)
            updateNetworkType(networkCapabilities = networkCapabilities)
        }

        override fun onLinkPropertiesChanged(
            network: Network,
            linkProperties: LinkProperties
        ) = Unit
    }
    private val _isConnectedState = MutableStateFlow(false)
    private val _networkTypeState = MutableStateFlow(NetworkType.Unknown)

    override val isConnectedState: StateFlow<Boolean> = _isConnectedState
    override val networkTypeState: StateFlow<NetworkType> = _networkTypeState

    override val isConnected: Boolean
        get() = _isConnectedState.value

    override val networkType: NetworkType
        get() = _networkTypeState.value

    init {
        startMonitoring()
    }

    override fun startMonitoring() =
        connectivityManager.registerDefaultNetworkCallback(networkCallback)

    override fun stopMonitoring() =
        connectivityManager.unregisterNetworkCallback(networkCallback)

    private fun updateConnectionStatus(networkCapabilities: NetworkCapabilities) {
        val isConnected =
            networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)

        _isConnectedState.value = isConnected
    }

    private fun updateNetworkType(networkCapabilities: NetworkCapabilities) {
        val networkType = when {
            networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> NetworkType.WiFi
            networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> NetworkType.Cellular
            else -> NetworkType.Unknown
        }

        _networkTypeState.value = networkType
    }
}

The ConnectivityMonitor interface is pretty simple:

interface ConnectivityMonitor {
    val isConnected: Boolean
    val networkType: NetworkType

    val isConnectedState: StateFlow<Boolean>
    val networkTypeState: StateFlow<NetworkType>
    
    fun startMonitoring()
    fun stopMonitoring()
}

And NetworkType is just a simple enum:

enum class NetworkType { Unknown, Cellular, WiFi }

As far as I've tested this works whether the App is in background or foreground.

Antipodal answered 19/12, 2022 at 16:24 Comment(0)
F
1

This code will help you find the internet is on or not.

public final boolean isInternetOn() {
        ConnectivityManager conMgr = (ConnectivityManager) this.con
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = conMgr.getActiveNetworkInfo();
        return (info != null && info.isConnected());
}

Also, you should provide the following permissions

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Flub answered 8/3, 2016 at 5:2 Comment(1)
Nice way to check network availability. But how to check internet access?Calutron
C
1

If you need to check for the internet connection, use this method using ping to the server:

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

Either you can use check through using port

public boolean checkIntCON() {
    try {
        Socket sock = new Socket();
        SocketAddress sockaddr = new InetSocketAddress("8.8.8.8", 80); 
        // port will change according to protocols

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

        return true;
    } catch (IOException e) { return false; }
}
Contrabandist answered 21/9, 2017 at 9:19 Comment(0)
M
1

This is simplest and easy way to check internet connection for wifi and mobile data.

public static boolean isConnected(Activity _context) {
        if (_context != null) {
            ConnectivityManager connMgr = (ConnectivityManager) _context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeInfo = connMgr.getActiveNetworkInfo();
            if (activeInfo != null && activeInfo.isConnected()) {
                boolean wifiConnected = activeInfo.getType() == ConnectivityManager.TYPE_WIFI;
                boolean mobileConnected = activeInfo.getType() == ConnectivityManager.TYPE_MOBILE;

                if (wifiConnected || mobileConnected) {
                    Log.d(TAG, "Wifi Connected ");
                    return true;
                } else {
                    showAlert(_context,_context.getString(R.string.err_no_internet));
                    return false;
                }
            } else {
                showAlert(_context,_context.getString(R.string.err_no_internet));
                return false;
            }
        } else {
            Log.e(TAG, "networkConnectivity: Context NULL");

        }
        return false;
    }
Moor answered 26/3, 2018 at 12:14 Comment(0)
T
1
 public static boolean isNetworkAvailable(Context context) {
    boolean flag = checkNetworkAvailable(context);

    if (!flag) {
        Log.d("", "No network available!");
    } 
    return flag;
}


private static boolean checkNetworkAvailable(Context context) {
    ConnectivityManager connectivityManager
            = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
    return activeNetworkInfo != null;
}
Tarriance answered 21/6, 2018 at 6:49 Comment(4)
While this code snippet may be the solution, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.Weimaraner
I am using this Code and I want to call the isNetworkAvailable Function in another static function, but I don't know which context Parameter to use because it says that the function Needs to be unstatic to use myclass.this Can you help me with my problemStartling
if you put this method in same class than u can remove static keywordTarriance
@GautamSurani I think I Need the static Keyword because I am using this functino in a class and in the MainActivityStartling
P
1

Use method:

private fun isInternetAvailable(context: Context): Boolean {
    (context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).run {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            return this.getNetworkCapabilities(this.activeNetwork)?.hasCapability(
                NetworkCapabilities.NET_CAPABILITY_INTERNET
            ) ?: false
        } else {
            (@Suppress("DEPRECATION")
            return this.activeNetworkInfo?.isConnected ?: false)
        }
    }
}

And permissions required:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Prejudice answered 29/12, 2019 at 19:55 Comment(1)
NetworkCapabilities.NET_CAPABILITY_INTERNET doesn't necessarily mean the device has internet access. For example, if your network connection loses internet access, onCapabilitiesChanged() never gets called.Ruphina
L
1

Kotlin implementation

/**
* Function that uses ping, takes server name or ip as argument.
*
* @return [Double.MAX_VALUE] if server is not reachable. Average RTT if the server is reachable.
*
* Success output example
*
* PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
* 64 bytes from 8.8.8.8: icmp_seq=1 ttl=254 time=172 ms
* 64 bytes from 8.8.8.8: icmp_seq=2 ttl=254 time=166 ms
* 64 bytes from 8.8.8.8: icmp_seq=3 ttl=254 time=167 ms
* 64 bytes from 8.8.8.8: icmp_seq=4 ttl=254 time=172 ms
* 64 bytes from 8.8.8.8: icmp_seq=5 ttl=254 time=167 ms

* --- 8.8.8.8 ping statistics ---
* 5 packets transmitted, 5 received, 0% packet loss, time 4011ms
* rtt min/avg/max/mdev = 166.470/169.313/172.322/2.539 ms
*          |________________________|
* value to parse using it.split('=')[1].trim().split(' ')[0].trim().split('/')[1].toDouble()
*/
@ExperimentalStdlibApi
fun pingServerAverageRtt(host: String): Double {

    var aveRtt: Double = Double.MAX_VALUE

    try {
        // execute the command on the environment interface, timeout is set as 0.2 to get response faster.
        val pingProcess: Process = Runtime.getRuntime().exec("/system/bin/ping -i 0.2 -c 5 $host")
        // gets the input stream to get the output of the executed command
        val bufferedReader = BufferedReader(InputStreamReader(pingProcess.inputStream))

        bufferedReader.forEachLine {
            if (it.isNotEmpty() && it.contains("min/avg/max/mdev")) {  // when we get to the last line of executed ping command
                aveRtt = it.split('=')[1].trim()
                        .split(' ')[0].trim()
                        .split('/')[1].toDouble()
            }
        }
    } catch (e: IOException) {
        e.printStackTrace()
    }

    return aveRtt
}

Usage example


val latency = pingServerAverageRtt(ipString)
if (latency != Double.MAX_VALUE) { 
    //server reachable
} else {
    //server not reachable
}
Leslee answered 24/8, 2020 at 2:17 Comment(0)
K
1

If you're using Firebase you could use this.

Java:

DatabaseReference connectedRef = FirebaseDatabase.getInstance().getReference(".info/connected");
connectedRef.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot snapshot) {
        boolean connected = snapshot.getValue(Boolean.class);
        if (connected) {
            Log.d(TAG, "connected");
        } else {
            Log.d(TAG, "not connected");
        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError error) {
        Log.w(TAG, "Listener was cancelled");
    }
});

Kotlin:

val connectedRef = Firebase.database.getReference(".info/connected")
connectedRef.addValueEventListener(object : ValueEventListener {
    override fun onDataChange(snapshot: DataSnapshot) {
        val connected = snapshot.getValue(Boolean::class.java) ?: false
        if (connected) {
            Log.d(TAG, "connected")
        } else {
            Log.d(TAG, "not connected")
        }
    }

    override fun onCancelled(error: DatabaseError) {
        Log.w(TAG, "Listener was cancelled")
    }
})
Knockknee answered 30/11, 2021 at 1:21 Comment(0)
B
0
if(isConnected()){
                Toast.makeText(getApplication(),"Thank you",Toast.LENGTH_SHORT).show();
        }
        else{

            AlertDialog.Builder builder =
                    new AlertDialog.Builder(this, R.style.AppCompatAlertDialogStyle);
            builder.setTitle("Amar Bhat");
            builder.setMessage("Oops...You are not connected to Internet!!!");
            builder.setPositiveButton("OK", null);
            builder.setNegativeButton("Cancel", null);
            builder.show();
            //Toast.makeText(getApplication(),"You are not connected",Toast.LENGTH_SHORT).show();
        }




//And outside the class define isConnected()

 public boolean isConnected(){
        ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Activity.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected())
            return true;
        else
            return false;
    }

// In minifest add these permission
<uses-permission android:name="android.permission.INTERNET" />

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Balneology answered 17/11, 2015 at 5:25 Comment(0)
R
0

Don't forget to add this permissions to your manifest :

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Radioelement answered 17/11, 2015 at 14:39 Comment(0)
J
0

Most of the answers in this thread only check if there is a connection available but do not check if that connection work, others answers are not device wide, my solution should work on every device.

You can drop my code in your main activity before launching the app, it will quickly determine if there is an actual internet connectivity, if there is the dialog will be immediately dropped and the app will be launched, if not an alert will pop up saying the app needs internet connectivity to work.

final AlertDialog alertDialog = new AlertDialog.Builder(this).create();
        alertDialog.setTitle("Checking Connection");
        alertDialog.setMessage("Checking...");
        alertDialog.show();
        new CountDownTimer(5000, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {

                new Thread(new Runnable() {
                    public void run() {
                        try {
                            URL url = new URL("http://web.mit.edu/");
                            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                            connection.setRequestMethod("GET");
                            connection.setConnectTimeout(5000);
                            isConnected = connection.getResponseCode() == HttpURLConnection.HTTP_OK;
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }).start();

                if (isConnected == false){
                    alertDialog.setMessage("Try " +  (5 - millisUntilFinished/1000) + " of 5.");
                } else {
                    alertDialog.dismiss();
                }
            }
            @Override
            public void onFinish() {
                if (isConnected == false) {
                    alertDialog.dismiss();
                    new AlertDialog.Builder(activity)
                            .setTitle("No Internet")
                            .setMessage("Please connect to Internet first.")
                            .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int which) {
                                    // kill the app?
                                }
                            })
                            .setIcon(android.R.drawable.ic_dialog_alert)
                            .show();
                } else {
                    // Launch the app
                }
            }
        }.start();
Jacobite answered 2/8, 2016 at 9:14 Comment(0)
M
0
public boolean isNetworkAvailable(Context context) {
    ConnectivityManager connectivityManager
            = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
    return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}

Here is the permission that you need :

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Mcminn answered 17/8, 2016 at 13:56 Comment(0)
L
0

You can check internet with below code as well:

 public class CheckInternetConnection {
        public Context context = null;

        public CheckInternetConnection(Context ctx) {
            this.context = ctx;
        }

        public boolean CheckInternet() {
            return isOnline();
        }
        public Boolean isOnline() 
        {
            try {
                if(isNetAvailable(context))
                    return true;
                else
                {
                    try {
                        URL url = new URL("http://www.google.com");
                        HttpURLConnection urlc = (HttpURLConnection) url
                                .openConnection();
                        urlc.setRequestProperty("User-Agent", "Test");
                        urlc.setRequestProperty("Connection", "close");
                        urlc.setConnectTimeout(3000); // This is time limit if the
                        // connection time limit
                        try {
                            urlc.connect();
                            Log.e("TAG", " urlc ----------" + urlc.getResponseCode());
                            if (urlc.getResponseCode() == 200) {
                                return true;
                            }
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    } catch (MalformedURLException e1) {
                        e1.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }

            return false;        
        }

         public synchronized static boolean isNetAvailable(Context context){

             try{
             boolean isNetAvailable=false;
             if ( context != null )
             {
                 ConnectivityManager mgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
                 if ( mgr != null )
                 {
                     boolean mobileNetwork = false;
                     boolean wifiNetwork = false;
                     boolean wiMaxNetwork = false;

                     boolean mobileNetworkConnecetd = false;
                     boolean wifiNetworkConnecetd = false;
                     boolean wiMaxNetworkConnected = false;

                     NetworkInfo mobileInfo = mgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
                     NetworkInfo wifiInfo = mgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
                     NetworkInfo wiMaxInfo = mgr.getNetworkInfo(ConnectivityManager.TYPE_WIMAX);

                     if ( mobileInfo != null )
                         mobileNetwork = mobileInfo.isAvailable();                   

                     if ( wifiInfo != null )
                         wifiNetwork = wifiInfo.isAvailable();

                     if(wiMaxInfo != null)
                         wiMaxNetwork = wiMaxInfo.isAvailable();

                     if(wifiNetwork == true)
                         wifiNetworkConnecetd = wifiInfo.isConnectedOrConnecting();
                     if(mobileNetwork == true)
                         mobileNetworkConnecetd = mobileInfo.isConnectedOrConnecting();
                     if(wiMaxNetwork == true)
                         wiMaxNetworkConnected = wiMaxInfo.isConnectedOrConnecting();

                     isNetAvailable = ( mobileNetworkConnecetd || wifiNetworkConnecetd || wiMaxNetworkConnected );
                 }
             }
             return isNetAvailable;
             }catch(NullPointerException e)
             {
                 return false;
             }catch(Exception e)
             {
                 return false;
             }
         }


    }
Lyon answered 17/8, 2016 at 14:0 Comment(0)
R
0

Here is some modern code that uses an AsynTask to get around an issue where android crashes when you try and connect on the main thread and introduces an alert with a rinse and repeat option for the user.

class TestInternet extends AsyncTask<Void, Void, Boolean> {
    @Override
    protected Boolean doInBackground(Void... params) {
        try {
            URL url = new URL("http://www.google.com");
            HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
            urlc.setConnectTimeout(3000);
            urlc.connect();
            if (urlc.getResponseCode() == 200) {
                return true;
            }
        } catch (MalformedURLException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
            return false;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        }
        return false;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        if (!result) { // code if not connected
            AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
            builder.setMessage("An internet connection is required.");
            builder.setCancelable(false);

            builder.setPositiveButton(
                    "TRY AGAIN",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                            new TestInternet().execute();
                        }
                    });


            AlertDialog alert11 = builder.create();
            alert11.show();
        } else { // code if connected
            doMyStuff();
        }
    }
}

...

new TestInternet().execute();
Reynaud answered 13/11, 2016 at 19:17 Comment(0)
R
0

Instead of checking WIFI connection or Mobile data connection, try hitting any hosted domain. So that, you can check whether the WIFI/Mobile connection has ability to connect public Internet.

The below will return if your mobile device is able to connect with the public domain provided.

boolean isReachable()
        {
            boolean connected = false;
            String instanceURL = "Your trusted domain name";
            Socket socket;
            try {
                socket = new Socket();
                SocketAddress socketAddress = new InetSocketAddress(instanceURL, 80);
                socket.connect(socketAddress, 5000);
                if (socket.isConnected()) {
                    connected = true;
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                socket = null;
            }
            return connected;
        }

Hope it will be helpful..

Reprobation answered 21/2, 2017 at 11:54 Comment(0)
G
0

Android provides ConnectivityManager class to know about the internet connection status. The following method will be very useful to know internet connection state.

First add the INTERNET and ACCESS_NETWORK_STATE permission to AndroidManifest.xml

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

Then use the below method to check if the device is connected to internet or not. This method will return true if the device is connected to internet.

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

Reference Link :- http://www.androidtutorialshub.com/android-check-internet-connection-status/

Geometrize answered 10/5, 2017 at 10:6 Comment(0)
G
0

Here is the optimal method for checking internet connection. What this method does is perform a series of checks "is the phone not in airplane mode, is the phone connected to a network, etc". If all the checks return true, the method will then download a file from the internet and see if the contents matches an expected value.

The benefits of this method compared to other methods that ping a server to check for internet connection are:

  1. The Android runtime varies on different phones - so you may not always be able to execute those commands, as shown here: Why does ping works on some devices and not others?

  2. Pinging a server doesn't always work because of login pages/re-directs on wifi networks which can give the false impression of a connection.

This answer is written in Kotlin and uses the Fuel library to download a file from the internet with the methodfetchUrlAsString, but any library can be substituted as long as you make sure your HTTP request is not cached. Think of showConnectionWarning() and hideConnectionWarning() as equivalent to internet connection status = false and internet connection status = true respectively.

private val networkReceiver = object : BroadcastReceiver() {

    override fun onReceive(context: Context?, intent: Intent?) {

        val activeNetworkInfo = (context?.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).activeNetworkInfo

        if (activeNetworkInfo != null) {
            if (activeNetworkInfo.isConnectedOrConnecting) {
                //Launches a coroutine to fetch file asynchronously 
                launch {
                    try {
                        //Downloads file from url on the internet - use any library you want here.  
                        val connectionStatus = fetchUrlAsString(<url_for_file_on_internet>)
                        //check if the contents of the file is as expected
                        if (connectionStatus == "Connected To Database") {
                            hideConnectionWarning()
                        } else {
                            showConnectionWarning()
                        }
                    } catch (e: Exception) {
                        //Catches an exception - fetchUrlAsString only throws an exception if there is no internet 
                        showConnectionWarning()
                    }
                }
            } else {
                showConnectionWarning()
            }
        } else {
            showConnectionWarning()
        }
    }
}

private suspend fun fetchUrlAsString(url: String): String = suspendCoroutine { cont ->
    url.httpGet().header(Pair("pragma", "no-cache"), Pair("cache-control", "no-cache")).responseString { _, _, result ->

        when (result) {
            is Result.Failure -> {
                cont.resumeWithException(result.getException())
            }
            is Result.Success -> {
                cont.resume(result.value)
            }
        }

    }
}

You will need the following permissions:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
Gefell answered 10/7, 2018 at 1:42 Comment(0)
J
0

Here is the Kotlin version I use for reachability checking,

Kotlin MyReachability

object MyReachability {

    private val REACHABILITY_SERVER = "http://google.com" // can be any URL you want

    private fun hasNetworkAvailable(context: Context): Boolean {
        val service = Context.CONNECTIVITY_SERVICE
        val manager = context.getSystemService(service) as ConnectivityManager?
        val network = manager?.activeNetworkInfo
        Log.d(classTag, "hasNetworkAvailable: ${(network != null)}")
        return (network != null)
    }

    fun hasInternetConnected(context: Context): Boolean {
        if (hasNetworkAvailable(context)) {
            try {
                val connection = URL(REACHABILITY_SERVER).openConnection() as HttpURLConnection
                connection.setRequestProperty("User-Agent", "Test")
                connection.setRequestProperty("Connection", "close")
                connection.connectTimeout = 1500
                connection.connect()
                Log.d(classTag, "hasInternetConnected: ${(connection.responseCode == 200)}")
                return (connection.responseCode == 200)
            } catch (e: IOException) {
                Log.e(classTag, "Error checking internet connection", e)
            }
        } else {
            Log.w(classTag, "No network available!")
        }
        Log.d(classTag, "hasInternetConnected: false")
        return false
    }
}

You can even pass the REACHABILITY_SERVER as param based on policy and restrictions, for example when you are in china you can check https://baidu.com rather https://google.com.

Calling example,

val webLoaderThread = Thread {
   if (MyReachability.hasInternetConnected(this)){
       runOnUiThread {
           //mWebView.loadUrl(LANDING_SERVER) // connected
       }
   } else {
       runOnUiThread {
           //showDialogNoNetwork() // not connected
       }
   }
}
webLoaderThread.start()

Android permissions

Dont forget to add these below permissions to your AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Joubert answered 2/7, 2019 at 5:27 Comment(0)
S
0

Using the following method to check internet connectivity, also ConnectivityManager.getActiveNetworkInfo() is deprecated in API 28

@Suppress("DEPRECATION")
fun isNetworkConnected(context: Context): Boolean {
    val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
    return cm?.run {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            cm.getNetworkCapabilities(cm.activeNetwork)?.run {
                when {
                    hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
                    hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
                    hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
                    else -> false
                }
            }
        } else {
            cm.activeNetworkInfo?.run {
                when (type) {
                    ConnectivityManager.TYPE_WIFI -> true
                    ConnectivityManager.TYPE_MOBILE -> true
                    else -> false
                }
            }
        }
    } ?: false

}

Also add the following permission to the manifest

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

hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) is used for apps developed for Android TV where TV can be directly connected to Ethernet

Seacock answered 6/12, 2019 at 12:2 Comment(0)
J
0

This my workaround to solve this problem and check the valid internet connection because as they said that Network info class cannot give you the expected result and it may return true when network connected but no internet.

So this my COMPLETE WORKAROUND based on @Levite Answer:

First you must have AsynckTask for checking Network availability and this is mine:

public class Connectivity {
 private static final String TAG = "Connectivity";
private static boolean hasConnected = false, hasChecked = false;
private InternetListener internetListener;
private Activity activity;

public Connectivity(InternetListener internetListener, Activity activity) {
    this.internetListener = internetListener;
    this.activity = activity;
}

public void startInternetListener() {


    CheckURL checkURL = new CheckURL(activity);

    checkURL.execute();

    long startTime = System.currentTimeMillis();

    while (true) {
        if (hasChecked && hasConnected) {
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    internetListener.onConnected();
                }
            });

            checkURL.cancel(true);
            return;
        }

        // check if time
        if (System.currentTimeMillis() - startTime >= 1000) {
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    internetListener.onDisconnected();
                }
            });


            checkURL.cancel(true);
            return;
        }
    }

    //return hasConnected;
}


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

    private Activity activity;

    public CheckURL(Activity activity) {
        this.activity = activity;
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        if (!isNetWorkAvailable(activity)) {
            Log.i(TAG, "Internet not available!");
            return false;
        }

        int timeoutMs = 3000;

        try {
            Socket sock = new Socket();
            SocketAddress sockaddr = new InetSocketAddress("8.8.8.8", 53);
            sock.connect(sockaddr, timeoutMs);
            sock.close();
            Log.i(TAG, "Internet available :)");
            return true;

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

    }

    @Override
    protected void onPostExecute(Boolean result) {
        hasChecked = true;
        hasConnected = result;
        super.onPostExecute(result);}}
     

private static final String TAG = "Connectivity";


private static boolean isNetWorkAvailable(Activity activity) {

    ConnectivityManager connectivityManager =
            (ConnectivityManager) 
   activity.getSystemService(Activity.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo =
            null;
    if (connectivityManager != null) {
        networkInfo = 
   connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
    }
    boolean isConnected;
    boolean isWifiAvailable = false;
    if (networkInfo != null) {
        isWifiAvailable = networkInfo.isAvailable();
    }
    boolean isWifiConnected = false;
    if (networkInfo != null) {
        isWifiConnected = networkInfo.isConnected();
    }
    if (connectivityManager != null) {
        networkInfo =
                connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
    }
    boolean isMobileAvailable = false;
    if (networkInfo != null) {
        isMobileAvailable = networkInfo.isAvailable();
    }
    boolean isMobileConnected = false;
    if (networkInfo != null) {
        isMobileConnected = networkInfo.isConnected();
    }
    isConnected = (isMobileAvailable && isMobileConnected) ||
            (isWifiAvailable && isWifiConnected);
    return (isConnected);}
    }}



private static boolean isNetWorkAvailable(Context context) {

    ConnectivityManager connectivityManager =
            (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo =
            null;
    if (connectivityManager != null) {
        networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
    }
    boolean isConnected;
    boolean isWifiAvailable = false;
    if (networkInfo != null) {
        isWifiAvailable = networkInfo.isAvailable();
    }
    boolean isWifiConnected = false;
    if (networkInfo != null) {
        isWifiConnected = networkInfo.isConnected();
    }
    if (connectivityManager != null) {
        networkInfo =
                connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
    }
    boolean isMobileAvailable = false;
    if (networkInfo != null) {
        isMobileAvailable = networkInfo.isAvailable();
    }
    boolean isMobileConnected = false;
    if (networkInfo != null) {
        isMobileConnected = networkInfo.isConnected();
    }
    isConnected = (isMobileAvailable && isMobileConnected) ||
            (isWifiAvailable && isWifiConnected);
    return (isConnected);

}

}

After that you should create another thread to start AscnkTask And listen for result with the InternetListener.

public interface InternetListener {
void onConnected();
void onDisconnected();
}

And the Thread that is waiting for AsynckTask result you can put it in Utility class:

 private static Thread thread;

public static void startNetworkListener(Context context, InternetListener 
    internetListener) {

    if (thread == null){
        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                new Connectivity(internetListener,context).startInternetListener();
            }
        });
    }

    thread.start();
 }

Finally call the startNetworkListener() method and listen for result.

example in activity from My Utils.java class :

     Utils.startNetworkListener(this, new InternetListener() {
        @Override
        public void onConnected() {
           // do your work when internet available. 
        }

        @Override
        public void onDisconnected() {
          // do your work when no internet available. 
        }
    });

Happy Coding :).

Jodhpurs answered 8/9, 2020 at 14:9 Comment(0)
U
0

If you want to show an alert when connection lost. You can use below method.

This method use to check connection one time. First you have to create this one in your class.

private boolean isNetworkConnected() {
        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        if(!(cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnected())){
            showNetworkDialog();
            return false;
        }
        return true;
    }

Create this method in your class as connection listener.

private void ConnectionCheck(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkRequest networkRequest = new NetworkRequest.Builder().build();
            connectivityManager.registerNetworkCallback(networkRequest, new ConnectivityManager.NetworkCallback() {
                @Override
                public void onAvailable(Network network) {
                    super.onAvailable(network);
                    Log.i("Tag", "active connection");
                }

                @Override
                public void onLost(Network network) {
                    super.onLost(network);
                    Log.i("Tag", "losing active connection");
                    isNetworkConnected();
                }
            });
        }
    }

For showing dialog, you may create showDialog() method.

private void showNetworkDialog(){
    new AlertDialog.Builder(MainActivity.this)
            .setIcon(android.R.drawable.ic_dialog_alert)
            .setTitle("Connection lost?")
            .setMessage("Please check your internet connection!")
            .setCancelable(false)
            .setPositiveButton("Exit", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    finish();
                }
            })
            .setNegativeButton("Retry", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    isNetworkConnected();
                }
            })
            .show();
}

Finally you can call this method in onCreate() method.

if(isNetworkConnected()){
            ConnectionCheck();
        }

in Manifest file you have to mention permission.

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Unmeasured answered 7/3, 2021 at 13:45 Comment(0)
S
0

Code :

    fun isInternetConnection(): Boolean {
    var returnVal = false
    thread {
        returnVal = try {
            khttp.get("https://www.google.com/")
            true
        }catch (e:Exception){
            false
        }
    }.join()
    return returnVal
}

Gradle:

implementation 'io.karn:khttp-android:0.1.0'

I use khttp because it's so easy to use.

So here in the above code if it successfully connects to google.com, it returns true else false. It's so simple. I don't understand why everyone has to code like lengthy lines of code even for a simple thing like this.

Sheepshearing answered 1/6, 2021 at 10:8 Comment(0)
E
0

Here is a simple solution to ensure your app has internet access:

static final String CHECK_INTERNET_ACCESS_URL = "https://www.google.com";

public static void isInternetAccessWorking(Context context) {

    StringRequest stringRequest = new StringRequest(Request.Method.GET, CHECK_INTERNET_ACCESS_URL,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    // Internet access is OK
                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            // NO internet access
        }
    });

    Volley.newRequestQueue(context).add(stringRequest);
}

This solution uses Android's Volley lib, which must be declared in build.gradle:

implementation 'com.android.volley:volley:1.1.1'
Elenore answered 29/9, 2022 at 9:18 Comment(0)
E
0

Jetpack Compose/Kotlin

Based on Levite's answer one could use this Composable in Jetpack Compose:

val DNS_SERVERS = listOf("8.8.8.8", "1.1.1.1", "4.2.2.4")
const val INTERNET_CHECK_DELAY = 3000L
@Composable
fun InternetAwareComposable(
    dnsServers: List<String> = DNS_SERVERS,
    delay: Long = INTERNET_CHECK_DELAY,
    successContent: (@Composable () -> Unit)? = null,
    errorContent: (@Composable () -> Unit)? = null,
    onlineChanged: ((Boolean) -> Unit)? = null
) {
    suspend fun dnsAccessible(
        dnsServer: String
    ) = try {
        withContext(Dispatchers.IO) {
            Runtime.getRuntime().exec("/system/bin/ping -c 1 $dnsServer").waitFor()
        } == 0
    } catch (e: Exception) {
        false
    }

    var isOnline by remember { mutableStateOf(false) }
    LaunchedEffect(Unit) {
        while (true) {
            isOnline = dnsServers.any { dnsAccessible(it) }
            onlineChanged?.invoke(isOnline)
            delay(delay)
        }
    }
    if (isOnline) successContent?.invoke()
    else errorContent?.invoke()
}
Ertha answered 10/11, 2022 at 18:46 Comment(0)
T
-1

In kotlin:

class UtilityMethods {
companion object {
    fun isConnected(activity: Activity): Boolean {
        val connectivityManager: ConnectivityManager =
                activity.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        return null != connectivityManager.activeNetworkInfo
    }
}}

Invoke isConnected inside Activity class as:

UtilityMethods.isConnected(this)

Inside fragment class as:

UtilityMethods.isConnected(activity)
Tradesfolk answered 25/5, 2018 at 5:33 Comment(2)
This doesn't work, just because a phone is connected to a network does not mean it is connected to the internet.Gefell
@Roymunson this is only a check whether the phone is connected to network or not. If it's connected in general it's consider as having network. You have to handle the timeout in code.Tradesfolk

© 2022 - 2024 — McMap. All rights reserved.