Cancel AsyncTask when HTTPPost fails? - android

I'm trying to cancel my AsyncTask when connecting to the server fails. I tried cancel(), but the onPostExecute() method still gets called, instead of onCancelled().
This is what I have inside doInBackground():
protected String doInBackground(String... params) {
Log.i("ping", "doInBackground() started");
DefaultHttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 15000);
HttpResponse response;
HttpEntity entity;
try {
HttpPost post = new HttpPost("http://192.168.1.6/ping/login.php");
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("username", getEmail()));
nvps.add(new BasicNameValuePair("password", getPassword()));
post.setHeader("Content-Type", "application/x-www-form-urlencoded");
post.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
response = client.execute(post);
entity = response.getEntity();
InputStream iStream = entity.getContent();
read(iStream);
iStream.close();
if(entity != null)
entity.consumeContent();
Log.i("ping", "doInBackground() vervolgd");
} catch (Exception e) {
e.printStackTrace();
Log.e("tvsping", "Exception: " + e.getMessage());
cancel(true);
}
return null;
}
I'm trying to see what happens when the server can't be reached (I'm shutting it down, so there's no way my phone is getting any response) and I get IOException: the connection was reset.
Any ideas how I should check if the connection isn't made?
update
I solved this like Tanmay suggested, with a boolean. But I have another problem:
Every time doInBackground() is called it takes about three minutes to stop, when it can't find the servers. Everything is fine when it can reach the server, but I can't have this taking 3 minutes before the user is notified of anything (I could do a background process, but still a 3 minute wating bar is no good neither)
Any ideas what is wrong with my code? This can't be normal, right?

From doInBackground() method you are returning a String .You can return null if your HTTPPost fails.And then in onPostExecute() method just check what are you getting, if the String is null dont do anything which you really want and on successful running do your UI work
Hope this will help you.

HttpHost target = new HttpHost("192.168.2.3", 80);
HttpPost post = new HttpPost("/ping/login.php");
response = client.execute(target, post);
This solved the slow server response for me.

Related

I have got Socket Timeout Exception but My data submitted on server too

I have got an prob with http post request i have set time out and on socket time out exception my data submitted on server successfully how i can restrict data to submitted on server my code is following
try{HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(
AppSettings.SERVICE_URL.POST_NEW_REGISTRATION);
HttpConnectionParams.setConnectionTimeout(
httpClient.getParams(), 5000);
HttpConnectionParams.setSoTimeout(httpClient.getParams(), 5000);
JSONObject jsonObject = new JSONObject();
jsonObject.put("agent_id", SharedPrefrence.getUserID());
httpPost.setEntity(new StringEntity(jsonObject.toString(),
"UTF-8"));
// Set up the header types needed to properly transfer JSON
httpPost.setHeader("Content-Type", "application/json");
httpPost.setHeader("Accept-Encoding", "application/json");
// Execute POST
//int getConnectionTimeout (HttpParams params);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity responseEntity = httpResponse.getEntity();
if (responseEntity != null) {
response = EntityUtils.toString(responseEntity);
} else {
response = "{'success':'FALSE'}";
}
} catch (ClientProtocolException e) {
response = "{'success':'FALSE'}";
progressDialog.cancel();
} catch (IOException e) {
response = "{'success':'FALSE','message':'Connection Time Out'}";
Log.d("Ex", e.toString());
Log.e("Ex", e.toString());
progressDialog.cancel();
} catch (JSONException e) {
response = "{'success':'FALSE','message':'JSON Parse Error'}";
progressDialog.cancel();
e.printStackTrace();
} catch (Exception e) {
response = "{'success':'FALSE'}";
progressDialog.cancel();
e.printStackTrace();
}
I think you are saying that you are getting a socket timeout exception even though the data is successfully received by the server?
If so, I think you may want to look at the value you are setting for the socket timeout - this appears to be 500ms in your code, which is quite short. It is quite possible that everything on the server side is working fine, but that the response is simply not getting to the client within 500ms.
A typical default is in the 6-10 seconds range, but it is really solution dependent so you may want to experiment. This blog post suggests some defaults for different scenarios and may be a useful reference:
http://dev.bizo.com/2013/04/sensible-defaults-for-apache-httpclient.html
probably your API call takes more than 500 ms, increase it and try again.

Android Check how fast post request took

