HTTP Post requests using HttpClient take 2 seconds, why? - android

Update:
Found the answer myself, see below :-)
Hi,
I'am currently coding an android app that submits stuff in the background using HTTP Post and AsyncTask. I use the org.apache.http.client Package for this. I based my code on this example.
Basically, my code looks like this:
public void postData() {
// Create a new HttpClient and Post Header
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://192.168.1.137:8880/form");
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("id", "12345"));
nameValuePairs.add(new BasicNameValuePair("stringdata", "AndDev is Cool!"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
} catch (ClientProtocolException e) {
Log.e(TAG,e.toString());
} catch (IOException e) {
Log.e(TAG,e.toString());
}
}
The problem is that the httpclient.execute(..) line takes around 1.5 to 3 seconds, and I do not understand why. Just requesting a page with HTTP Get takes around 80 ms or so, so the problem doesn't seem to be the network latency itself.
The problem doesn't seem to be on the server side either, I have also tried POSTing data to http://www.disney.com/ with similarly slow results. And Firebug shows 1 ms response time when POSTing data to my server locally.
This happens on the Emulator and with my Nexus One (both with Android 2.2).
If you want to look at the complete code, I've put it on GitHub.
It's just a dummy program to do HTTP Post in the background using AsyncTask on the push of a button. It's my first Android app, and my first java code for a long time. And incidentially, also my first question on Stackoverflow ;-)
Any ideas why httpclient.execute(httppost) takes so long?

Allright, I solved this myself with some more investigation. All I had to do was to add a parameter that sets the HTTP Version to 1.1, as follows:
HttpParams params = new BasicHttpParams();
params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
HttpClient httpclient = new DefaultHttpClient(params);
I found this thanks to the very nice HttpHelper Class from and-bookworm and some trial-and-error.
If I remember correctly, HTTP 1.0 opens a new TCP connection for every request. Does that explain the large delay?
A HTTP POST request now takes between 50 and 150 ms over WLAN and something between 300 and 500 ms over 3G.

i am not on android, but i faced exactly the same kind of problem on windows platform with httpclient 4.0.1, after quite a bit of head scratching, i found the solution.
HttpParams params = new BasicHttpParams();
//this how tiny it might seems, is actually absoluty needed. otherwise http client lags for 2sec.
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpClient httpClient = new DefaultHttpClient(params);
HttpResponse httpResponse;
HttpPost httpPost = new HttpPost("http://"+server+":"+port+"/");
StringEntity entity = new StringEntity(content, "utf-8");
entity.setContentType("text/plain; charset=utf-8");
httpPost.setEntity(entity);
httpResponse=httpClient.execute(httpPost);
String response = IOUtils.toString(httpResponse.getEntity().getContent(),encoding);
httpResponse.getEntity().consumeContent();
httpClient.getConnectionManager().shutdown();
return(response);
i have no idea why setting the parameters with HTTP1.1 version solves the problem. but it does.
also even weirder, the symptom did not show if executing an HTTP Get request.
anyhow, i hope this helps some out there !
h

Related

Can I use HttpClient to do a PUT or Delete

