I want to return false if the URL takes more then 5 seconds to connect - how is this possible using Java? Here is the code I am using to check if the URL is valid
HttpURLConnection.setFollowRedirects(false);HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();con.setRequestMethod("HEAD");return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
Best Answer
HttpURLConnection
has a setConnectTimeout method.
Just set the timeout to 5000 milliseconds, and then catch java.net.SocketTimeoutException
Your code should look something like this:
try {HttpURLConnection.setFollowRedirects(false);HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();con.setRequestMethod("HEAD");con.setConnectTimeout(5000); //set timeout to 5 secondsreturn (con.getResponseCode() == HttpURLConnection.HTTP_OK);} catch (java.net.SocketTimeoutException e) {return false;} catch (java.io.IOException e) {return false;}
You can set timeout like this,
con.setConnectTimeout(connectTimeout);con.setReadTimeout(socketTimeout);
If the HTTP Connection doesn't timeout, You can implement the timeout checker in the background thread itself (AsyncTask, Service, etc), the following class is an example for Customize AsyncTask which timeout after certain period
public abstract class AsyncTaskWithTimer<Params, Progress, Result> extendsAsyncTask<Params, Progress, Result> {private static final int HTTP_REQUEST_TIMEOUT = 30000;@Overrideprotected Result doInBackground(Params... params) {createTimeoutListener();return doInBackgroundImpl(params);}private void createTimeoutListener() {Thread timeout = new Thread() {public void run() {Looper.prepare();final Handler handler = new Handler();handler.postDelayed(new Runnable() {@Overridepublic void run() {if (AsyncTaskWithTimer.this != null&& AsyncTaskWithTimer.this.getStatus() != Status.FINISHED)AsyncTaskWithTimer.this.cancel(true);handler.removeCallbacks(this);Looper.myLooper().quit();}}, HTTP_REQUEST_TIMEOUT);Looper.loop();}};timeout.start();}abstract protected Result doInBackgroundImpl(Params... params);}
A Sample for this
public class AsyncTaskWithTimerSample extends AsyncTaskWithTimer<Void, Void, Void> {@Overrideprotected void onCancelled(Void void) {Log.d(TAG, "Async Task onCancelled With Result");super.onCancelled(result);}@Overrideprotected void onCancelled() {Log.d(TAG, "Async Task onCancelled");super.onCancelled();}@Overrideprotected Void doInBackgroundImpl(Void... params) {// Do background workreturn null;};}
The System property sun.net.client.defaultConnectTimeout can be set. The value is in milliseconds. This will set a default timeout for each request-
Either by setting in JVM options-
-Dsun.net.client.defaultConnectTimeout=5000
OR in java code-
System.setProperty("sun.net.client.defaultConnectTimeout", "5000");
I could get solution for such a similar problem with addition of a simple line
HttpURLConnection hConn = (HttpURLConnection) url.openConnection();hConn.setRequestMethod("HEAD");
My requirement was to know the response code and for that just getting the meta-information was sufficient, instead of getting the complete response body.
Default request method is GET and that was taking lot of time to return, finally throwing me SocketTimeoutException. The response was pretty fast when I set the Request Method to HEAD.