问题
I am developing an Android app and have already found out that different Android versions have a different ways on how they handle Http(s)URLConnections (http://stackoverflow.com/q/9556316/151682).
I ran into the issue that Android 4 performs a POST request over HTTPS nicely, adding headers like Content-Type automatically when running the code below.
However, on Android 2.3.5 (device & emulator), any write to the output stream seems to be ignored - I debugged it with the web proxy Charles and while all headers are sent, the data written to the output stream is not sent along...
Anyone knows how to solve this?
Note: As the API I am developing against has only a self-signed certificate, I need to disable certification validation at this time.
TIA, Patrick
Update In the meantime, I also have tried to following, to no avail:
- Calling
close()
after theflush()
call on the BufferedOutputStream - Calling
close()
on both the OutputStream and the BufferedOutputStream - Using a OutputStreamWriter instead
Not calling
close()
before callinggetInputStream()
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setConnectTimeout(CONNECT_TIMEOUT); connection.setDoOutput(true); // Triggers POST. connection.setRequestMethod("POST"); int contentLength = 0; if(body != null) { contentLength = body.getBytes().length; } // Workarounds for older Android versions who do not do that automatically (2.3.5 for example) connection.setRequestProperty(HTTP.TARGET_HOST, url.getHost()); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); // Set SSL Context -- Development only if(context != null && connection instanceof HttpsURLConnection){ HttpsURLConnection conn = (HttpsURLConnection)connection; conn.setSSLSocketFactory(context.getSocketFactory()); conn.setHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }); } try{ // Add headers if(headers != null){ for (NameValuePair nvp : headers) { if(nvp != null){ connection.setRequestProperty(nvp.getName(), nvp.getValue()); } } } connection.setFixedLengthStreamingMode(contentLength); OutputStream outputStream = null; try { if(body != null){ outputStream = connection.getOutputStream(); BufferedOutputStream stream = new BufferedOutputStream(outputStream); stream.write(body.getBytes()); // <<<< No effect ?! stream.flush(); } } finally { if (outputStream != null) try { outputStream.close(); } catch (IOException logOrIgnore) { // ... } } InputStream inputStream = connection.getInputStream(); // .... Normal case .... } catch(IOException e){ // ... Exception! Check Error stream and the response code ... } finally{ connection.disconnect(); }
}
回答1:
To me it seems that the order in which you call DoSetOutput
etc. is the reason for the strange behaviour...
Some links/source with working code for HTTP POST on Android:
- HttpURLConnection fail on Android (see class in the question as reference)
- HttpURLConnection (reference including sample code)
- nice sample including exception handling
- http://digitallibraryworld.com/?p=189
- How do I write to an OutputStream using DefaultHttpClient?
- DefaultHttpClient GET and POST commands Java Android (see code in question)
回答2:
Ah, I finally found it. Looking in the wrong place... The problem was the headers:
My code above actually works fine - the cause is that I included a header which is Base64 encoded. On my Android 2.3.5 the specified option (Base64.DEFAULT
) seems to insert an extra newline at the end which ends the request prematurely, giving me no time to send the actual body.
On Android 4, the Default seems to be changed to something like BASE64.NO_WRAP as explained in the post linked below...
This was actually already answered here.
Thanks for your efforts.
来源:https://stackoverflow.com/questions/10058516/httpurlconnection-post-output-stream-has-no-effect