42

I'm writing an application that connects to a webservice and I don't want it to wait too long if it can't get a connection. I therefore set the connectionTimeout of the httpparams. But it doesn't seem to have any effect whatsoever.

To test I turn of my WLAN temporarily. The application tries to connect for quite some time (way more than the 3 seconds I want) and then throws an UnknownHostException.

Here is my code:

try{
    HttpClient httpclient = new DefaultHttpClient();
    HttpParams params = httpclient.getParams();
    HttpConnectionParams.setConnectionTimeout(params, 3000);
    HttpConnectionParams.setSoTimeout(params, 3000);

    httppost = new HttpPost(URL);
    StringEntity se = new StringEntity(envelope,HTTP.UTF_8);
    httppost.setEntity(se);
    //Code stops here until UnknownHostException is thrown.
    BasicHttpResponse httpResponse = (BasicHttpResponse) httpclient.execute(httppost);

    HttpEntity entity = httpResponse.getEntity();
    return entity;

}catch (Exception e){
    e.printStackTrace();
}

Anyone have any ideas what I missed?

Cristian
  • 198,401
  • 62
  • 356
  • 264
ascu
  • 1,029
  • 1
  • 19
  • 33

4 Answers4

9

With the marked solution I am still getting a UnknownHostException after 30+ seconds. In this case the device is connected to a wifi router but there is no internet access.

The approach taken was to kick off an AsyncTask that will just attempt to resolve the hostname. The blocking call checks every 250 ms to see if it succeeded, and after 4 seconds it will cancel the task and return.

This is what I did to solve it:

private boolean dnsOkay = false;
private static final int DNS_SLEEP_WAIT = 250;
private synchronized boolean resolveDns(){

    RemoteDnsCheck check = new RemoteDnsCheck();
    check.execute();
    try {
        int timeSlept = 0;
        while(!dnsOkay && timeSlept<4000){
            //Log.d("RemoteDnsCheck", "sleeping");
            Thread.sleep(DNS_SLEEP_WAIT);
            timeSlept+=DNS_SLEEP_WAIT;
            //Log.d("RemoteDnsCheck", "slept");
        }
    } catch (InterruptedException e) {

    }

    if(!dnsOkay){
        Log.d("resolveDns", "cancelling");
        check.cancel(true);
        Log.d("resolveDns", "cancelled");
    }
    return dnsOkay;
}

private class RemoteDnsCheck extends AsyncTask<Void, Void, Void>{

    @Override
    protected Void doInBackground(Void... params) {
        try {
            Log.d("RemoteDnsCheck", "starting");
            dnsOkay = false;
            InetAddress addr = InetAddress.getByName(baseServiceURL);
            if(addr!=null){
                Log.d("RemoteDnsCheck", "got addr");
                dnsOkay = true;
            }
        } catch (UnknownHostException e) {
            Log.d("RemoteDnsCheck", "UnknownHostException");
        }
        return null;
    }

}

Then, any time I want to do a web call, this is called at the beginning of the function:

    if(!resolveDns()){
        return null;
    }
hooby3dfx
  • 936
  • 1
  • 8
  • 18
3

See: https://stackoverflow.com/a/20031077/2609238

The problem might be in the Apache HTTP Client. See HTTPCLIENT-1098. Fixed in 4.1.2.

The timeout exception tries to reverse DNS the IP, for logging purposes. This takes an additional time until the exception is actually fired.

Community
  • 1
  • 1
noam
  • 101
  • 1
  • 5
1

This method works for me :

AndroidHttpTransport androidHttpTransport = new AndroidHttpTransport( endpoint, 3000) ;
Ali
  • 9,800
  • 19
  • 72
  • 152
Jr.
  • 126
  • 1
  • 10
0
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT)
duggu
  • 37,851
  • 12
  • 116
  • 113
  • This is not an answer to the question, because that method call is already a part of the code below; *another tip*: use code formatting for better presentation ... – Trinimon Mar 22 '13 at 08:36