Currently I am connecting from android to a .net WEB API using HttpClient and I have been able to do a GET and POST to read/write data. However I want to do an Update and a Delete.
I tried to do this using a POST, but it simple creates more records. Here is my code for the POST, how would I change it to do a PUT or DELETE instead?
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://mywebsite.net/api/employees/6");
try {
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(5);
nameValuePairs.add(new BasicNameValuePair("firstName", "UpdatedHello"));
nameValuePairs.add(new BasicNameValuePair("lastName", "World"));
nameValuePairs.add(new BasicNameValuePair("employee_name", "UpdatedHello World"));
nameValuePairs.add(new BasicNameValuePair("password", "xxx"));
nameValuePairs.add(new BasicNameValuePair("isActive", "1"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
yeah! the document of httpClient http://hc.apache.org/httpclient-3.x/methods.html
You have PutMethod and DeleteMethod API for performing PUT and DELETE Http requests. The sample usage as follows as per doc
PUT Request - The put method is very simple, it takes a URL to put to and requires that the body of the request method be set to the data to upload. The body can be set with an input stream or a string.This method is generally disabled on publicly available servers because it is generally undesireable to allow clients to put new files on the server or to replace existing files.
PutMethod put = new PutMethod("http://jakarta.apache.org");
put.setRequestBody(new FileInputStream("UploadMe.gif"));
// execute the method and handle any error responses.
...
// Handle the response. Note that a successful response may not be
// 200, but may also be 201 Created, 204 No Content or any of the other
// 2xx range responses.
DELETE Request - The delete method is used by supplying a URL to delete the resource at and reading the response from the server.This method is also generally disabled on publicly available servers because it is generally undesireable to allow clients to delete files on the server.
DeleteMethod delete = new DeleteMethod("http://jakarata.apache.org");
// execute the method and handle any error responses.
...
// Ensure that if there is a response body it is read, then release the
// connection.
...
delete.releaseConnection();

Why don't Android web requests automatically follow redirects? [duplicate]

This question already has answers here:
Handling HttpClient Redirects
(5 answers)
Closed 9 years ago.
I had an issue a few weeks ago in a WebView where it wasn't following redirects as a normal browser would. I used the following suggestion given in many SO answers:
String newUrl = response.getFirstHeader("Location").getValue();
but it only gave 1 step of redirection, but not more, which it needed to. I got around it by repeatedly listening for redirects and manually going through each step.
Now I'm using the following code:
HttpClient httpClient = MyApp.getHttpClient();
HttpPost httpPost = new HttpPost(con.getString(R.string.platform_url_getBalances));
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("sid", String.valueOf(sessionKey)));
ResponseHandler<String> responseHandler = new BasicResponseHandler();
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
String response = null;
// Execute HTTP Post Request. Response body returned as a string
response = httpClient.execute(httpPost, responseHandler);
Recently the end-point for the R.string.platform_url_getBalances changed but we put in a 302 redirect to a different URL. It works fine in a browser and on the iPad version of the app but for Android I get org.apache.http.client.HttpResponseException: Not Found.
I find it very strange that Android is such a pain when it comes to redirecting. Why does it behave like this and is there a reasonable way around it?
Actually, the answer I linked to in my comment is for HttpClient 4.1, near as I can tell, and Android's is older.
My guess is that the equivalent process in Android's version of HttpClient would be do:
Create a subclass of DefaultRedirectHandler that overrides isRedirectRequested() as appropriate for your app
Create a subclass of DefaultHttpClient and override createRedirectHandler() to return an instance of the subclass you created in the previous step
Use your subclass of DefaultHttpClient as a replacement for DefaultHttpClient itself wherever you are creating that instance

httpclient.execute(httppost) issue with Android 4.0 and higher

I'm writing an application for Android. The application connects to a server to retrieve comments.
The code of interest is:
BufferedReader input = null;
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://www.domain.com/personal_proj/directorydirectory/file.php");
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
Log.i("TEST","after httpclient.execute()");
HttpEntity entity = response.getEntity();
I tested this code in HTC Wildfire, HTC Desire Z and it works. If this code is executed in Android 4.0+, it never reach the line
Log.i("TEST","after httpclient.execute()");
, the server never gets the request and it never throw an exception.
Any ideas?
I'm not sure what the default connection and socket timeout parameters are for the no arg constructed DefaultHttpClient, but I'd check that, or set the params:
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, 15000);
HttpConnectionParams.setSoTimeout(params, 20000);
Then construct your HttpClient with the params:
new DefaultHttpClient(params)
At that point you should at least get the timeout, if no other response.
Also look at AndroidHttpClient (it sets up reasonable timeouts, among other things like gzip support), and consider the advice to prefer HttpUrlConnection (though there are caveats with that).
Thanks to Charlie Collins i have noticed that i have not handled well the exception. The exception that i captured it's android.os.NetworkOnMainThreadException. This means that i can't perform a networking operation on the main thread (this is thrown for applications targeting 3.0+). Using AsyncTask worked for me.

Android Login to Website - POST Request Crashing App

I have a site that I would like to log into. Once there, I would parse the code to display member data (like any other login app). I have sort of pulled this code from somewhere and I'd like to know why it's crashing. Basically, I have two login inputs, username and password. I'll take them from the user but as of now I'm just inputting random credentials for testing. At the end, I want to get it to the login page (same url once logged in) and display the HTML, for now.
Here's my code so far:
HttpClient httpClient = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(httpClient.getParams(), TIMEOUT_MS);
HttpConnectionParams.setSoTimeout(httpClient.getParams(), TIMEOUT_MS);
HttpPost httpPost = new HttpPost("login url"); // Removed for StackOverflow question
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("sid", "name"));
nameValuePairs.add(new BasicNameValuePair("pin", "pass"));
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpClient.execute(httpPost);
BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()), 8096);
tvStatus.setText((CharSequence) br);
Are you running the POST request on the UI thread? This causes the UI to freeze and after a certain time period, the OS considers the app to be non-responsive and force closes it. Web Requests should always be an Async task
I guess this post on my blog will help you to understand, how to use AsyncTask, for downloading stuff.
Though if you tell us what is the Exception which is getting thrown up, I could've helped you more on this. To see the Exception, open the LogCat,identify the error text which will be in red, copy the whole red text and paste it into your question.

Android: Get response from a https url

Greetings,
I'm developing an Android app and need to open a url (with POST parameters) over https and get the response.
There's the added complication that I have a self-signed certificate. I also need to accept cookies.
Anyone have any ideas about where to get started?
Many thanks in advance,
Android comes with the apache commons http library included.
Setting up a https post request is quite easy:
HttpPost post = new HttpPost("https://yourdomain.com/yourskript.xyz");
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("postValue1", "my Value"));
nameValuePairs.add(new BasicNameValuePair("postValue2", "2nd Value"));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(post);
HttpEntity entity = response.getEntity();
String responseText = EntityUtils.toString(entity);
Android uses a version 4.x of the commons http library as all versions below 4.0 are out of their lifecycle.
I can't tell exactly how to register a self-signed certificate to the HttpClient, but mybe the commons http documentation helps:
http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
I managed to get it all working asyncronously with both cookies and unsigned https.
I used the code here:
http://masl.cis.gvsu.edu/2010/04/05/android-code-sample-asynchronous-http-connections/
and modified for unsigned https using Brian Yarger's code here:
Self-signed SSL acceptance on Android
(Add the above code to the beginning of run() in HttpConnection.java)
To get the cookies to work, I had to modify some code (POST snippet from HttpConnection.java):
case POST:
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new StringEntity(data));
httpPost.addHeader("Cookie", Cookie.getCookie());
response = httpClient.execute(httpPost);
Header[] headers=response.getAllHeaders();
for(int i=0;i<headers.length;i++){
if(headers[i].getName().equalsIgnoreCase("Set-Cookie")){
//Log.i("i",headers[i].getName()+"---"+headers[i].getValue());
Cookie.setCookie(headers[i].getValue());
break;
}
}
break;
Many thanks to everyone for pointing me in the direction,

Categories

Resources