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

当前回答

对我来说,在Activity类中检查连接状态并不是一个好的实践,因为

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

应该在那里调用,或者您需要下推您的活动实例(上下文)到连接处理程序类,以能够检查那里的连接状态 当没有可用的连接(wifi,网络)时,我捕捉到UnknownHostException异常:

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

通过这种方式,我可以处理这种情况连同其他情况在同一类(我的服务器总是响应回json字符串)

其他回答

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

从以下链接找到并修改(!):

在你的manifest文件中至少添加:

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

如果您正在访问它,您可能已经拥有INTERNET权限。那么一个允许测试连通性的布尔函数是:

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

我已经尝试了近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);
  }

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

这里是检查互联网连接的最佳方法。这个方法所做的是执行一系列检查“手机是否处于飞行模式,手机是否连接到网络,等等”。如果所有检查都返回true,该方法将从互联网下载一个文件,并查看内容是否与预期值匹配。

与其他通过ping服务器来检查互联网连接的方法相比,这种方法的好处是:

Android运行时在不同的手机上是不同的-所以你可能并不总是能够执行这些命令,如下所示:为什么ping在一些设备上工作,而不是其他设备? ping服务器并不总是有效,因为登录页面/重定向在wifi网络上,这可能会给人一种连接的错误印象。

这个答案是用Kotlin写的,并使用Fuel库从互联网上下载一个文件,使用methodfetchUrlAsString,但是任何库都可以被替换,只要你确保你的HTTP请求没有被缓存。可以将showConnectionWarning()和hideConnectionWarning()分别等价于互联网连接状态= false和互联网连接状态= true。

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

    }
}

您将需要以下权限:

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