我得到了一个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();
    }   
}

当前回答

最简单的解决办法是

在大多数情况下,如果他/她想连接到远程服务器,只会检查互联网连接,所以简单和最好的解决方案是ping你的服务器,如下所示。

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

其他回答

看一下ConnectivityManager类。您可以使用这个类来获取主机上活动连接的信息。http://developer.android.com/reference/android/net/ConnectivityManager.html

编辑:你可以使用

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

or

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

并解析返回NetworkInfo对象的DetailedState枚举

EDIT EDIT:查看是否可以访问主机

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

显然,我使用Context.getSystemService(Context.CONNECTIVITY_SERVICE)作为代理来表示

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

这个线程中的大多数答案只检查是否有可用的连接,但不检查该连接是否工作,其他答案不是设备范围,我的解决方案应该在每个设备上工作。

你可以在启动应用程序之前在你的主要活动中删除我的代码,它会快速确定是否有实际的互联网连接,如果有对话框将立即删除,应用程序将被启动,如果没有警报会弹出说应用程序需要互联网连接才能工作。

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

我已经尝试了近5+不同的android方法,发现这是谷歌提供的最佳解决方案,特别是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);
  }

它比任何其他可用的解决方案都更快、高效和准确。

这段代码将帮助您找到互联网是否打开。

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

此外,您应该提供以下权限

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

使用这个Kotlin扩展:

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