I am trying to check how fast a Post request took to execute. I am doing the request inside an AsyncTask.
This is how I am currently checking for execution time
long start = System.nanoTime();
new POSTTask().execute();
long end = System.nanoTime() - start;
I am not sure if the time given by this is the actual time it takes for the Post request. Inside the AsyncTask the only thing I am doing is the following
try {
HttpClient httpClient = new DefaultHttpClient();
HttpPost request = new HttpPost(url);
List<NameValuePair> postParameters = new ArrayList<>();
postParameters.add(new BasicNameValuePair("test", "tets1"));
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(postParameters);
request.setEntity(formEntity);
HttpResponse response = httpClient.execute(request);
result = EntityUtils.toString(response.getEntity());
Log.i("Result", result);
} catch (IOException e) {
e.printStackTrace();
}
Am I going about this the right way or the wrong way?
No, its not the actual time. You are trying to get execution time on main thread but your post query is running in a different thread in background.
Use it like this
try {
HttpClient httpClient = new DefaultHttpClient();
HttpPost request = new HttpPost(url);
List<NameValuePair> postParameters = new ArrayList<>();
postParameters.add(new BasicNameValuePair("test", "tets1"));
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(postParameters);
request.setEntity(formEntity);
long start = System.nanoTime();
HttpResponse response = httpClient.execute(request);
long end = System.nanoTime() - start;
// Print value of end here
result = EntityUtils.toString(response.getEntity());
Log.i("Result", result);
} catch (IOException e) {
e.printStackTrace();
}
Nope, this is wrong. The execute method on an AsyncTask returns immediately, before the request has been performed.
If you move the timing code into the AsyncTask, specifically by putting it around this line
HttpResponse response = httpClient.execute(request);
you will get the actual time.
that is wrong as those lines do not execute in order.
new POSTTask().execute();
starts a new thread meaning your 2 time stamps are going to be really close together like milliseconds apart and thats not accurate
what you should be doing all your timing in your doInBackground

How to handle the situation when server is down on my android side

Here is my doInBackground() method in which I call my makeHttpRequest() method which is in other class.
protected String doInBackground(Integer... args) {
// Building Parameters
String parameter1 = "tenant";
String parameter2 = "price";
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("person",parameter1));
params.add(new BasicNameValuePair("price",parameter2));
JSONObject json = jParser.makeHttpRequest(requiredurl, "POST", params);
Log.d("Details", json.toString());
int success = json.getInt("connected");
if (success == 1) {
//blah blah
}
}
makeHttpRequest() method:
public JSONObject makeHttpRequest(String url, String method,
List<NameValuePair> params) {
// Making HTTP request
try {
// check for request method
if(method == "POST"){
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(params));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
................
....................... // Here the result is extracted and made it to json object
.............................
// return JSON
return jObj; // returning the json object to the method that calls.
}
So, by the above code, the actual call to the server is made by this line -> HttpResponse httpResponse = httpClient.execute(httpPost);
When my server is up everything works fine, but when it is down the progress bar continuously loads. I want to handle this situation. Have done lot of search, but could find only this post. This looks good for my situation because even my thought is to wait for the 10 seconds to get the response and if it exceeds that time out, I need to handle it to show the message in the catch block. But I am unable to implement it according to my code. Can some one please help me on this? I would be very thankful.
Your exceptions are not getting hit because the HttpClient is not throwing an exception. Perhaps you are getting an error in your HttpResponse code, such as a 500. In your try block, add this line:
response.getStatusLine().getStatusCode()
Then read the status code. If your web server is up you should get a 200 OK, but if it's down, you'll probably get a 500 or something else. You can then handle the code here where your spinning progress bar needs to be hidden, and an error message can be displayed.
Add Following Code before executing the url.
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, 30000);
HttpConnectionParams.setSoTimeout(httpParameters, 30000);
DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
write the above code in try block and Catch ConnectTimeOutException and SocketConnectionTimeOutException. Where you can show some custom dialog.
You can also judge it by checking the status line of HttpClient Response.

Android service - data connection lost and can't restore

