¿Por qué el valor de tiempo de espera no es respetado por HttpURLConnection de Android?

Tengo el siguiente bloque de código:

try { URL url = new URL("http://site-to-test.com/nonexistingpage.html"); HttpURLConnection urlc = (HttpURLConnection) url.openConnection(); urlc.setRequestProperty("User-Agent", CoreProtocolPNames.USER_AGENT); urlc.setRequestProperty("Connection", "close"); urlc.setConnectTimeout(500); // timeout is in milliseconds urlc.connect(); if (urlc.getResponseCode() == 404) { // Server was reachable Log.i(TAG, "Server is reachable"); } } catch (MalformedURLException mue) { Log.e(TAG, "MalformedURLException: " + mue.getMessage()); } catch (IOException e) { Log.e(TAG, "IOException: " + e.getMessage()); } 

Cuando el dominio site-to-test no es accesible a través de la red actual, este código se bloquea durante aproximadamente 30-40 segundos antes de recibir la IOException . Y establecí específicamente el valor del tiempo de espera a 500ms. ¿Que me estoy perdiendo aqui? ¿No debería terminar el bloque anterior en medio segundo, sin importar el estado de la red y la disponibilidad del sitio?

Parece que Java URLConnection no proporciona ningún tiempo de espera a prueba de fallos en lecturas

Como se explica en el artículo, la solución es utilizar un hilo independiente para la temporización y desconectar la HttpURLConnection manualmente una vez que se realiza el hilo del temporizador.

Después de profundas investigaciones y un montón de pistas, encontré que la mejor manera de implementar un temporizador para AsyncTask (o Service, el objeto que utilizó para realizar trabajos de fondo) lejos de la clase de conexión HTTP, como a veces cuando desconecta la conexión HTTP, esto No interrumpe la llamada de la tela, implementé esta clase para ser utilizado cuando usted necesita la comprobación del tiempo de espera para su conexión del HTTP

 public abstract class AsyncTaskWithTimer<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> { private static final int HTTP_REQUEST_TIMEOUT = 30000; @Override protected Result doInBackground(Params... params) { createTimeoutListener(); return doInBackgroundImpl(params); } private void createTimeoutListener() { Thread timeout = new Thread() { public void run() { Looper.prepare(); final Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { if (AsyncTaskWithTimer.this != null && AsyncTaskWithTimer.this.getStatus() != Status.FINISHED) AsyncTaskWithTimer.this.cancel(true); handler.removeCallbacks(this); Looper.myLooper().quit(); } }, HTTP_REQUEST_TIMEOUT); Looper.loop(); } }; timeout.start(); } abstract protected Result doInBackgroundImpl(Params... params); } 

Una muestra para esto

 public class AsyncTaskWithTimerSample extends AsyncTaskWithTimer<Void, Void, Void> { @Override protected void onCancelled(Void void) { Log.d(TAG, "Async Task onCancelled With Result"); super.onCancelled(result); } @Override protected void onCancelled() { Log.d(TAG, "Async Task onCancelled"); super.onCancelled(); } @Override protected Void doInBackgroundImpl(Void... params) { // Do background work return null; }; } 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.