Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 979
András Szepesházi Avatar asked Oct 06 '22 23:10

András Szepesházi


1 Answers

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.

like image 160
yorkw Avatar answered Oct 13 '22 03:10

yorkw