2011-07-26 14 views
35

Łączę się z prostym kanałem RSS za pomocą HTTPUrlConnection. Działa idealnie. Chciałbym dodać czas oczekiwania na połączenie, ponieważ nie chcę, aby aplikacja zawieszała się w przypadku złego połączenia lub czegoś podobnego. Jest to kod, którego używam, a metoda setConnectTimeout nie ma żadnego efektu.HttpURLConnection setConnectTimeout() nie ma żadnego efektu

 HttpURLConnection http = (HttpURLConnection) mURL.openConnection(); 
     http.setConnectTimeout(15000); //timeout after 15 seconds 
... 

Jeśli to pomaga, rozwijam się na Androidzie.

+1

dwie rzeczy do rozważenia. Jeśli nie chcesz, aby aplikacja się zawiesiła, umieść metodę połączenia w osobnym wątku. Po drugie, powiedziałeś, że to "działa" idealnie, co robisz, aby symulować złe połączenie? – Otra

+0

@Otra Mam go w osobnym wątku za pomocą progressdialog. Zasadniczo dzieje się tak, że jeśli połączenie jest dobre, zadanie wykonuje swoje zadanie. Ale jeśli połączenie jest złe, progressdialog pozostaje na wieki. Aby zasymulować nieprawidłowe połączenie, ograniczam limit czasu. Zamiast dawać mu 15 sekund, 1 sekundę.Tylko do testowania. Czy to źle? –

+3

HttpURLConnection.setReadTimeout (mili sec); –

Odpowiedz

16

Prawdopodobnie obaj/obie:
1) Nie czytać niczego z związku
2) Nie złapać & obsłużyć wyjątek prawidłowo

Jak wspomniano here, wykorzystanie logiki podobny do to:

int TIMEOUT_VALUE = 1000; 
try { 
    URL testUrl = new URL("http://google.com"); 
    StringBuilder answer = new StringBuilder(100000); 

    long start = System.nanoTime(); 

    URLConnection testConnection = testUrl.openConnection(); 
    testConnection.setConnectTimeout(TIMEOUT_VALUE); 
    testConnection.setReadTimeout(TIMEOUT_VALUE); 
    BufferedReader in = new BufferedReader(new InputStreamReader(testConnection.getInputStream())); 
    String inputLine; 

    while ((inputLine = in.readLine()) != null) { 
     answer.append(inputLine); 
     answer.append("\n"); 
    } 
    in.close(); 

    long elapsed = System.nanoTime() - start; 
    System.out.println("Elapsed (ms): " + elapsed/1000000); 
    System.out.println("Answer:"); 
    System.out.println(answer); 
} catch (SocketTimeoutException e) { 
    System.out.println("More than " + TIMEOUT_VALUE + " elapsed."); 
} 
52

Powinieneś także spróbować ustawić czas oczekiwania na odczyt (http.setReadTimeout()). Często serwer WWW z przyjemnością akceptuje twoje połączenie, ale może reagować powoli na żądanie.

+0

To działało dla mnie. – stevehs17

+1

Nie działa dla mnie, jeśli jest podłączony do routera, ale połączenie internetowe jest wyłączone. –

-1

Spróbuj ustawić przed otwarciem połączenia.

+2

Jak - konstruktor jest metodą chronioną? – SK9

6

Miałem podobny problem - ponieważ do pobrania jest średnio HttpUrlConnection won't time out. Na przykład, jeśli wyłączysz Wi-Fi, gdy pobieranie się rozpocznie, moje nadal mówi, że pobiera, zablokowane w tym samym procencie.

Znalazłem rozwiązanie, używając TimerTask, podłączony do AsyncTask o nazwie DownloaderTask. Spróbuj:

class Timeout extends TimerTask { 
    private DownloaderTask _task; 

    public Timeout(DownloaderTask task) { 
     _task = task; 
    } 

    @Override 
    public void run() { 
     Log.w(TAG,"Timed out while downloading."); 
     _task.cancel(false); 
    } 
}; 

Następnie w pętli faktycznego pobierania ustawienie czasu Timeout-błędu:

    _outFile.createNewFile(); 
        FileOutputStream file = new FileOutputStream(_outFile); 
        out = new BufferedOutputStream(file); 
        byte[] data = new byte[1024]; 
        int count; 
        _timer = new Timer(); 
        // Read in chunks, much more efficient than byte by byte, lower cpu usage. 
        while((count = in.read(data, 0, 1024)) != -1 && !isCancelled()) { 
         out.write(data,0,count); 
         downloaded+=count; 
         publishProgress((int) ((downloaded/ (float)contentLength)*100)); 
         _timer.cancel(); 
         _timer = new Timer(); 
         _timer.schedule(new Timeout(this), 1000*20); 
        } 
        _timer.cancel(); 
        out.flush(); 

Jeśli to czasy, i nie będzie pobierał nawet 1K w 20 sekund, to anuluje zamiast wydaje się być na zawsze pobieranie.

+0

Dobry pomysł, aby zapobiec trwającemu połączeniu i pobieraniu :) –

2

Miałem do czynienia z tym samym problemem. Ustawienie connectionTimeout i readTimeout wydaje się nie zwracać wyjątku zgodnie z oczekiwaniami, ale naprawdę. Zajęło mi to chwilę, aby sprawdzić metodę URLConnection() i zrozumieć, co się dzieje. W dokumentacji dla setConnectTimeout pojawia się ostrzeżenie: "jeśli nazwa hosta jest rozpoznawana na wiele adresów IP, klient spróbuje wykonać każdą z nich. Jeśli połączenie z każdym z tych adresów zakończy się niepowodzeniem, upłynie wiele czasu oczekiwania, zanim próba połączenia zgłosi wyjątek. " Oznacza to, że jeśli masz 10 ips rozstrzygniętych przez twojego hosta, twój faktyczny limit czasu to "10 * readTimeoutSet".

można sprawdzić IP dla nazwy hosta here

1
http.setConnectTimeout(15000); 
http.setReadTimeout(15000); 
Powiązane problemy