2012-07-25 7 views
7

W mojej aplikacji na Androida próbuję pobrać dane z serwera, wykonując żądanie POST.getHttpResponseCode() zwraca -1 w systemie Android 2.2

Używam klasy HttpURLConnection do wysyłania żądań jako serwer Apache HttpClient, który nie jest już obsługiwany przez Androida.

Oto, co robię.

private boolean callWS() { 
    try { 

     // To avoid the bug in httpurlconnection prior froyo which 
     // causes the getInputStream to return headers along with response 
     if (Build.VERSION.SDK_INT < 8) 
      System.setProperty("http.keepAlive", "false"); 

     mHttpResponseCode = 0; 
     mErrorMessage = ""; 

     // Initialize connection 
     URL connectURL = new URL(mServerUrl); 

     HttpURLConnection conn = (HttpURLConnection) connectURL.openConnection(); 
     conn.setDoInput(true); 
     conn.setDoOutput(true); 
     conn.setUseCaches(false); 
     conn.setInstanceFollowRedirects(true); 
     conn.setReadTimeout(30000); 
     conn.setConnectTimeout(15000); 
     conn.setRequestMethod("POST"); 

     // Set some headers 
     connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 
     connection.setRequestProperty("Accept-Encoding", "deflate, gzip"); 
     connection.setRequestProperty("Content-Length", mParameters.length() + ""); 

     // Connect to host 
     conn.connect(); 

     // Write parameters to connection 
     OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream()); 
     writer.write(mParameters); 
     writer.flush(); 
     writer.close(); 

     // Wait for http response code 
     mHttpResponseCode = conn.getResponseCode(); 

     // Read response from connection 
     BufferedInputStream bis = new BufferedInputStream(conn.getInputStream()); 
     ByteArrayBuffer baf = new ByteArrayBuffer(50); 
     int read = 0; 
     int bufSize = 1024; 
     byte[] buffer = new byte[bufSize]; 

     while (true) { 
      read = bis.read(buffer); 
      if (read == -1) 
       break; 
      baf.append(buffer, 0, read); 
     } 

     // Decompress gzipped response 
     if (conn.getHeaderField("Content-Encoding") != null && conn.getHeaderField("Content-Encoding").contains("gzip")) 
      mResponseString = decompress(baf.toByteArray()); 
     else 
      mResponseString = new String(baf.toByteArray()); 

     mResponse.setResponse(mResponseString);   
     isWSCallSuccessfull = true; 
    } catch(UnknownHostException unknownHostException) { 
     isWSCallSuccessfull = false; 
     mErrorMessage = "Unknown host exception"; 
     unknownHostException.printStackTrace(); 
     mLogger.putStacktrace(unknownHostException); 
    } catch(SocketException socketException) { 
     isWSCallSuccessfull = false; 
     mErrorMessage = "Socket Exception"; 
     socketException.printStackTrace(); 
     mLogger.putStacktrace(socketException); 
    } catch(SocketTimeoutException socketTimeOutException) { 
     isWSCallSuccessfull = false; 
     mErrorMessage = "Socket Timeout Exception"; 
     socketTimeOutException.printStackTrace(); 
     mLogger.putStacktrace(socketTimeOutException); 
    } catch(SSLException sslException) { 
     isWSCallSuccessfull = false; 
     mErrorMessage = "SSL Exception"; 
     sslException.printStackTrace(); 
     mLogger.putStacktrace(sslException); 
    } catch(IOException ioException) { 
     isWSCallSuccessfull = false; 
     mErrorMessage = "IO Exception " + ioException.getMessage(); 
     ioException.printStackTrace(); 
     mLogger.putStacktrace(ioException); 
    } 

    mResponse.setHttpResponseCode(mHttpResponseCode); 
    mResponse.setErrorMessage(mErrorMessage); 
    mResponse.isWSCallSuccessful(isWSCallSuccessfull); 

    return isWSCallSuccessfull; 
} 

Działa to dobrze na każdym urządzeniu, z wyjątkiem urządzeń z systemem 2.2 (nie spróbować go na 2,1).

W wersji 2.2 działa poprawnie. Ale jeśli zostawiam tę część kodu bezczynnego przez ponad 30 sekund, zwraca ona ponownie -1 jako kod odpowiedzi http zaraz po następnym.

Inną rzeczą, na którą należy zwrócić uwagę, jest to, że dzieje się tak tylko z adresami URL HTTPS, a nie z adresami URL HTTP. Nie chcę używać klasy HttpsURLConnection, ponieważ czasami mogę chcieć również użyć http.

Nie zamykam połączenia tylko po to, aby utrzymać połączenie przy życiu. Co ja robię źle?

+0

czy połączenia Https automatycznie się zamykają po pewnym czasie (jeśli nic nie jest przenoszone, mam na myśli)? Nie wiem zbyt wiele o połączeniach https, więc może to być całkowicie błędne. (Odczytywanie go z powrotem Nie jestem nawet pewien, co powiedziałem ma sens LOL) –

+0

-1 jest zwykle, gdy połączenie nie powiodło się z powodu, który nie jest określony przez kod HTTP - w twoim przypadku brzmi to jak timeout, ale może również być nieudolnym rozpoznawaniem DNS, itd ... Teraz, kiedy _ konkretna wersja Androida kończy się, nie wiem ... – Basic

+0

Cóż, mój pomysł polega na tym, że jeśli nie robię niczego złego, to jest tylko ten problem ze mną? Ponieważ przeszukując w sieci, nie znalazłem nikogo, kto miałby ten problem. – Enigma

Odpowiedz

0

Jeśli chcesz użyć HTTPS i HTTP w tym samym czasie i nie chce, aby utworzyć połączenie oddzielna -i jeśli HttpsUrlConnection rozwiązuje problem „-1” można użyć następujące podejście:

URLConnection conn = new URL(url).openConnection(); 
if (conn instanceof HttpsURLConnection) { 
    // do stuff with cast to HttpsUrlConection 
} 
else { 
    // do stuff with cast to HttpUrlConnection 
} 

Otrzymałem this odpowiedź jako odniesienie