https on tmobile android super slow (using httpclient.execute method) - android

I have an application that makes numerous calls to REST web services I have written. I have noticed in general that when I added SSL the web calls went from <1 sec to ~3sec to execute. Is that normal when adding SSL? I have measured the times using the Droid, HTC Thunderbolt, and Samsung Tablet (all on Verizon).
What is really CRAZY is:
whenever using a phone on the TMobile network (Comet and Nexus) those same calls (over HTTPs) take 30-40 seconds each. If I remove SSL those same calls take <1s just like the other devices. Any clue as to why SSL on the TMobile devices is having this issues? I am stumped?
Code:
String url = BASE_URL + path;
HttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter("http.socket.timeout", new Integer(30000));
httpclient.getParams().setParameter("setSocketBufferSize", 8192);
HttpPost httppost = new HttpPost(url);
httppost.addHeader("Content-Type", "text/json");
InputStream istream = null;
try {
httppost.setEntity(new StringEntity(request.toString()));
HttpResponse response = httpclient.execute(httppost);
istream = response.getEntity().getContent();
String result = IOUtils.toString(istream);
...

Related

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.

EntityUtils reports NoApplicableCode exception for Android request

I am trying to retrieve a JSON file from a web service using the following URL. That works fine when I use a browser to send the HTTP request.
For the Android application I came up with the following code.
// Android request
String url = "http://data.wien.gv.at/daten/geoserver/ows?service=WFS" +
"&request=GetFeature&version=1.1.0&typeName=ogdwien:BAUMOGD" +
"&srsName=EPSG:4326&outputFormat=json" +
"&bbox=16.377681,48.211448,16.379829,48.21341,EPSG:4326" +
"&maxfeatures=10"
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity);
Though, EntityUtils does not output a JSON file but this XML exception.
// Value of result
<?xml version="1.0" encoding="UTF-8"?>
<ows:ExceptionReport version="1.0.0"
xsi:schemaLocation="http://www.opengis.net/ows http://data.wien.gv.at/daten/geoserver/schemas/ows/1.0.0/owsExceptionReport.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ows="http://www.opengis.net/ows">
<ows:Exception exceptionCode="NoApplicableCode">
<ows:ExceptionText>java.io.EOFException: input contained no data
input contained no data</ows:ExceptionText>
</ows:Exception>
</ows:ExceptionReport>
I hope you can see what wents wrong ...
The HTML specifications technically define the difference between "GET" and "POST" so that former means that form data is to be encoded (by a browser) into a URL while the latter means that the form data is to appear within a message body. > [source]
Since you do encode the full request into the URL (request=GetFeature etc.) => use HttpGet instead.
Might even work imo with post since the url should still be transmitted to the server but the server would need to detect that the post request is actually a get request and behave accordingly.

HttpPost: No "Set-Cookie" Header

I want to get the session cookie of a website. Unfortunately the "Set-Cookie"-Header doesn't show up.
Here's the code I've written:
"commands" is a String[][] and the whole code is wrapped by try/catch.
CookieStore cookieStore = new BasicCookieStore();
HttpContext localContext = new BasicHttpContext();
localContext.setAttribute(ClientContext.COOKIE_STORE,cookieStore);
HttpPost httppost = new HttpPost(url);
List<NameValuePair> nvps = new ArrayList<NameValuePair>(0);
for (int i=0;i<commands.length;++i)
nvps.add(new BasicNameValuePair(commands[i][0],commands[i][1]));
httppost.setEntity(new UrlEncodedFormEntity(nvps,HTTP.UTF_8));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
Header[] headers = response.getAllHeaders();
List<Cookie> cookies = cookieStore.getCookies();
String data = EntityUtils.toString(entity);
My understanding of Http Communication tells me that there should be a "Set-Cookie" Header. The only Headers I get from response.getAllHeaders() are Connection:close, X-Powered-By:PHP/4.3.4 and Content-Type:text/html
There is a bit of javascript included in the returned data (response.getEntity()).
<script language = "javascript">
<!--
location.href="/index.php";
function SetCookie(name,value,expire,path){
document.cookie = name + "=" + escape(value) + ((path == null) ? "":(";path="+path))
}
var iad = 461180104
SetCookie("iad",iad,0,"/")
-->
</script>
As far as I understand this, this code is never executed because it's just a comment ?!
But as well this is probably the bit where the cookie should be created.
Any ideas?
UPDATE:
"Opera Mobile" is the only browser for Android I found which has no problem with cookies on this site. "Opera Mini", "Dolphin HD" and the Froyo Stock browser all fail. No Desktop browser has problems connecting. Is this a webkit issue? And if this is the case: how to avoid it?
Using Chrome's developer tools or Firebug, check the HTTP response for the "expires" parameter in the Set-Cookie header field. Make sure the time / date settings on the phone are set correctly. If the browser thinks the cookie is already expired, it won't store it.
If that doesn't work try using wireshark / tshark to grab a trace of the communication from your client, and compare it to a browser that's working the way you expect it to.
By the way, the comment delimiters around that bit of Javascript don't prevent the script from being run; they just prevent older (really old) browsers from trying to render the script in the document. That cookie ("iab") doesn't look like the cookie for authentication. There's likely an http-only cookie with a session identifier; you should be able to see it using the aforementioned Firebug / Dev tools.

HTTP Post requests using HttpClient take 2 seconds, why?

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

Categories

Resources