I'm developing an Android app which works with server. I have POST request (using HttpURLConnection). Code is:
//setting URL to HttpURLConnection conn
conn.setReadTimeout(30000);
conn.setConnectTimeout(14000);
conn.setChunkedStreamingMode(0);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
Uri.Builder builder = new Uri.Builder();
for (Map.Entry<String, String> entry : paramList.entrySet())
builder.appendQueryParameter(entry.getKey(), entry.getValue());
String query = builder.build().getEncodedQuery();
DataOutputStream os = new DataOutputStream(conn.getOutputStream());
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(query);
writer.flush();
writer.close();
os.close();
responseCode = conn.getResponseCode(); // IOException!
BufferedReader in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
In case of error I need to show exact error message, for instance, "Connection timeout", or "Read timeout", or "Authorization problems" (for 401 status), etc.
How can I handle:
Connection timeout?
ReadTimeout?
And how can I get response code if it throws an IOException if server responses 4xx status? I read several questions here, but I didn't understand, how can I handle timeout errors and how can I get response code in case of IOException.
Related
Currently, I am working on creating a Android app to read and create google sites content. It seems like the java api doesn't work for Android, so I use google protocol
https://developers.google.com/google-apps/sites/docs/1.0/developers_guide_protocol#ContentFeedPOST.
I can get all the content on google site by this GET request
https://sites.google.com/feeds/site/domainName.
But I have no idea how to send a POST request to create a content beside on the google api guide.
Hope anyone could help me with this. All I need is how to send the request in curl.
Thanks!
you can try curl command like this:
curl -H "Content-Type: your-content-type" -X POST -d 'your-data' https://localhost:8080/api/login
And to post data using HttpUrlConnection class use following:
HttpURLConnection connection = null;
try {
//Create connection
url = new URL(targetURL);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"your-content-type");//set required content type
connection.setRequestProperty("Content-Length", "" +
data.getBytes().length);//set Content-Length header using your data length in bytes
connection.setRequestProperty("Content-Language", "en-US");
connection.setDoInput(true);
connection.setDoOutput(true);
//Send request
DataOutputStream wr = new DataOutputStream (
connection.getOutputStream ());
wr.writeBytes (data);//write data to o/p stream
wr.flush ();
wr.close ();
//Get Response
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuffer response = new StringBuffer();
while((line = rd.readLine()) != null) {
response.append(line);
response.append('\r');
}
rd.close();
return response.toString();
} catch (Exception e) {
} finally {
if(connection != null) {
connection.disconnect();
}
}
i have an android application that makes an HTTP post request to a server containing some NameValuePairs, and It works just fine over any wifi network, but when i use the same http post over 3g, the server gets a http request with an empty body. Here is the code for the request
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(
3);
nameValuePairs.add(new BasicNameValuePair("Name", params[0]));
nameValuePairs.add(new BasicNameValuePair("DNI", params[1]));
nameValuePairs.add(new BasicNameValuePair("Token", params[2]));
URL url = new URL(URL_SERVER);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.setReadTimeout(30000);
conn.setConnectTimeout(50000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(getQuery(nameValuePairs));
writer.flush();
writer.close();
os.close();
conn.connect();
int responseCode = conn.getResponseCode();
BufferedReader in;
if (responseCode == 404)
in = new BufferedReader(new InputStreamReader(
conn.getErrorStream()));
else
in = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
Here is the code for the getQuery method
private String getQuery(List<NameValuePair> params)
throws UnsupportedEncodingException {
StringBuilder result = new StringBuilder();
boolean first = true;
for (NameValuePair pair : params) {
if (first)
first = false;
else
result.append("&");
result.append(URLEncoder.encode(pair.getName(), "UTF-8"));
result.append("=");
result.append(URLEncoder.encode(pair.getValue(), "UTF-8"));
}
return result.toString();
}
Any idea why this happens?
I have new info. I made a form to send the http post over the web browser. that form works great and sends perfectly the body over 3g on Windows phone and over wifi. But when I try to use the chrome of the android phone over 3g to send the http post, it arrives empty, and also if I try to send the http post from one computer connected to a hotspot of my android phone it fails. When i try with the same computer connected to a wifi network, no problem at all. This is so weird. Ideas?
My advice is to use Google's Volley library for networking. It is pretty much the best choice currently when it comes to networking on Android. It really should not be a 3G problem. If it is, you problem might be an isolated one.
Here you have some resources to look at(volley is really easy to use):
https://developers.google.com/events/io/sessions/325304728
https://developer.android.com/training/volley/index.html
Solved, the problem was that the server didn't read properly the requests that had multiple tcp datagrams, and looks like android split the tcp datagrams over 3g
I got IOException when i try call getCodeResponse(). When parameters are valid there is no exception and code response is 200. In case of wrong parameteres server should return 401 code. I've tested query on hurl.it and in case of wrong parameters i got 401 code. Maybe HttpURLConnection class throws exception when error code occurs.
URL url = new URL(sUrl);
String charset = "UTF-8";
conn = (HttpsURLConnection) url.openConnection();
conn.setReadTimeout(DEFAULT_TIMEOUT /* milliseconds */);
conn.setConnectTimeout(DEFAULT_TIMEOUT /* milliseconds */);
conn.setRequestMethod(methodType);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.addRequestProperty("Accept-Charset", charset);
conn.addRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.addRequestProperty(HEADER_ACCEPT_ENCODING, ENCODING_GZIP);
conn.setDoOutput(true);
conn.setInstanceFollowRedirects(false);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os));
writer.write(query);
writer.flush();
writer.close();
//os.write(query.getBytes());
os.flush();
os.close();
conn.connect();
if(conn != null){
responseCode = conn.getResponseCode();
result = readResponse(conn);
}
The IOException means that there is a 401 response. Print the stacktrace and if everything else is correct, it'll give a 401 response. Something like : java.io.IOException: Server returned HTTP response code: 401 for URL:
I'm trying to do a post method for a REST service, but I'm not getting any response from server:
public JSONObject postValues (String strUrl, String strJsonArray) throws Exception{
JSONObject jsonObject = null;
URL url = new URL(strUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
strJsonArray = "data=" + strJsonArray;
Log.e("result",""+strJsonArray);
OutputStream os = conn.getOutputStream();
os.write(strJsonArray.getBytes());
os.flush();
conn.connect();
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));
String output;
StringBuilder sb = new StringBuilder();
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
Log.e("output",output);
sb.append(output);
}
Log.e("output",sb.toString());
jsonObject = new JSONObject(sb.toString());
conn.disconnect();
return jsonObject;
}
When I see my logCat a get:
output {}
I know that the server is working right because I'm using the "advanced REST client" plugin of google chrome. If I call the URL manually (using the plugin of course)I get the desired answer:
{"message":"OK","code":200}
But if I try to use my function, my strJsonArray is inserted but I get an empty respond from server.
Is there anything wrong with my code?.
Everything looks good...
You could use Wireshark to capture the packets sent to and received from the server using an emulator and the chrome rest client. Then you can compare them and maybe find out what's wrong.
You could also check if theres something in the error stream (conn.getErrorStream()).
Our server expects 'application/x-www-form-urlencoded' content-type on POST calls but when I set the header to 'application/x-www-form-urlencoded', it returns a 400 Bad Request. Here's my code using HttpPost:
DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader(HTTP.CONTENT_TYPE, "application/x-www-form-urlencoded; charset=UTF-8");
httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
HttpResponse responseobj = httpClient.execute(httpPost);
InputStream is = null;
HttpEntity entity = responseobj.getEntity();
is = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
Here's my code using HttpsUrlConnection:
URL urlToRequest;
urlToRequest = new URL(url);
HttpsURLConnection conn = (HttpsURLConnection) urlToRequest.openConnection();
String postParams = getEncodedPostParams(params);
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setFixedLengthStreamingMode(postParams.getBytes().length);
conn.setRequestProperty(HTTP.CONTENT_TYPE, "application/x-www-form-urlencoded; charset=UTF-8");
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
writer.write(postParams);
writer.close();
os.close();
conn.connect();
Here's the request on Charles Proxy. You can see that although I have set the content-type to 'application/x-www-form-urlencoded' in both cases, the request content-type is 'application/json':
https://myurl/
Complete
400 Bad Request
HTTP/1.1
POST
application/json
Does anyone know why I cannot change the content-type? I know similar questions have been asked before on SO and I have tried all of them to no avail. Your help would be greatly appreciated.
Thanks!
Why don't use:
con.setRequestProperty("Content-Type",....)
it worked for me.