2012-07-04 10 views
14

Mam następujący blok kodu:Dlaczego wartość timeout nie jest przestrzegana przez android HttpURLConnection?

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

Kiedy domena site-to-test nie jest osiągalny za pośrednictwem istniejącej sieci, kod ten blokuje przez około 30-40 sekund zanim otrzymaniu IOException. I specjalnie ustawiłem wartość limitu czasu na 500ms. Czego tu mi brakuje? Czy powyższy blok nie powinien kończyć się w pół sekundy, niezależnie od stanu sieci i dostępności strony?

+1

można użyć TimerTask i Timer razem, aby ustawić limit .... –

+0

BTW, robisz to na oddzielnym "Thread" (lub 'AsyncTask'), prawda? –

+0

Tak, Alex, nie marzyłbym o zablokowaniu wątku interfejsu użytkownika. –

Odpowiedz

13

Wydaje się, że Java URLConnection provides no fail-safe timeout on reads

Rozwiązanie to, tak jak w artykule, stosowanie oddzielnego wątku dla czasu i odłączyć HttpURLConnection ręcznie raz gwint czasowy jest wykonywana.

+0

Czy to obejście jest możliwe, jeśli używam AsyncTask zamiast wątku? – NoBugs

+0

Myślę, że znalazłem dobre rozwiązanie dla mojego problemu AsyncTask w systemie Android. Ustawiam programator, aby zatrzymał go po pewnym opóźnieniu i zresetował licznik czasu, gdy pobierze kolejny element. W ten sposób nie traci czasu na wolne połączenie, ale przekracza limit czasu, gdy sieć jest odłączona: http://stackoverflow.com/questions/6829801/httpurlconnection-setconnecttimeout-has-no-effect/11790633#11790633 – NoBugs

+0

Mam ' Obiekt HttpURLConnection' pobiera dane i próbuje je zapisać do pliku przy użyciu obiektu 'OutputStream'. 'output = connection.getOutputStream();'. Po wyłączeniu Wi-Fi wyrzucono "ConnectException". Czy to oznacza, że ​​mogę słuchać mojego połączenia sieciowego? –

1

Po przeprowadzeniu dokładnych badań i wielu szlaków, stwierdziłem, że najlepszym sposobem na wdrożenie licznika czasu dla AsyncTask (lub usługi, obiekt używany do wykonywania pracy w tle) z dala od klasy połączenia HTTP, jak czasami po odłączeniu połączenie HTTP, to nie przerywa połączenia internetowego, i wdrożone tej klasy należy stosować, gdy trzeba limitu czasu czek na połączenia 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); 
} 

próbkę tego

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

Działa świetnie. Dzięki. Nie mógłbym dla mojego życia uzyskać HttpURLConnection na cześć metod setXXXTimeout. –

Powiązane problemy