如何在Android上检查互联网接入?inetaddress从不超时

时间 2009-10-13
阅读 424048
点赞 593
收藏 359
连接vidar-vestnes

我得到了一个AsyncTask它应该检查对主机名的网络访问。但是doInBackground()永远不会超时。有人有线索吗?

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()(大多数答案中使用)检查网络连接
  • 要知道这些网络中是否有互联网访问,使用以下选项之一

a)ping服务器(简单)

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

+可以在主线程上运行

-不适用于某些旧设备(GalaysS3等),如果没有可用的互联网,它会阻塞一段时间。

b)连接到互联网上的插座(高级)

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

+非常快(无论哪种方式),适用于所有设备,非常可靠的

-无法在UI线程上运行

这在每个设备上都非常可靠,而且速度非常快。它需要在单独的任务中运行(例如ScheduledExecutorServiceAsyncTask

可能的问题

  • 它真的够快吗?

    是的,非常快;-)

  • 除了在互联网上测试一些东西之外,是否没有可靠的方法来检查互联网?

    据我所知,但让我知道,我会编辑我的答案。

  • 如果DNS关闭怎么办?

    Google DNS(例如8.8.8.8)是世界上最大的公共DNS。截至2013年,它每天处理1300亿个请求。让我们假设一下,你的应用程序可能不会成为一天的话题。

  • 需要哪些权限?

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

    仅仅是互联网接入-惊喜^(顺便问一下,你有没有想过,如果没有这个许可,这里建议的一些方法甚至可以有一个关于互联网接入的远程胶水?)

nbsp;

额外:一击AsyncTask例子

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

额外:一击RxJava/RxAndroid示例(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 */}
👍 416