HttpURLConnection Message: Output stream not affected?
I am developing an Android app and have already figured out that different Android versions have different ways to manage Http urls (http://stackoverflow.com/q/9556316/151682).
I ran into the problem that Android 4 does a fine POST request over HTTPS adding Content-Type headers automatically when running the code below.
However, on Android 2.3.5 (device and emulator) any write to the output stream seems to be ignored - I debugged it with Charles's web proxy and when all headers are sent, the data written to the output stream is not sent ...
Does anyone know how to solve this?
Note. Since the API I'm developing against only has a self-signed certificate, I need to disable certificate validation for the time being.
TIA, Patrick
Update At the same time, I also tried to follow, to no avail:
- Call
close()
after callflush()
to BufferedOutputStream - Call on
close()
both OutputStream and BufferedOutputStream - Use OutputStreamWriter instead
-
Do not call
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(); }
}
source to share
Ah, I finally found it. Looking in the wrong place ... The problem was the headers:
My code above actually works fine - the reason is because I included the header which is Base64 encoded. On my Android 2.3.5, the ( Base64.DEFAULT
) option 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 have been changed to something like BASE64.NO_WRAP as described in the post below ...
This has already been answered here .
Thanks for your efforts.
source to share
It seems to me that the order in which you are calling DoSetOutput
etc. is causing the strange behavior ...
Some links / source with working code for HTTP POST on Android:
- HttpURLConnection doesn't work on Android (see class in question as link)
- HttpURLConnection (link including sample code)
- good sample including exception handling
- http://digitallibraryworld.com/?p=189
- How can I write to OutputStream using DefaultHttpClient?
- DefaultHttpClient GET and POST Java Android Commands (see the code in question)
source to share