Android Bitmap.createScaledBitmap throws java.lang.OutOfMemoryError mostly on Jelly Bean 4.1

15,505

Solution 1

http://www.youtube.com/watch?v=_CruQY55HOk. After andorid 3.0 bitmaps pixel data are stored on the heap. It seems you are exceeding heap memory size. Just because your app requires large heap do not use large heap. More the size of heap, more regular garbage collections. The video has a good explanation on the topic.

Also recycle bitmaps when not in use. Garbage collections on heap is done my mark and sweep , so when you recycle bitmaps it free's memory. So your heap size will not grow and run out of memory.

 bitmap.recycle();

http://developer.android.com/training/displaying-bitmaps/load-bitmap.html. Documentation on loading bitmaps efficiently. Have a look at loading scaled down version in memory.

Apart form this you can use Universal Image Loader. https://github.com/nostra13/Android-Universal-Image-Loader.

https://github.com/thest1/LazyList. Lazy Loading of Images.

Both use caching.

Solution 2

It's important to note that following code can cause Exception:

Bitmap bitmap = Bitmap.createScaledBitmap(oldBitmap, newWidth, newHeight, true); 
oldBitmap.recycle();

Proper is:

Bitmap bitmap = Bitmap.createScaledBitmap(oldBitmap, newWidth, newHeight, true); 
if (oldBitmap!= bitmap){
     oldBitmap.recycle();
}

because documentation says:

If the specified width and height are the same as the current width and height of the source btimap, the source bitmap is returned and now new bitmap is created.

Solution 3

You are trying to access more memory then you have. Try to use

 BitmapFactory.Options opts=new BitmapFactory.Options();
        opts.inDither=false;                    
        opts.inSampleSize = 8;                   
        opts.inPurgeable=true;                 
        opts.inInputShareable=true;             
        opts.inTempStorage=new byte[16 * 1024]; 

Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.h1)
        , 65,65, true),

Also look at below links to increase memory

http://developer.android.com/reference/android/R.styleable.html#AndroidManifestApplication_largeHeap

Detect application heap size in Android

EDIT 1

try to use nostras image downloader, you can use it to show image in local storage. And it manages memory very well ...

https://github.com/nostra13/Android-Universal-Image-Loader

Share:
15,505
Rohit
Author by

Rohit

Updated on June 05, 2022

Comments

  • Rohit
    Rohit about 2 years

    My app main purpose is to display images in following fashion as shown in image

    enter image description here

    private void setSelectedImage(int selectedImagePosition) 
    {
    
        BitmapDrawable bd = (BitmapDrawable) drawables.get(selectedImagePosition);
        Bitmap b = Bitmap.createScaledBitmap(bd.getBitmap(), (int) (bd.getIntrinsicHeight() * 0.9), (int) (bd.getIntrinsicWidth() * 0.7), false);
        selectedImageView.setImageBitmap(b);
        selectedImageView.setScaleType(ScaleType.FIT_XY);
    
    }
    

    Detailed code can be find here

    exception is thrown at following line

    Bitmap b = Bitmap.createScaledBitmap(bd.getBitmap(), (int) (bd.getIntrinsicHeight() * 0.9), (int) (bd.getIntrinsicWidth() * 0.7), false);
    

    Above function is called from onItemSelected. **The app still works well on 2.2 and 2.3, but throws exception immediately on 4.1 Above code works fine, but throws following exception. I didnot see any crashes in 2.2 and 2.3, but it immedidately crashes in 4.1 Is there any major difference of memory management in Jelly beans? **:

    java.lang.OutOfMemoryError
    AndroidRuntime(2616):   at android.graphics.Bitmap.nativeCreate(Native Method)
    AndroidRuntime(2616):   at android.graphics.Bitmap.createBitmap(Bitmap.java:640)
    AndroidRuntime(2616):   at android.graphics.Bitmap.createBitmap(Bitmap.java:586) 
    AndroidRuntime(2616):   at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:466)
    AndroidRuntime(2616):   at com.rdx.gallery.GalleryDemoActivity.setSelectedImage(GalleryDemoActivity.java:183)
    
  • Rohit
    Rohit over 11 years
    using bitmap.recycle() of not in use acutally helped.
  • Rohit
    Rohit over 11 years
    Used bitmap.recycle for unused bitmaps. No more crashes on that module now. Thanks
  • Yoann Hercouet
    Yoann Hercouet about 9 years
    This code can still trigger exceptions if the bitmap was already recycled for any reason, you need to add this to the check: && !oldBitmap.isRecycled()
  • Malachiasz
    Malachiasz about 9 years
    In which implementation of Bitmap class it is necessary? Because not in 5.1.0_r1, as the method checks it istelf: "if (!mRecycled && mFinalizer.mNativeBitmap != 0) " grepcode.com/file/repository.grepcode.com/java/ext/…