0

I'm getting a lot of these exceptions from users: java.lang.OutOfMemoryError: bitmap size exceeds VM budget - but i'm unable to reproduce the problem on the emulator.

I'm using this as my ImageDownloader http://code.google.com/p/android-imagedownloader/source/browse/trunk/src/com/example/android/imagedownloader/ImageDownloader.java#185 and the problem occurs on line 185 when trying to decode the image.

There is a lot of other questions here on stackoverflow, regarding this error, but none that fits my specific case. The solution in this question could work: https://stackoverflow.com/a/823966 but i can't seem to get it to work.

Here is what i changed in my ImageDownloader:

final HttpEntity entity = response.getEntity();
if (entity != null) {
    InputStream inputStream = null;
    try {
        inputStream = entity.getContent();
        // return BitmapFactory.decodeStream(inputStream);
        // Bug on slow connections, fixed in future release.

        FlushedInputStream flushedStream = new FlushedInputStream(inputStream);

        // Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(flushedStream, null, o);
        Log.d(LOG_TAG, "decodeStream - outWidth=" + o.outWidth + " outHeight=" + o.outHeight);

        // The new size we want to scale to
        final int REQUIRED_SIZE = 70;

        // Find the correct scale value. It should be the power of
        // 2.
        int scale = 1;
        while (o.outWidth / scale / 2 >= REQUIRED_SIZE && o.outHeight / scale / 2 >= REQUIRED_SIZE)
            scale *= 2;

        // Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        return BitmapFactory.decodeStream(flushedStream, null, o2);
    } finally {
        if (inputStream != null) {
            inputStream.close();
        }
        entity.consumeContent();
    }
}

It fails when calling decodeStream() the second time. Error is SkImageDecoder::Factory returned null. I figured maybe the inputStream is closed or not available on the second call, so i then tried to use BufferedHttpEntity in the first line above, but with no luck.

Can someone guide me towards the right direction? Thanks.

Community
  • 1
  • 1
Lasse P
  • 315
  • 4
  • 9

3 Answers3

0

Check first that how many images downloading at one time. how much memory it consumes there is a maximum heap memory of 16MB in most android phones, when you dont need any resources, simply release(null) at regular time, it wont let the heap memory to grow and no memory leaks issue will occur. This is one of the common issue i high memory application such as working with multimedia. So all you need to do is that check the unused resource and also wont come to use in future and make them null (e.g. bitmaps), so it will free the memory.

mayank_droid
  • 1,015
  • 10
  • 19
  • As you can see in the original ImageDownloader source, the bitmaps are wrapped in a SoftReference cache, so that should be garbage collected if the device is low on memory? The problem must be that i'm downloading images that are too large in the first place, hence i need to downsample if thats the case – Lasse P Feb 14 '12 at 08:58
  • Are you storing them to SD card or keeping in application only? – mayank_droid Feb 14 '12 at 10:02
0

Using BitmapFactory.Options should do the thing.Still if you are getting outofmemory, try clearing memory by removing variables .

And where are you getting "SkImageDecoder::Factory returned null" in // Decode image size or // Decode with inSampleSize

voidRy
  • 674
  • 9
  • 20
0

Download the image first and put into a byte array. decodeStream returns null after a certain period of time when using input stream.

Shaiful
  • 5,643
  • 5
  • 38
  • 41
  • I've tried your method and it seems to be working, but i'm a little concerned about downloading the entire image and putting it in a byte array - wouldn't it just cause the same problem, filling up the memory if lots of big images are being downloaded at the same time? – Lasse P Feb 14 '12 at 09:32
  • Either way you have to download the full image. You need the full image data for decoding. But for your method the method will fail when timeout occurs. It'll wait a certain period of time and return null value while full imaga data not loaded in this time period. Better way is try to scale the image in server. – Shaiful Feb 14 '12 at 09:47
  • Ok that makes sense. But now i'm able to downsample the image and save that in the cache, instead of the full image (depending on the size), which is hopefully better than before and saves a bit of memory. I agree it would be better to scale server-side. – Lasse P Feb 14 '12 at 09:57
  • I've modified `DroidFu` for image caching(Just add the downsampling support). You can try too. DroidFu support two level of caching file & memory. uses soft references. P.S. - If the ans help you then put a up vote and accept the answer please. – Shaiful Feb 14 '12 at 10:23