Question

I need to disconnect a long polling http request from the client side in some cases. The relevant part of the HttpUrlConnection I make to the server is as follows (all the code below is within a Thread's run() method):

try {
    URL url = new URL(requestURL);

    connection = (HttpURLConnection) url.openConnection();
    connection.setRequestProperty("Accept-Charset", "UTF-8");
    connection.setConnectTimeout(5 * 1000);
    connection.setReadTimeout(60 * 1000);
    connection.setRequestMethod("GET");

    // read the output from the server
    reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
    StringBuilder stringBuilder = new StringBuilder();

    String line = null;
    while ((line = reader.readLine()) != null) {
        stringBuilder.append(line + "\n");
    }
    Log.d(TAG, stringBuilder);
} catch (IOException ioe) {
    Log.e(TAG, ioe);
} finally {
    if (reader != null) {
        try {
            reader.close();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}

This is how I first initiate, then (after a second delay) try to cancel the request:

pollThread = new PollThread();
pollThread.start();
Log.d(TAG, "pollThread started");

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        pollThread.cancelRequest();
        Log.d(TAG, "pollThread presumably cancelled");
    }
}, 1000);

And this is what the cancelRequest() method looks like:

public void cancelRequest() {
    if (connection != null) {
        connection.disconnect();
    }
}

So essentially,

  1. I initiate a HttpUrlConnection with a get request, with 1 minute read timeout
  2. Then after one second, I try to cancel the earlier request
  3. The expected outcome is that the connection should throw an IOException when I call connection.disconnect()

And this is exactly what happens on various emulators (2.2 - 4.0.3), a Motorola Atrix (2.3.7) and a Samsung Note (4.0.1). But on some HTC devices running 2.2, the request will stay alive and it will recieve the response, despite the fact that I explicitly terminated the connection. I verified this with an HTC Desire and an HTC Wildfire.

What's going on here? How can I cancel such a request safely on all devices running 2.2+?

For your convenience, the whole code is available here, should you like to do a test drive yourself: https://gist.github.com/3306225

Was it helpful?

Solution

What's going on here?

This is a known bug in earlier android release (Froyo 2.2) which, in sort, sockets can not be closed asynchronously by other threads, and has been fixed in Gingerbread 2.3:

Issue 11705: impossible to close HTTP connection using HttpURLConnection

How can I cancel such a request safely on all devices running 2.2+?

Comments from project member in that link:

The best approximation of this that will work in current releases is to set read and connect timeouts on the HTTP connection.

Hope that helps.

OTHER TIPS

Actually, I would recommend you to use Apache HttpClient lib, instead of the default supplied with android.

You can download it from: http://code.google.com/p/httpclientandroidlib/

If you want to go "all the way", you can also use AndroidHttpClient "that is configured with reasonable default settings and registered schemes for Android" and could also support cookies. You can download it from here (I can't remember when I found the original one...)

This is how you use a "Get" call, I guess you can figure out the rest:

    InputStream isResponse = null;

    HttpGet httpget = new HttpGet(strUrl);
    HttpResponse response = getHttpClient().execute(httpget);

    HttpEntity entity = response.getEntity();
    isResponse = entity.getContent();
    responseBody = convertStreamToString(isResponse);

and

    /**
 * @return the mClient
 */
protected AndroidHttpClient getHttpClient() {
    if (mClient == null)
        mClient = AndroidHttpClient.newInstance(mCookieStore);
    return mClient;
}

To close the connction:

getHttpClient().close();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top