I'm having some trouble making a simple HTTP POST request on a website. It seems like the POST parameters is not being sent!
Scenario:
HTTP Response code 200 - Wrong User/Pass - Occurring on Android 4.0+
HTTP Response code 302 - User/Pass OK - Occurring on others SDK versions
The Web form thats works OK:
<form id="form_mn_login" enctype="application/x-www-form-urlencoded" action="http://dummyhost/r.php" class="estil" accept-charset="utf-8" method="post">
<input type="text" name="m_email" id="m_email" />
<input type="password" name="m_senha" id="m_senha" />
The code (inside doInBackground AsyncTask's method):
urlParameters = "m_email="
+ URLEncoder.encode(username, "UTF-8") + "&m_senha="
+ URLEncoder.encode(password, "UTF-8");
URL url;
HttpURLConnection connection = null;
// Create connection
url = new URL("http://dummyhost/r.php");
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Language", "en-US");
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
// Send request
DataOutputStream wr = new DataOutputStream(
connection.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
publishProgress(30);
Log.w("responsecode", Integer.toString(connection.getResponseCode()));
This issue only shows up when I emulate it on Android 4.0+ AVD Devices. (Tried on 2.2,2.3.3, 3.0 and it works flawlessly)
What am I missing?
I'm aware maybe this is an server issue, but I really believe there must be an workaround for this. I've tried thousands of different ways of doing it but none seems to work as it should.
Thanks a lot,
RC
Related
Does HttpURLConnection that works for android API 23 also work for android API22?
I'm trying to program for android version over 4.0.
I am unsure if the difference between sdk22 and sdk23 will cause a problem
// http client
URL url = new URL(url1);
HttpURLConnection httpClient = (HttpURLConnection) url.openConnection();
httpClient.setRequestMethod("POST");
httpClient.setUseCaches(false);
httpClient.setDoInput(true);
httpClient.setDoOutput(true);
httpClient.setRequestProperty("Connection", "Keep-Alive");
httpClient.addRequestProperty("Content-length", reqEntity.getContentLength() + "");
OutputStream os = httpClient.getOutputStream();
reqEntity.writeTo(httpClient.getOutputStream());
os.close();
httpClient.connect();
if (httpClient.getResponseCode() == HttpURLConnection.HTTP_OK) {
return readStream(httpClient.getInputStream());
Yes it will work without any issues, and the difference will not cause any problem
HttpUrlConnection is available in from API Level 1 , you can further get more insight from the docs.
Its a good practice to use HttpUrlConnection over deprecated Apache HttpClient classes,
i'm trying to get the source code from a site using this code
conn = (HttpURLConnection)url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(20000);
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.addRequestProperty("User-Agent", "Mozilla/5.0");
conn.setRequestProperty("Accept-Encoding", "gzip, deflate");
int response = conn.getResponseCode();
if (response = 307){
String locationHeader = conn.getHeaderField("Location");
URL redirectURL = new URL(locationHeader);
...
}
when the server responds with a 307 code i create a new connection with the same parameters as above with the new url given by the server.
this code works fine while following the first 2 redirects, at the third the server gives a relative url that forces a MalformedURLException when my code executes ' new URL(locationHeader); '.
so i tried to fix that adding the ' http://servername/ ' to the ' locationHeader ' string but doing that creates a loop cause the server then redirects to the first url of his redirection chain.
since my browser gets the source code from that server with no problems is there a way to achieve that with HttpURLConnection?
if someone is interested thanks to Fiddler i worked out a solution to this issue.
first i changed the "User-Agent" property to mimic the one of Mozilla then i manually tweaked the cookie the serer was sending in its reply with the relative path.
that did the trick. thank you Fiddler.
I need to post schoolname=xyz&schoolid=1234 to server. I wrote the following Android client code:
String data = "schoolname=xyz&schoolid=1234";
//The url is correct
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Accept-Encoding", "gzip");
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = new BufferedOutputStream(conn.getOutputStream());
os.write(data.toString().getBytes("UTF-8"));
//response complains that missing parameter 'schoolname'
int responseCode = conn.getResponseCode();
...
After I send my request with above code, server however constantly complains that schoolname parameter is missing. What do I miss or did wrong?
Have a look at [this example that explains How to use a HttpURLConnection to POST data
If you're planning on doing a lot of web communication, take a look at Square's Retrofit which will help you automate a lot of this work.
You can't use the format "key=value&key1=value1" for http post. That would work fine only for get. In this case you need something like this:
List<NameValuePair> nameValuePairs;
nameValuePairs.add(new BasicNameValuePair("schoolname", "xyz"));
nameValuePairs.add(new BasicNameValuePair("schoolid", "1234"));
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
httpPost.execute();
I figured out myself, the reason is that I forget to call flush() on output stream. After flush it, everything works fine.
Working on the emulator, but when I am trying on an HTC Sense, i have got an exception on the last line of this code
url = new URL(urlString);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/json; charset=utf-8");
//Send request
Gson requestGson = new Gson();
OutputStream wr = connection.getOutputStream();
The exception is java.net.ProtocolException: Does not support output for the connection.getOutputStream();
I am testing on API 10, Gingerbread on an HTC Sense (remote debugging).
anyone has encountered this problem before?
Thanks.
David.
Try calling setDoOutput(true). It is needed for POST requests. The first part of your code would change to look like this:
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/json; charset=utf-8");
connection.setDoOutput(true);
Source: https://groups.google.com/forum/?fromgroups=#!topic/android-developers/2aEYpsZEMvs
See also this other StackOverflow answer: What exactly does URLConnection.setDoOutput() affect?
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?