2012-07-04 13 views
14

Ich habe folgenden Codeblock:Warum Timeout-Wert von Android HttpURLConnection nicht eingehalten wird?

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

Wenn die site-to-test Domäne nicht erreichbar durch das aktuelle Netzwerk ist diese Code-Blöcke für etwa 30-40 Sekunden, bevor die IOException empfängt. Und ich habe den Timeout-Wert speziell auf 500ms eingestellt. Was fehlt mir hier? Sollte die oben genannte Blockierung nicht innerhalb von einer halben Sekunde enden, unabhängig vom Netzwerkstatus und der Verfügbarkeit der Site?

+1

benötigen, können Sie verwenden, und Timertask Timer zusammen um Limit zu setzen .... –

+0

BTW, du machst das auf einem separaten 'Thread' (oder' AsyncTask'), oder? –

+0

Ja, Alex, ich würde nicht davon träumen, den UI-Thread zu blockieren. –

Antwort

13

Es scheint, dass Java URLConnection provides no fail-safe timeout on reads

Die Lösung ist, wie der Artikel erklärt, einen separaten Thread für den Zeitablauf zu verwenden, und trennt das HttpURLConnection manuell, sobald der Timer-Thread ausgeführt wird.

+0

Ist diese Problemumgehung möglich, wenn ich eine AsyncTask anstelle eines Threads verwende? – NoBugs

+0

Ich glaube, ich habe eine gute Lösung für mein AsyncTask-Problem in Android gefunden. Ich stelle einen Timer ein, um ihn nach einer bestimmten Verzögerung zu stoppen, und setze den Timer zurück, wenn er ein anderes Stück herunterlädt. Auf diese Weise Timeout nicht bei langsamer Verbindung, aber Timeout, wenn Netzwerk getrennt ist: http://StackOverflow.com/Questions/6829801/httpurlconnection-setconnecttimeout-has-No-Effect/11790633#11790633 – NoBugs

+0

Ich habe eine ' HttpURLConnection '-Objekt, Daten abrufen und versuchen, es in eine Datei mit einem' OutputStream'-Objekt zu schreiben. 'output = connection.getOutputStream();'. Nachdem ich Wi-Fi ausgeschaltet hatte, wurde "ConnectException" ausgelöst. Bedeutet das, dass ich meine Netzwerkverbindung hören kann? –

1

Nach gründlichen Untersuchungen und vielen Trails, fand ich, dass der beste Weg, um einen Timer für AsyncTask (oder Service, das Objekt, das Sie im Hintergrund arbeiten) außerhalb der HTTP-Verbindungsklasse zu implementieren, wie manchmal wenn Sie die Verbindung trennen HTTP-Verbindung, wird dies den Web-Anruf nicht unterbrechen, implementiert ich diese Klasse verwendet werden, wenn Sie Timeout-Check für Ihre HTTP-Verbindung

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

Ein Beispiel für diesen

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

Funktioniert gut. Vielen Dank. Konnte nicht für das Leben von mir bekommen HttpURLConnection die setXXXTimeout Methoden zu beachten. –

Verwandte Themen