2

I am trying to connect to internet where I have to fetch data, if the time exceeds more than 5 secs to connect I have to finish the process & continue to work offline.
Everything is working fine, sometimes it takes around 10secs to return when internet is not available, Now I have to return the xml == null; when the time exceeds more than time limit,
I don't want to do this in Async Task

    public String getUrlData(String url) {
    String xml = null;

    DefaultHttpClient httpClient = new DefaultHttpClient();
    HttpPost httpPost = new HttpPost(url);
    System.out.println("waiting");
    HttpResponse httpResponse;

    try {
        // start the timer here

        httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        xml = EntityUtils.toString(httpEntity);

        // check if the timer has exceeded by "if else"
        // move to "return xml;" Manually when exceeds 5sec, but how?

    } catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return xml;

}

Edited Code after this answer

public String getUrlData(String url) {
    String xml = null;

    final int TIMEOUT_MILLISEC = 5000; // 5 seconds

    HttpParams httpParams = new BasicHttpParams();
    HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT_MILLISEC);
    HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT_MILLISEC);

    DefaultHttpClient httpClient = new DefaultHttpClient(httpParams);
    HttpPost httpPost = new HttpPost(url);
    System.out.println("waiting");
    HttpResponse httpResponse;

    try {
        // start the timer here
        System.out.println("Started");
        httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        xml = EntityUtils.toString(httpEntity);

    } catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    System.out.println("Ended");
    return xml;

}

LogCat Here >> 20 Secs

Community
  • 1
  • 1
VenomVendor
  • 15,064
  • 13
  • 65
  • 96
  • Did you try this on a real device or on the emulator? While experimenting with the DefaultHttpClient I noticed that setting a timeout doesn't work properly in the emulator. It basically just ignores any timeout setting (see also [this post](http://stackoverflow.com/a/10812506/741249)) – THelper Sep 13 '12 at 12:44
  • But, my requirement is not that, I need something to skip my execution of HTTP request after 5secs & return the xml as null. If the xml is returned before 5sec then nothing should happen. – VenomVendor Sep 13 '12 at 13:59
  • 1
    If you set a timeout as suggested by Waqas your http-request will automatically be stopped after the timeout interval and an error will be thrown. All you have to do is catch the error an return null. My point is that this will only work on real devices and not in the emulator. – THelper Sep 13 '12 at 14:06

5 Answers5

8

All you need to do is to define a timeout limit for your connections. For example:

final int TIMEOUT_MILLISEC = 5000;  // 5 seconds

HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT_MILLISEC);
HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT_MILLISEC);

HttpClient httpClient = new DefaultHttpClient(httpParams);

and afterwards, use httpClient in the same way you are using it.


Edit

public String getUrlData(String url) {
String xml = null;

final int TIMEOUT_MILLISEC = 5000;  // 5 seconds

HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT_MILLISEC);
HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT_MILLISEC);

DefaultHttpClient httpClient = new DefaultHttpClient(httpParams);
HttpPost httpPost = new HttpPost(url);
System.out.println("waiting");
HttpResponse httpResponse;

try {
    // start the timer here

    httpResponse = httpClient.execute(httpPost);
    HttpEntity httpEntity = httpResponse.getEntity();
    xml = EntityUtils.toString(httpEntity);

    // check if the timer has exceeded by "if else"
    // move to "return xml;" Manually when exceeds 5sec, but how?

} catch (ClientProtocolException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
return xml;

}
waqaslam
  • 67,549
  • 16
  • 165
  • 178
  • Thanks dude, but this doesn't seem to work plz check the [LogCat Here](http://dl.dropbox.com/u/40690073/logcat.txt). Also check my Updated Code which I am Currently Using. – VenomVendor Sep 12 '12 at 09:19
  • ahaan the famous **java.net.UnknownHostException** :) Simply close and run again your emulator (perhaps eclipse too) then clean your project and build again – waqaslam Sep 12 '12 at 10:12
  • I understand that, but i want to bypass what ever the exception at the end of 5th sec and `retrun xml==null`. To explain in more detail, Think you are waiting for someone for 5sec, if he doesnt come you have to bypass, no matter what ever the exception is, don't accept any exception. After 5th sec return the xml. – VenomVendor Sep 13 '12 at 08:59
  • 1
    What you are doing right now will do pretty much what you want. However, if you want then simply add a single catch block (`catch(Exception ex){ /* do nothing */ }`) which will do nothing but will silently eat all types of exceptions and return null – waqaslam Sep 13 '12 at 09:08
  • But, my requirement is not that, I need something to skip my execution of HTTP request after 5secs & return the xml as null. If the HTTP value is fetched within 5 secs the xml is already returned with some value, so after that 5sec timer has to be exited. If you are finding difficult in understand my exact requirement please let me know, I think you can help me out. – VenomVendor Sep 13 '12 at 14:01
  • I think that's what the code does. When it hits to the `httpClient.execute(httpPost);`, it will wait for at least 5 seconds to get the response, otherwise it will simply kill the operation/socket and will move on to exception. If you are talking about implementing the code in a big picture (like UI/database) then it depends if you are doing some other operations too which may consume extra time besides this webcall. Moreover, if you may create a simple project with an activity and post it online and send me the link, then perhaps I can look into it and see whats bothering you :) – waqaslam Sep 13 '12 at 14:16
