ANDROID HttpURLConnection always uses GET - android

I am developing an app in android studio and for web service calls I use HttpURLConnection. Although the class always uses GET when I call it, even tough I set it to POST. I have even double sat it to POST to make sure that's the method it will use.
URL url = new URL(Activity.this.getString(R.string.ws));
urlConn = (HttpURLConnection) url.openConnection();
urlConn.setRequestMethod("POST");
urlConn.setDoOutput(true);
urlConn.addRequestProperty("Content-Type", "application/json");
urlConn.addRequestProperty("Cache-Control", "no-cache");
urlConn.addRequestProperty("Accept", "application/json");
urlConn.addRequestProperty("Authorization", "Bearer " + fileHelper.getPropertyFromSharedPreferences(getString(R.string.key_token)));
urlConn.connect();
Anyone else has had this problem before? And how to fix it?
PS. I have also tried OKHTTP, but still the same problem
EDIT:
I have found out the reason that the method will always be GET, is because when I call setDoOutput it doesn't change the value, not even if I do
urlConn.setDoOutput(!urlConn.getDoOutput);

Do not use urlConn.connect();. Use urlConn.getOutputStream() instead.

Related

How setConnectTimeout can work?

I read many posts about setConnectTimeout but I really wonder how this method could work because we cannot initialize it before openConnection() exists.
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setConnectTimeout(5000);
urlConnection.setReadTimeout(2000);
...
So what is the purpose of setConnectTimeout()?
You're just opening / initializing the connection. You haven't actually called urlConnection.connect() yet. You're only initializing things like the URL, headers, setting your request method, etc.
It'll come into effect once you actually run the connection.

setRequestProperty throwing java.lang.IllegalStateException: Cannot set request property after connection is made

I am getting java.lang.IllegalStateException:
java.lang.IllegalStateException: Cannot set request property after connection is made error when setRequestProperty method is called after
url.openConnection();
Here is what i am trying:
URL url = new URL("https://49.205.102.182:7070/obsplatform/api/v1/mediadevices/545b801ce37e69cc");
urlConnection = (HttpsURLConnection) url
.openConnection();
urlConnection.setRequestProperty("Content-Type","application/json");
any suggestions please? Thanks in advance.
This usually happens if you have in the debug watchers calls, such as conn.getResponseCode() or anything that queries the request result before the request was actually issued or completed.
This causes, that during debug, a request is performed by the watcher, before having properly set you request, and then it becomes invalid.
I only have this issue while in debugging mode,
Run without debugging (You can print logs) everything should work fine
The obvious thing is to think that you need to add properties before calling open on the URL. this however is not the case. i have seen many samples of settings being set AFTER url has been open (as counter intuitive as that is).
the problem in my case is that i had conn.getResponseCode() added in my watch list. removed that and all good.
... tricky.
please check below code
HttpURLConnection httpcon = (HttpURLConnection) ((new URL("a url").openConnection()));
httpcon.setDoOutput(true);
httpcon.setRequestProperty("Content-Type", "application/json");
httpcon.setRequestProperty("Accept", "application/json");
httpcon.setRequestMethod("POST");
httpcon.connect();
I was getting the same exception on setRequestProperty("Range","byte=" + downloadedSize + "-") .
After adding connection.setChunkedStreamingMode(0); the issue disappeared
I'm having the same issue.
I was observing this issue on Nexus 5. Code of my app constantly fails with the same exception (or its twin brother "cannot set request method ..")
What I've observed that it happens if i leave phone for a while. One it starts failing it fails all the time - but if i restart phone/emulator it's ok once again).
My suspicion is its either some bug in connection pooling on framework side, or somewhere in code resources are leaked.
i found the problem it's about ordering the code, if you are trying to add header and post parameters both, it's important to be careful about this
HttpURLConnection connection = (HttpURLConnection) urlConnection;
//// Add Request Headers
for (NameValuePair nvp :
request[0].getHeaderParams()) {
connection.setRequestProperty(nvp.getName(),nvp.getValue());
}
// done
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestMethod("POST");
//// Add Post Parameters
OutputStream outputStream = urlConnection.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
List<NameValuePair> params = new ArrayList<>(request[0].getPostParams());
bufferedWriter.write(getQuery(params));
// done
connection.setConnectTimeout(3000);
connection.setReadTimeout(3000);
bufferedWriter.flush();
bufferedWriter.close();
outputStream.flush();
outputStream.close();
connection.connect();
in here, i have added header parameters then set setDoInput and setDoOutput then setRequestMethod and finally you can add POST parameters.
i don't know what is wrong with setRequestMethod but i think its preparing the connection by opening it or something and that's why it throws exception
not invoke setRequestProperty after write byte to OutputStream.
OutputStream os = connection.getOutputStream();
os.write("k=v".getBytes());
os.close();
you should invoke setRequestProperty above the code
To avoid the error:
java.lang.IllegalStateException: Cannot set request property after connection is made
We have to check the connection response before access the request header fields :
URL url = new URL("https://49.205.102.182:7070/obsplatform/api/v1/mediadevices/545b801ce37e69cc");
urlConnection = (HttpsURLConnection) url
.openConnection();
//Check connection
if(urlConnection.getResponseCode() == 200/*Successful*/) {
urlConnection.setRequestProperty("Content-Type","application/json");
...
...
}

