Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OutOfMemory exception when loading bitmap from external storage

In my application I load a couple of images from JPEG and PNG files. When I place all those files into assets directory and load it in this way, everything is ok:

InputStream stream = getAssets().open(path);
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, null);
stream.close();
return new BitmapDrawable(bitmap);

But when I try to load the exact same images from sd card, I get an OutOfMemory exception!

InputStream stream = new FileInputStream("/mnt/sdcard/mydata/" + path);
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, null);
stream.close();
return new BitmapDrawable(bitmap);

This is what I get in the log:

11-05 00:53:31.003: ERROR/dalvikvm-heap(13183): 827200-byte external allocation too large for this process.
11-05 00:53:31.003: ERROR/GraphicsJNI(13183): VM won't let us allocate 827200 bytes
...
11-05 00:53:31.053: ERROR/AndroidRuntime(13183): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
11-05 00:53:31.053: ERROR/AndroidRuntime(13183):     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
...

Why can this happen?

UPDATE: Tried both of these on real device - it seems that I can't load more than 12MB of bitmaps into whatever is called "external memory" (this is not an sd card).

like image 593
Fixpoint Avatar asked Nov 05 '10 00:11

Fixpoint


3 Answers

I tried all the approaches mentioned here & at other resources but I came to the inference that setting ImageView's reference to null will solve the issue:

  public Bitmap getimage(String path ,ImageView iv)
   {
    //iv is passed to set it null to remove it from external memory
    iv=null;
    InputStream stream = new FileInputStream("/mnt/sdcard/mydata/" + path);
    Bitmap bitmap = BitmapFactory.decodeStream(stream, null, null);
    stream.close();
    stream=null;
    return bitmap;
    }

& you are done!

Note:Though it may solve above problem but I would suggest you to check Tom van Zummeren 's optimized image loading.

And also check SoftReference: All SoftReferences pointing to softly reachable objects are guaranteed to be cleared before the VM will throw an OutOfMemoryError.

like image 106
100rabh Avatar answered Nov 12 '22 14:11

100rabh


  • When doing a lot with bitmaps, don't debug the app - just run it. The debugger will leave memory leaks.
  • Bitmaps are very expensive. If possible, scale them down on load by creating BitmapFactory.Options and setting inSampleSize to >1.

EDIT: Also, be sure to check your app for memory leaks. Leaking a Bitmap (having static Bitmaps is an excellent way to do that) will quickly exhaust your available memory.

like image 5
EboMike Avatar answered Nov 12 '22 16:11

EboMike


Probably nothing wrong with your API usage, I guess all we can do is infer that using the AssetManager involves less behind-the-scenes heap allocation than opening a random file from the SD card.

800KB is a serious allocation in anybody's book... this will doubtless be for the decompressed image pixels. Given that you know the size of the image, what depth is it? If it's 32bpp then try overriding that using inPreferredConfig.

like image 4
Reuben Scratton Avatar answered Nov 12 '22 14:11

Reuben Scratton