BitmapFactory.decodeStream(InputStream is) returns null for non null InputStream on Android

10,332

Solution 1

I've run into this. Try using BufferedHttpEntity with your inputstream. I found this prevented 99.9% of the issues with getting silent nulls from decodeStream.

Maybe not signficant, but I reliably use org.apache.http.client.HttpClient rather than HttpURLConnection as in:

public static Bitmap decodeFromUrl(HttpClient client, URL url, Config bitmapCOnfig)
{
    HttpResponse response=null;
    Bitmap b=null;
    InputStream instream=null;

    BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
    decodeOptions.inPreferredConfig = bitmapCOnfig;
    try
    {
    HttpGet request = new HttpGet(url.toURI());
        response = client.execute(request);
        if (response.getStatusLine().getStatusCode() != 200)
        {
            MyLogger.w("Bad response on " + url.toString());
            MyLogger.w ("http response: " + response.getStatusLine().toString());
            return null;
        }
        BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(response.getEntity());
        instream = bufHttpEntity.getContent();

        return BitmapFactory.decodeStream(instream, null, decodeOptions);
    }
    catch (Exception ex)
    {
        MyLogger.e("error decoding bitmap from:" + url, ex);
        if (response != null)
        {
            MyLogger.e("http status: " + response.getStatusLine().getStatusCode());
        }
        return null;
    }
    finally
    {
        if (instream != null)
        {
            try {
                instream.close();
            } catch (IOException e) {
                MyLogger.e("error closing stream", e);
            }
        }
    }
}

Solution 2

Google brought me here. For everyone having the same problem:

Problem: http://code.google.com/p/android/issues/detail?id=6066

Solution ("FlushedInputStream"): http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html

Share:
10,332
Ripityom
Author by

Ripityom

Updated on June 04, 2022

Comments

  • Ripityom
    Ripityom about 2 years

    I'm developing an Android application, and it's view is containing multiple Gallerys. The content of the Gallerys (the Bitmaps) are red from the Internet.

    For the first gallery, everything works fine, but when trying to download the first image of the second Gallery, the BitmapFactory.decodeStream(InputStream) returns null, while the stream is NOT null.

    public void loadBitmap() throws IOException {
    
            for (int i = 0; i < images.size(); ++i) {
                URL ulrn = new URL(images.get(i).getThumbUrl());
                HttpURLConnection con = (HttpURLConnection) ulrn.openConnection();
                InputStream is = con.getInputStream();
                images.get(i).setImage(BitmapFactory.decodeStream(is));
                Log.i("MY_TAG", "Height: " + images.get(i).getImage().getHeight());
            }
    }
    

    The getThumbUrl() returns the URL of the image (eg. http://mydomain.com/image.jpg) and it throws a NullPointerException at the line Log.i("MY_TAG", "Height: ... ) (images is an ArrayList containing objects of my class, that holds the URL and the Bitmap too).

    Thanks for any advice!

    • Ripityom
      Ripityom about 13 years
      Not too big, i would say about 100x50. But if that was the problem I would get some OutOfMemoryException, wouldn't I? (im loading about 30-35 images to the Galleries, and about 10 a little bigger image at a time)
  • Ripityom
    Ripityom about 13 years
    Hi!Yes i logged out the url, copied to browser, and the browser opens the image.
  • Aleadam
    Aleadam about 13 years
    check that the value of con.getResponseCode(); is 200 (HTTP_OK)
  • Ripityom
    Ripityom about 13 years
    Yes it solved it, thank you very much, and thanks for the code too!
  • mmeyer
    mmeyer about 13 years
    Hmmm...I'm using the above with 2 gallerys in one view with success. What knd of error are you getting?
  • Ripityom
    Ripityom about 13 years
    I dont get any error, the returned Bitmap is simply null. Its strange since i included the error messages to the code.
  • Ripityom
    Ripityom about 13 years
    Now the app loaded all the images, but I got the following error: '05-10 10:31:19.553: ERROR/dalvikvm-heap(26407): 582400-byte external allocation too large for this process.' I assume its about a memory issue, but then why dont I get Exception?
  • Ripityom
    Ripityom about 13 years
    Yes, its 200, so the stream seems to be fine.
  • Ripityom
    Ripityom about 13 years
    strange.. the line 'return BitmapFactory.decodeStream(instream, null, decodeOptions);' throws now a OutOfMemoryException, but it is unhandled (the app crashes), despite of the catch block
  • mmeyer
    mmeyer about 13 years
    Ok, good. That's a different issue. Either your 1 bitmap is way to large or the views in the gallery are not getting recycled and all of the other bitmaps are still in memory and the one that gave error is the one that broke the camel's back. Have a look at this post: stackoverflow.com/questions/3181728/…
  • Ripityom
    Ripityom about 13 years
    Oh I see, so I ran out of memory. But why did the catch bloch not catch the Exception?
  • mmeyer
    mmeyer about 13 years
    Out of Memory is a Runtime Exception, it's not catchable. By the time it happens it's too late. Android will kill your process and wont run anything else from you once it's thrown. There is a low memory event you can catch and get a chance to clean some things but that doesnt work with Bitmaps prior to Honeycomb since BMs are allocated on the native heap. Bottomline for you is that you probably need to use bitmapOptions to scale down, and make sure youre recycling views in your adapter for gallery.
  • Ripityom
    Ripityom about 13 years
    Thanks that you explained that.
  • user123321
    user123321 over 12 years
    OMG, you need WAAAAY more upvotes. I've been reading everywhere about this issue and THIS is the only one that actually resolves it. THANKS!!!
  • user123321
    user123321 over 12 years
    The FlushedInputStream didn't work for me. @mmeyer solution did though.