The background of my service: it implements LocationListener and in LocationManager instance (locMananager) registers for updates:
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
In onLocationChanged method it calls a method named recordTrace with a current location, which then calls getHttpResponse to send the location coordinates to a server. The latter method is as follows:
public InputStream getHttpResponse(String url, ArrayList<NameValuePair> params, int timeout) throws Exception {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, timeout);
httpClient.setParams(httpParams);
HttpPost post = new HttpPost(url);
if(params != null && !params.isEmpty()) {
try {
post.setEntity(new UrlEncodedFormEntity(params));
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "HttpPost.setEntity Error: " + e.getMessage());
lastError = "błąd HTTP";
}
}
CookieStore store = new BasicCookieStore();
if(localCookies != null && localCookies.size() > 0) {
for(int i = 0; i < localCookies.size(); i++) {
store.addCookie(localCookies.get(i));
}
}
HttpContext context = new BasicHttpContext();
context.setAttribute(ClientContext.COOKIE_STORE, store);
HttpResponse response = null;
HttpEntity entity = null;
InputStream content = null;
try {
response = httpClient.execute(post, context);
store = (CookieStore) context.getAttribute(ClientContext.COOKIE_STORE);
List<Cookie> cookies = store.getCookies();
if(cookies != null && cookies.size() > 0) {
localCookies = new ArrayList<BasicClientCookie>();
for(Cookie cookie : cookies) {
localCookies.add((BasicClientCookie) cookie);
}
}
entity = response.getEntity();
content = entity.getContent();
return content;
} catch (ClientProtocolException e) {
throw e;
} catch (IOException e) {
throw e;
} catch (Exception e) {
throw e;
}
}
params is a NameValuePair with prepared data, timeout is set to 5000 (5 seconds). ArrayList localCookies holds cookies saved before, after successful logging in (to keep the session).
The problem is: when I loose a mobile signal (i.e. when I go to a subway) and restore it, I get IOException, which is unrecoverable unless I restart the phone.
Any help would be appreciated. I'm loosing my mind and going bald!
Thanks,
Peter.
EDIT
I've done some research. After the method getHttpResponse is invoked, I utilize InputStream returned by it, but don't close it after all. Do you thing that might be the issue? Is this possible that the operator breaks the connection and then establishes a new one, whereas my InputStream somehow "keeps" the former connection and produces the problems with data transfer?
I added a finally block where now the InputSTream is closed. However, since it's hard to cause the problem on demand (it doesn't happen regularly), I can't check if closing stream solves it.
After a few days of testing it seems I've found the solution. Calling 2 methods solves the issue:
close the InputStream returned by httpResponse.getEntity()
shutdown the connection by executing httpClient.getConnectionManager().shutdown()
Code snippet of a complete request and response handling:
String url = "www.someurl.com";
ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("login", "mylogin"));
params.add(new BasicNameValuePair("password", "mypassword"));
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
try {
httpPost.setEntity(new UrlEncodedFormEntity(params));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
InputStream content = httpEntity.getContent();
/*
* utilize content here...
*/
content.close(); // here's the point
httpClient.getConnectionManager().shutdown(); // the second important thing
}
catch (UnsupportedEncodingException e) {}
catch (ClientProtocolException e) {}
catch (IOException e) {}
I'm answering my own question since I've spent a lot of time on searching what's causing the problem and I think I can save somebody's time. After a few days the aplication is still working and doesn't break the connection.
Regards,
Peter.

Android development -Unknown Host exception problem

I'm developing an Android app that gets a JSON_encoded result from a php middleware script that connects to a MySQL database. I have given the application Internet permissions.
The problem I'm having is that the program gives an UnknownHostException error the first time it is run. I have the program on a timer, and subsequent calls to the timer handler function do not return the UnknownHostException error. Do you have any idea why this would occur? I have tested the domain and made sure that it connects correctly through a web browser.
Here's a snippet from the code:
public final void timerAlert(){
final Handler handler = new Handler();
final Runnable r = new Runnable()
{
public void run() {
Timer_Method();
handler.postDelayed(this,1000);
}
};
handler.postDelayed(r, 1000);
}
public void Timer_Method()
{
//See if this buzzer is being signaled.
String result = null;
InputStream is = null;
StringBuilder sb=null;
//http post
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("BuzzerID",BuzzerID.toString()));
Toast.makeText(getBaseContext(), "BuzzerID="+BuzzerID.toString() ,Toast.LENGTH_LONG).show();
try{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://domain/getBuzzStatus.php?BuzzerID="+BuzzerID.toString());
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
}catch(Exception e){
Log.e("log_tag", "Error in http connection"+e.toString());
Toast.makeText(getBaseContext(), "Hm, problem here="+e.toString() ,Toast.LENGTH_LONG).show();
}
Note that domain has something else there in the actual code and that this is just a snippet but is where the first issue occurs. Also note that I am mixing get and post, something I'd rather not do, but for some reason passing the nameValuePair to the php script doesn't send anything to $_REQUEST.
A snippet from the very simple PHP script:
$sql_string="SELECT Signal FROM BuzzCustomer WHERE idBuzzCustomer=" . $_GET['BuzzerID'];
$sql = mysql_query($sql_string);
while($row=mysql_fetch_assoc($sql))
$output[]=$row;
print(json_encode($output));
mysql_close();
I switched to $_GET here because I could not get $_REQUEST to work. Any help would be appreciated. Thanks in advance!
May be their will be no Internet connection in the simulator......Check a url in browser
Instead of
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
Use
ResponseHandler<String> response = new BasicResponseHandler();
String result = httpclient.execute(httppost,response);
Also put Internet permission in the Manifest
Just a guess, but maybe the DNS request takes too long and your HttpClient gives up, but the request is finished and cached so the next time it does not fail?
This With Apache HttpClient, why isn't my connection timeout working? seems to be a question about how to set the timeout for HttpClient.

Categories

Resources