Android HTTP PUT request returns 411 error only on Android 2.1

I have an app here that sends out an HTTP PUT to a webserver. The code looks like this:
URL url = new URL(urlStr + "?" + encodedParameters);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("PUT");
connection.setRequestProperty("Content-Length", "0");
When I try this on Android 2.1, I end up getting back a 411 error ("Length Required").
On Android 2.3.3 and up I was getting this same 411 error back until I added that last "Content-Length" property. But it's still happening on Android 2.1.
Anyone have an idea what might be going on here?
Not sure if this will work, but it may be worth trying to set "Content-Length" like below:
connection.setRequestProperty("Content-Length", Integer.toString(encodedParameters.getBytes().length));

Android HttpURLConnection with HTTP Basic Authorization on RAILS Web Service

I'm trying around with the HttpURLConnection for quite some time now and I tried several solution posted here and on other places, but nothing seems to work.
I have the following architecture:
A Ruby on Rails Web Service (Rest interface with JSON)
An iPhone Client with RestKit
An Android Client with HttpURLConnection
The iPhone Client works like a charm. It connects to the web service with RestKit.
Now the Android Client is a completely different story. I always get a 401 Unauthorized message from the server (which results in a local FileNotFoundException).
The strange thing is, that the iPhone Client gets the same error, but RestKit somehow manages the handle it by sending the same request again. I tried that of course, but I just get the same error twice.
On the Rails Log Output it looks like this:
Started POST "/api/v1/login" for 127.0.0.1 at 2012-05-03 12:44:56 +0200
Processing by Api::V1::ApiController#session_login as JSON
Parameters: {"device"=>{"model"=>"Simulator", "system"=>"Android", "version"=>"Hugo", "name"=>"Android Simulator"}, "email"=>"florian.letz#simpliflow.com", "api"=>{"device"=>{"model"=>"Simulator", "system"=>"Android", "version"=>"Hugo", "name"=>"Android Simulator"}, "email"=>"florian.letz#simpliflow.com", "action"=>"session_login", "controller"=>"api/v1/api"}}
Filter chain halted as :require_login_from_http_basic rendered or redirected
Completed 401 Unauthorized in 0ms (ActiveRecord: 0.0ms)
The exact same message occurs when the iPhone Client connect's but then suddenly a magical second request occurs and it goes through.
On the Android Client I do the following:
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod(HTTP_POST);
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Accept-Encoding", "gzip, deflate");
String userpassword = email + ":" + password;
con.setRequestProperty("Authorization", "Basic " + new String(Base64.encodeBase64(userpassword.getBytes())));
String body = jsonLogin.toString();
byte[] body_bytes = body.getBytes();
con.setRequestProperty("Content-Length", "" + Integer.toString(body_bytes.length));
con.setRequestProperty("Content-Language", "en-US");
con.setInstanceFollowRedirects(false);
con.setUseCaches (false);
con.setDoInput(true);
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream (con.getOutputStream ());
wr.write(body_bytes);
wr.flush ();
wr.close ();
InputStream is = con.getInputStream();
And on the last line the exception occurs.
I've read some things about redirects, but there is no redirect implemented at the server and I do not receive one on the client. I just get the 401 Unauthorized. The code in the web service and the iphone client indicate a quite simple workflow. Just send the data and receive the answer. I don't know where the SECOND login call comes from when the iPhone connects.
Does anyone here have any idea what the problem could be?
Thanks a lot!
EDIT #1:
I have identified the "magical" second request. The RestKit Log shows the following:
Asked if canAuthenticateAgainstProtectionSpace: with authenticationMethod = NSURLAuthenticationMethodDefault
This then results in the second request with quite a buch of headers I cannot make any sense of.
So do you know a way to implement this in Android?

FileNotFoundException for HttpURLConnection in Ice Cream Sandwich

I have an Android app that works fine with Android 2.x and 3.x, but it fails when run on Android 4.x.
The problem is in this section of code:
URL url = new URL("http://blahblah.blah/somedata.xml");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
When the application is running on Android 4.x, the getInputStream() call results in a FileNotFoundException. When the same binary is running on earlier versions of Android, it succeeds. The URLs also work fine in web browsers and with curl.
Apparently something about HttpURLConnection has changed in ICS. Does anybody have any idea what has changed, and/or what the fix might be?
Try removing the setDoOutput call. Taken from this blog:
a blog
Edit: This is needed when using a POST call.
A FileNotFoundException may also been thrown if the server returns a bad error code (e.g., 400 or 401). You can handle this as follows:
int responseCode = con.getResponseCode(); //can call this instead of con.connect()
if (responseCode >= 400 && responseCode <= 499) {
throw new Exception("Bad authentication status: " + responseCode); //provide a more meaningful exception message
}
else {
InputStream in = con.getInputStream();
//etc...
}
I Don't know why, but dealing manually with redirection resolves the problem.
connection.setInstanceFollowRedirects(false);
A little late but you can also verify the accepted content. You can add this line to accept all kinds of contents
urlConnection.setRequestProperty("Accept","*/*");

Categories

Resources