2

How about this:

Thread thread = new Thread() {
  @Override
  public void run() {
    // do the downloading thing..
  }
};
thread.start();
thread.join(5000);
yegor256
  • 102,010
  • 123
  • 446
  • 597
  • The question says "don't want to do this in Async Task". This is like AsyncTask. AsyncTask is a wrapper over a thread. – gammay Sep 10 '12 at 08:53
  • `join()` makes it synchronous – yegor256 Sep 10 '12 at 09:00
  • This also suffers from the fact that you might not be able to cancel the running code. Ideally, you'd just do a thread.interrupt if the join comes back and the thread is still alive. However, thread.interrupt() is a cooperate effort and the underlying Runnable code needs to be coded to deal with it. Some operations like Thread.sleep do this for you and throw an InterruptedException. Others like java.io streams don't and you explicitly have to keep checking Thread.currentThread().isInterrupted. It's much safer to set the socket timeout as others have suggested. – Matt Sep 10 '12 at 17:35
1

This is just an idea, but you could set up a delayed runnable and check after 5 seconds if the file has any size.

0
 HttpParams params = new BasicHttpParams();

    // Turn off stale checking.  Our connections break all the time anyway,
    // and it's not worth it to pay the penalty of checking every time.
    HttpConnectionParams.setStaleCheckingEnabled(params, false);

    HttpConnectionParams.setConnectionTimeout(params, SOCKET_OPERATION_TIMEOUT);
    HttpConnectionParams.setSoTimeout(params, SOCKET_OPERATION_TIMEOUT);
    HttpConnectionParams.setSocketBufferSize(params, 8192);

    // Don't handle redirects -- return them to the caller.  Our code
    // often wants to re-POST after a redirect, which we must do ourselves.
    HttpClientParams.setRedirecting(params, false);

    // Use a session cache for SSL sockets
    SSLSessionCache sessionCache = context == null ? null : new SSLSessionCache(context);

    // Set the specified user agent and register standard protocols.
    HttpProtocolParams.setUserAgent(params, userAgent);
    SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme("http",
            PlainSocketFactory.getSocketFactory(), 80));
    schemeRegistry.register(new Scheme("https",
            SSLCertificateSocketFactory.getHttpSocketFactory(
            SOCKET_OPERATION_TIMEOUT, sessionCache), 443));

    ClientConnectionManager manager =
            new ThreadSafeClientConnManager(params, schemeRegistry);

    // We use a factory method to modify superclass initialization
    // parameters without the funny call-a-static-method dance.
    return new AndroidHttpClient(manager, params);

Change SOCKET_OPERATION_TIMEOUT value according to your need.

Shachillies
  • 1,616
  • 14
  • 12
0

This code may help you

this code from last answer is Ok

final int TIMEOUT_MILLISEC = 5000;  // 5 seconds

HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT_MILLISEC);
HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT_MILLISEC);

HttpClient httpClient = new DefaultHttpClient(httpParams);

Only when you are trying to execute your request you have to care about 3 more exceptions SocketTimeoutException, UnknownHostException, ConnectTimeoutException

so catch this 3 exceptions also.

Vishal Pawar
  • 4,324
  • 4
  • 28
  • 54