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

3

5

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!

Thordia answered 9/5, 2011 at 17:41 Comment(1)
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)Thordia
S
7

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);
            }
        }
    }
}
Stronski answered 9/5, 2011 at 19:26 Comment(9)
Hmmm...I'm using the above with 2 gallerys in one view with success. What knd of error are you getting?Stronski
I dont get any error, the returned Bitmap is simply null. Its strange since i included the error messages to the code.Thordia
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?Thordia
strange.. the line 'return BitmapFactory.decodeStream(instream, null, decodeOptions);' throws now a OutOfMemoryException, but it is unhandled (the app crashes), despite of the catch blockThordia
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: #3182228Stronski
Oh I see, so I ran out of memory. But why did the catch bloch not catch the Exception?Thordia
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.Stronski
Thanks that you explained that.Thordia
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!!!Topmost
N
1

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

Nekton answered 6/10, 2011 at 8:6 Comment(1)
The FlushedInputStream didn't work for me. @Stronski solution did though.Topmost
S
0
public static Bitmap decodeStream (InputStream is)

Returns

The decoded bitmap, or null if the image data could not be decoded.

Did you check that you're not getting some 404 error or similar instead of the image?

Silicone answered 9/5, 2011 at 18:58 Comment(3)
Hi!Yes i logged out the url, copied to browser, and the browser opens the image.Thordia
check that the value of con.getResponseCode(); is 200 (HTTP_OK)Silicone
Yes, its 200, so the stream seems to be fine.Thordia

© 2022 - 2024 — McMap. All rights reserved.