Question

I am trying to download an image from a URL to display as an ImageView. The download is done in the background using AsyncTask. However, the call to the decodeStream of the BitmapFactory always returns a null object. I verified that the Url provided for the connection is right, but it seems that BitmapFactory cannot read the image from the InputStream returned by the HTTP connection. Here is the code below:

@Override
    protected Bitmap doInBackground(String... uri) {
        Bitmap bm = null;
        HttpClient client = new DefaultHttpClient();
        HttpGet request = new HttpGet(Uri.encode(uri[0]));
        try {
            HttpResponse response = client.execute(request);
            HttpEntity entity = response.getEntity();
            String contentType = entity.getContentType().getValue();
            DisplayMetrics metrics = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(metrics);
            int halfScreen = metrics.widthPixels / 2;
            int photoWidth = halfScreen > 200 ? 200 : halfScreen;
            if (contentType.contains("image/jpeg") || contentType.contains("image/png") || contentType.contains("image/gif")) {
                bm = BitmapFactory.decodeStream(new BufferedInputStream(entity.getContent()));
                if (bm.getWidth() > photoWidth)
                bm = Bitmap.createScaledBitmap(bm, photoWidth, Math.round((photoWidth*bm.getHeight())/bm.getWidth()), true);
            }
        } catch (Exception e) {
            bm = null;
        }
        return bm;
    }

What is weird is that the exact same code runs fine on a Nexus S, but does not work on a Samsung running Android 2.1-update1.

Was it helpful?

Solution

The problem was in the BitmapFactory.decodeStream() method. It seems that this method has a bug that makes it fail on slow connections. I applied the recommendations found at http://code.google.com/p/android/issues/detail?id=6066.

I created the FlushedInputStream class below:

public class FlushedInputStream extends FilterInputStream {

protected FlushedInputStream(InputStream in) {
    super(in);
}

@Override
public long skip(long n) throws IOException {
    long totalBytesSkipped = 0L;
    while (totalBytesSkipped < n) {
        long bytesSkipped = in.skip(n - totalBytesSkipped);
        if (bytesSkipped == 0L) {
              int onebyte = read();
              if (onebyte < 0) {
                  break;  // we reached EOF
              } else {
                  bytesSkipped = 1; // we read one byte
              }
       }
        totalBytesSkipped += bytesSkipped;
    }
    return totalBytesSkipped;
}
}

Then, in my code I used:

bm = BitmapFactory.decodeStream(new FlushedInputStream(entity.getContent()));

instead of:

bm = BitmapFactory.decodeStream(new BufferedInputStream(entity.getContent()));

OTHER TIPS

Try to wrap your HttpEntity into BufferedHttpEntity, like it's done in this question: BitmapFactory.decodeStream returns null without exception . Seems that problem is quite similar.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top