2010-05-10 16 views
91

Quiero devolver el valor falso si la URL tarda más de 5 segundos en conectarse. ¿Cómo es posible usar Java? Aquí está el código que estoy utilizando para comprobar si la URL es válidaHttpURLConnection configuración de tiempo de espera

HttpURLConnection.setFollowRedirects(false); 
HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(); 
con.setRequestMethod("HEAD"); 
return (con.getResponseCode() == HttpURLConnection.HTTP_OK); 

Respuesta

153

HttpURLConnection tiene un método setConnectTimeout.

Sólo hay que establecer el tiempo de espera a 5000 milisegundos, y luego coger java.net.SocketTimeoutException

El código debería ser algo como esto:

 

try { 
    HttpURLConnection.setFollowRedirects(false); 
    HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(); 
    con.setRequestMethod("HEAD"); 

    con.setConnectTimeout(5000); //set timeout to 5 seconds 

    return (con.getResponseCode() == HttpURLConnection.HTTP_OK); 
} catch (java.net.SocketTimeoutException e) { 
    return false; 
} catch (java.io.IOException e) { 
    return false; 
} 

 
+1

Configuré el valor en 10 minutos. Sin embargo, me arroja una 'java.net.ConnectException: La conexión ha expirado: conecte' antes incluso de que hayan transcurrido 2 minutos. ¿Sabes lo que está causando el problema? – Pacerier

+0

@dbyrne esto me parece un poco confuso, ya que establecemos el tiempo de espera después de que se crea el objeto 'HttpURLConnection', me pregunto cuál es el lugar exacto en el código que levantará' SocketTimeoutException'? – Less

+3

SocketTimeoutException es una subclase de IOException. Si ambos bloques de capturas hacen lo mismo, podrías atrapar IOException. – spaaarky21

85

Puede establecer el tiempo de espera de este tipo,

con.setConnectTimeout(connectTimeout); 
con.setReadTimeout(socketTimeout); 
+1

¿Cuál es el valor máximo del tiempo de espera que podemos especificar? – Pacerier

+5

@Pacerier Los documentos no indican esto explícitamente. Lanza una IllegalArgumentException si el valor es negativo (un valor de 0 significa esperar indefinidamente). Como el tiempo de espera es un int sin firmar de 32 bits, supongo que el tiempo de espera máximo sería de aproximadamente 49 días (aunque tengo serias dudas de que dicho valor sea útil para cualquiera). –

+1

+1 para los múltiples tipos de tiempo de espera ... – jsh

1

Si la conexión HTTP no agota el tiempo de espera, puede implementar el verificador de tiempo de espera en el hilo de fondo (AsyncTask, Service, etc.), la siguiente clase es un examen PLE para Personalizar AsyncTask que el tiempo de espera después de cierto período

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 este

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

Es absolutamente innecesario crear un nuevo hilo de looper solo para programar una llamada a cancelar(). Puede hacerlo desde el hilo principal en 'onPreExecute()'.Además, si cancela la tarea manualmente, también debe cancelar la llamada programada para evitar fugas. – BladeCoder

+0

El punto aquí es cancelar AsyncTask en el medio de doInBackground() cuando toma mucho tiempo en la ejecución no en onPreExecute(), también quiero cancelar solo esta instancia de AsyncTask que toma demasiado tiempo y mantiene a los demás, mucho Agradecemos sus comentarios. –

+1

Creo que mi mensaje no fue lo suficientemente claro. No dije que debías cancelar en onPreExecute(), dije que deberías crear el controlador en onPreExecute() y publicar la cancelación diferida del hilo principal. De esta forma, usarás el hilo principal como hilo de looper y, por supuesto, puedes cancelar AsyncTask más tarde mientras doInBackground() se está ejecutando porque el hilo principal también se ejecuta simultáneamente con el hilo de fondo. – BladeCoder

0

que podría conseguir solución para tal problema similar con la adición de una simple línea

HttpURLConnection hConn = (HttpURLConnection) url.openConnection(); 
hConn.setRequestMethod("HEAD"); 

Mi el requisito era conocer el código de respuesta y para eso solo bastaba con obtener la metainformación, en lugar de obtener el cuerpo completo de la respuesta.

El método de solicitud predeterminado es GET y tardaba mucho tiempo en regresar, finalmente arrojándome SocketTimeoutException. La respuesta fue bastante rápida cuando establecí el método de solicitud en HEAD.

Cuestiones relacionadas