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

后端 未结 30 3342
猫巷女王i
猫巷女王i 2020-11-21 04:45

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?

30条回答
  •  鱼传尺愫
    2020-11-21 04:53

    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 2013 it served 130 billion requests a day. Let 's just say, your app would probably not be the talk of the day.

    • Which permissions are required?

      
      

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

     

    Extra: One-shot AsyncTask Example

    class InternetCheck extends AsyncTask {
    
        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 */ });
    

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

    fun hasInternetConnection(): Single {
      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 */}
    

提交回复
热议问题