如何在Android上检查互联网访问?InetAddress 永远不会超时 [英] How to check internet access on Android? InetAddress never times out

查看:20
本文介绍了如何在Android上检查互联网访问?InetAddress 永远不会超时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 AsyncTask 应该检查对主机名的网络访问.但是 doInBackground() 永远不会超时.有人知道吗?

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();
    }   
}

推荐答案

网络连接/互联网访问

  • isConnectedOrConnecting()(用于大多数答案)检查任何网络连接
  • 要了解这些网络中是否有任何一个可以互联网访问,请使用以下方法之一
  • 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
    • // 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;
      }
      

      + 可以在主线程上运行

      - 在某些旧设备(Galays S3 等)上不起作用,如果没有互联网可用,它会阻塞一段时间.

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

      // 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

      - 无法在 UI 线程上运行

      - can't run on the UI thread

      这在所有设备上都非常可靠,而且速度非常快.但它需要在单独的任务中运行(例如 ScheduledExecutorServiceAsyncTask).

      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).

      • 真的够快了吗?

      • Is it really fast enough?

      是的,非常快;-)

      除了在互联网上测试一些东西之外,还有没有其他可靠的方法可以检查互联网?

      Is there no reliable way to check internet, other than testing something on the internet?

      据我所知,但请告诉我,我会编辑我的答案.

      如果 DNS 出现故障怎么办?

      What if the DNS is down?

      Google DNS(例如 8.8.8.8)是世界上最大的公共 DNS.截至 2018 年,它每天处理超过一万亿次查询 [1].这么说吧,您的应用可能不会成为热门话题.

      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.

      需要哪些权限?

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

      只是互联网访问 - 惊喜^^(顺便说一句,你有没有想过,这里建议的一些方法如何甚至可以在没有此许可的情况下远程连接互联网访问?)

      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 */}
      

      额外:一次性RxJava/RxAndroid 示例(Java)

      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 {
      
              }
          });
      

      额外:一次性AsyncTask 示例

      注意: 这显示了如何执行请求的另一个示例.但是,由于 AsyncTask 已被弃用,它应该被您的应用程序的线程调度、Kotlin Coroutines、Rx、...

      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 */ });
      

      这篇关于如何在Android上检查互联网访问?InetAddress 永远不会超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