androidhttpurlconnectionandroid-2.2-froyodisconnect

How to disconnect an HttpUrlConnection on HTC (Froyo and below) phones?


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


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.