2010-06-19 19 views
41

Piszę aplikację, która łączy się z serwisem internetowym i nie chcę, aby zbyt długo czekać, jeśli nie może uzyskać połączenia. Dlatego ustawiam connectionTimeout na httpparams. Ale wydaje się, że nie ma to żadnego wpływu.Limit czasu połączenia HTTP w systemie Android nie działa

Aby przetestować tymczasowo włączam swoją sieć WLAN. Aplikacja próbuje nawiązać połączenie przez dłuższy czas (czyli dłużej niż przez 3 sekundy), a następnie generuje wyjątek UnknownHostException.

Oto mój kod:

try{ 
    HttpClient httpclient = new DefaultHttpClient(); 
    HttpParams params = httpclient.getParams(); 
    HttpConnectionParams.setConnectionTimeout(params, 3000); 
    HttpConnectionParams.setSoTimeout(params, 3000); 

    httppost = new HttpPost(URL); 
    StringEntity se = new StringEntity(envelope,HTTP.UTF_8); 
    httppost.setEntity(se); 
    //Code stops here until UnknownHostException is thrown. 
    BasicHttpResponse httpResponse = (BasicHttpResponse) httpclient.execute(httppost); 

    HttpEntity entity = httpResponse.getEntity(); 
    return entity; 

}catch (Exception e){ 
    e.printStackTrace(); 
} 

Ktoś ma jakieś pomysły co brakowało mi?

Odpowiedz

74

Spróbuj zrobić to w ten sposób:

HttpPost httpPost = new HttpPost(url); 
StringEntity se = new StringEntity(envelope,HTTP.UTF_8); 
httpPost.setEntity(se); 

HttpParams httpParameters = new BasicHttpParams(); 
// Set the timeout in milliseconds until a connection is established. 
int timeoutConnection = 3000; 
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection); 
// Set the default socket timeout (SO_TIMEOUT) 
// in milliseconds which is the timeout for waiting for data. 
int timeoutSocket = 3000; 
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket); 

DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters); 
BasicHttpResponse httpResponse = (BasicHttpResponse) httpClient.execute(httpPost); 

HttpEntity entity = httpResponse.getEntity(); 
return entity; 

wtedy można złapać możliwie ConnectTimeoutException.

+3

W jaki sposób system jest powiadamiany o przekroczeniu limitu czasu i jaki wyjątek należy zastosować? – vokilam

+1

@VokilaM: Właśnie zredagowałem swoją odpowiedź. – Cristian

+3

Po ponad 30 sekundach nadal otrzymuję wyjątek UnknownHostException. W tym przypadku urządzenie jest podłączone do routera Wi-Fi, ale nie ma dostępu do Internetu. Jakąkolwiek wskazówkę, jak sprawić, aby to połączenie było zgodne z tym? W przeciwnym razie mógłbym wrócić do zewnętrznego timera ... :( – hooby3dfx

1

Ta metoda działa dla mnie:

AndroidHttpTransport androidHttpTransport = new AndroidHttpTransport(endpoint, 3000) ; 
0
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection); 
// Set the default socket timeout (SO_TIMEOUT) 
+0

To nie jest odpowiedź na pytanie, ponieważ ta metoda jest już częścią poniższego kodu; * kolejna wskazówka *: użyj formatowania kodu dla lepszej prezentacji ... – Trinimon

9

Z zaznaczonym rozwiązania nadal jestem coraz UnknownHostException po ponad 30 sekund. W tym przypadku urządzenie jest podłączone do routera Wi-Fi, ale nie ma dostępu do Internetu.

Podejście to polegało na uruchomieniu AsyncTask, który będzie próbował rozwiązać nazwę hosta. Wywołanie blokujące sprawdza co 250 ms, czy udało się, a po 4 sekundach anuluje zadanie i powróci.

To co zrobiłem go rozwiązać:

private boolean dnsOkay = false; 
private static final int DNS_SLEEP_WAIT = 250; 
private synchronized boolean resolveDns(){ 

    RemoteDnsCheck check = new RemoteDnsCheck(); 
    check.execute(); 
    try { 
     int timeSlept = 0; 
     while(!dnsOkay && timeSlept<4000){ 
      //Log.d("RemoteDnsCheck", "sleeping"); 
      Thread.sleep(DNS_SLEEP_WAIT); 
      timeSlept+=DNS_SLEEP_WAIT; 
      //Log.d("RemoteDnsCheck", "slept"); 
     } 
    } catch (InterruptedException e) { 

    } 

    if(!dnsOkay){ 
     Log.d("resolveDns", "cancelling"); 
     check.cancel(true); 
     Log.d("resolveDns", "cancelled"); 
    } 
    return dnsOkay; 
} 

private class RemoteDnsCheck extends AsyncTask<Void, Void, Void>{ 

    @Override 
    protected Void doInBackground(Void... params) { 
     try { 
      Log.d("RemoteDnsCheck", "starting"); 
      dnsOkay = false; 
      InetAddress addr = InetAddress.getByName(baseServiceURL); 
      if(addr!=null){ 
       Log.d("RemoteDnsCheck", "got addr"); 
       dnsOkay = true; 
      } 
     } catch (UnknownHostException e) { 
      Log.d("RemoteDnsCheck", "UnknownHostException"); 
     } 
     return null; 
    } 

} 

Następnie, za każdym razem chcę zrobić połączenia internetowego, nazywa się to na początku funkcji:

if(!resolveDns()){ 
     return null; 
    } 
+0

Tego właśnie szukałem. Dzięki stary! –

2

Apostolskiej : https://stackoverflow.com/a/20031077/2609238

Problem może dotyczyć klienta HTTP Apache. Zobacz HTTPCLIENT-1098. Naprawiono w 4.1.2.

Wyjątek timeout próbuje odwrócić DNS IP w celu rejestrowania. Zajmuje to dodatkowy czas, dopóki wyjątek nie zostanie faktycznie uruchomiony.

Powiązane problemy