Strange OutOfMemory issue while loading an image to a Bitmap object

640,362

Solution 1

The Android Training class, "Displaying Bitmaps Efficiently", offers some great information for understanding and dealing with the exception `java.lang.OutOfMemoryError: bitmap size exceeds VM budget when loading Bitmaps.


Read Bitmap Dimensions and Type

The BitmapFactory class provides several decoding methods (decodeByteArray(), decodeFile(), decodeResource(), etc.) for creating a Bitmap from various sources. Choose the most appropriate decode method based on your image data source. These methods attempt to allocate memory for the constructed bitmap and therefore can easily result in an OutOfMemory exception. Each type of decode method has additional signatures that let you specify decoding options via the BitmapFactory.Options class. Setting the inJustDecodeBounds property to true while decoding avoids memory allocation, returning null for the bitmap object but setting outWidth, outHeight and outMimeType. This technique allows you to read the dimensions and type of the image data prior to the construction (and memory allocation) of the bitmap.

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;

To avoid java.lang.OutOfMemory exceptions, check the dimensions of a bitmap before decoding it unless you absolutely trust the source to provide you with predictably sized image data that comfortably fits within the available memory.


Load a scaled-down version into Memory

Now that the image dimensions are known, they can be used to decide if the full image should be loaded into memory or if a subsampled version should be loaded instead. Here are some factors to consider:

  • Estimated memory usage of loading the full image in memory.
  • The amount of memory you are willing to commit to loading this image given any other memory requirements of your application.
  • Dimensions of the target ImageView or UI component that the image is to be loaded into.
  • Screen size and density of the current device.

For example, it’s not worth loading a 1024x768 pixel image into memory if it will eventually be displayed in a 128x96 pixel thumbnail in an ImageView.

To tell the decoder to subsample the image, loading a smaller version into memory, set inSampleSize to true in your BitmapFactory.Options object. For example, an image with resolution 2048x1536 that is decoded with an inSampleSize of 4 produces a bitmap of approximately 512x384. Loading this into memory uses 0.75MB rather than 12MB for the full image (assuming a bitmap configuration of ARGB_8888). Here’s a method to calculate a sample size value that is a power of two based on a target width and height:

public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

Note: A power of two value is calculated because the decoder uses a final value by rounding down to the nearest power of two, as per the inSampleSize documentation.

To use this method, first decode with inJustDecodeBounds set to true, pass the options through and then decode again using the new inSampleSizevalue andinJustDecodeBoundsset tofalse`:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
    int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}

This method makes it easy to load a bitmap of arbitrarily large size into an ImageView that displays a 100x100 pixel thumbnail, as shown in the following example code:

mImageView.setImageBitmap(
    decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

You can follow a similar process to decode bitmaps from other sources, by substituting the appropriate BitmapFactory.decode* method as needed.

Solution 2

To fix the OutOfMemory error, you should do something like this:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap preview_bitmap = BitmapFactory.decodeStream(is, null, options);

This inSampleSize option reduces memory consumption.

Here's a complete method. First it reads image size without decoding the content itself. Then it finds the best inSampleSize value, it should be a power of 2, and finally the image is decoded.

// Decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f) {
    try {
        // Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(f), null, o);

        // 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(new FileInputStream(f), null, o2);
    } catch (FileNotFoundException e) {}
    return null;
}

Solution 3

I've made a small improvement to Fedor's code. It basically does the same, but without the (in my opinion) ugly while loop and it always results in a power of two. Kudos to Fedor for making the original solution, I was stuck until I found his, and then I was able to make this one :)

 private Bitmap decodeFile(File f){
    Bitmap b = null;

        //Decode image size
    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;

    FileInputStream fis = new FileInputStream(f);
    BitmapFactory.decodeStream(fis, null, o);
    fis.close();

    int scale = 1;
    if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) {
        scale = (int)Math.pow(2, (int) Math.ceil(Math.log(IMAGE_MAX_SIZE / 
           (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
    }

    //Decode with inSampleSize
    BitmapFactory.Options o2 = new BitmapFactory.Options();
    o2.inSampleSize = scale;
    fis = new FileInputStream(f);
    b = BitmapFactory.decodeStream(fis, null, o2);
    fis.close();

    return b;
}

Solution 4

I come from iOS experience and I was frustrated to discover an issue with something so basic as loading and showing an image. After all, everyone that is having this issue is trying to display reasonably sized images. Anyway, here are the two changes that fixed my problem (and made my app very responsive).

1) Every time you do BitmapFactory.decodeXYZ(), make sure to pass in a BitmapFactory.Options with inPurgeable set to true (and preferably with inInputShareable also set to true).

2) NEVER use Bitmap.createBitmap(width, height, Config.ARGB_8888). I mean NEVER! I've never had that thing not raise memory error after few passes. No amount of recycle(), System.gc(), whatever helped. It always raised exception. The one other way that actually works is to have a dummy image in your drawables (or another Bitmap that you decoded using step 1 above), rescale that to whatever you want, then manipulate the resulting Bitmap (such as passing it on to a Canvas for more fun). So, what you should use instead is: Bitmap.createScaledBitmap(srcBitmap, width, height, false). If for whatever reason you MUST use the brute force create method, then at least pass Config.ARGB_4444.

This is almost guaranteed to save you hours if not days. All that talk about scaling the image, etc. does not really work (unless you consider getting wrong size or degraded image a solution).

Solution 5

It's a known bug, it's not because of large files. Since Android Caches the Drawables, it's going out of memory after using few images. But I've found an alternate way for it, by skipping the android default cache system.

Solution: Move the images to "assets" folder and use the following function to get BitmapDrawable:

public static Drawable getAssetImage(Context context, String filename) throws IOException {
    AssetManager assets = context.getResources().getAssets();
    InputStream buffer = new BufferedInputStream((assets.open("drawable/" + filename + ".png")));
    Bitmap bitmap = BitmapFactory.decodeStream(buffer);
    return new BitmapDrawable(context.getResources(), bitmap);
}
Share:
640,362
Chrispix
Author by

Chrispix

Updated on July 08, 2022

Comments

  • Chrispix
    Chrispix almost 2 years

    I have a ListView with a couple of image buttons on each row. When the user clicks the list row, it launches a new activity. I have had to build my own tabs because of an issue with the camera layout. The activity that gets launched for the result is a map. If I click on my button to launch the image preview (load an image off the SD card) the application returns from the activity back to the ListView activity to the result handler to relaunch my new activity which is nothing more than an image widget.

    The image preview on the ListView is being done with the cursor and ListAdapter. This makes it pretty simple, but I am not sure how I can put a resized image (I.e. Smaller bit size not pixel as the src for the image button on the fly. So I just resized the image that came off the phone camera.

    The issue is that I get an OutOfMemoryError when it tries to go back and re-launch the 2nd activity.

    • Is there a way I can build the list adapter easily row by row, where I can resize on the fly (bitwise)?

    This would be preferable as I also need to make some changes to the properties of the widgets/elements in each row as I am unable to select a row with the touch screen because of the focus issue. (I can use rollerball.)

    • I know I can do an out of band resize and save my image, but that is not really what I want to do, but some sample code for that would be nice.

    As soon as I disabled the image on the ListView it worked fine again.

    FYI: This is how I was doing it:

    String[] from = new String[] { DBHelper.KEY_BUSINESSNAME, DBHelper.KEY_ADDRESS,
        DBHelper.KEY_CITY, DBHelper.KEY_GPSLONG, DBHelper.KEY_GPSLAT,
        DBHelper.KEY_IMAGEFILENAME  + ""};
    int[] to = new int[] { R.id.businessname, R.id.address, R.id.city, R.id.gpslong,
        R.id.gpslat, R.id.imagefilename };
    notes = new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to);
    setListAdapter(notes);
    

    Where R.id.imagefilename is a ButtonImage.

    Here is my LogCat:

    01-25 05:05:49.877: ERROR/dalvikvm-heap(3896): 6291456-byte external allocation too large for this process.
    01-25 05:05:49.877: ERROR/(3896): VM wont let us allocate 6291456 bytes
    01-25 05:05:49.877: ERROR/AndroidRuntime(3896): Uncaught handler: thread main exiting due to uncaught exception
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:304)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:149)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:174)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.drawable.Drawable.createFromPath(Drawable.java:729)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ImageView.resolveUri(ImageView.java:484)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ImageView.setImageURI(ImageView.java:281)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.SimpleCursorAdapter.setViewImage(SimpleCursorAdapter.java:183)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.SimpleCursorAdapter.bindView(SimpleCursorAdapter.java:129)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.CursorAdapter.getView(CursorAdapter.java:150)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.AbsListView.obtainView(AbsListView.java:1057)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ListView.makeAndAddView(ListView.java:1616)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ListView.fillSpecific(ListView.java:1177)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ListView.layoutChildren(ListView.java:1454)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.AbsListView.onLayout(AbsListView.java:937)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1108)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.onLayout(LinearLayout.java:922)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.FrameLayout.onLayout(FrameLayout.java:294)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.layoutVertical(LinearLayout.java:999)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.onLayout(LinearLayout.java:920)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.FrameLayout.onLayout(FrameLayout.java:294)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.ViewRoot.performTraversals(ViewRoot.java:771)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1103)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.os.Handler.dispatchMessage(Handler.java:88)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.os.Looper.loop(Looper.java:123)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.app.ActivityThread.main(ActivityThread.java:3742)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at java.lang.reflect.Method.invokeNative(Native Method)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at java.lang.reflect.Method.invoke(Method.java:515)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)
    01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at dalvik.system.NativeStart.main(Native Method)
    01-25 05:10:01.127: ERROR/AndroidRuntime(3943): ERROR: thread attach failed 
    

    I also have a new error when displaying an image:

    22:13:18.594: DEBUG/skia(4204): xxxxxxxxxxx jpeg error 20 Improper call to JPEG library in state %d
    22:13:18.604: INFO/System.out(4204): resolveUri failed on bad bitmap uri: 
    22:13:18.694: ERROR/dalvikvm-heap(4204): 6291456-byte external allocation too large for this process.
    22:13:18.694: ERROR/(4204): VM won't let us allocate 6291456 bytes
    22:13:18.694: DEBUG/skia(4204): xxxxxxxxxxxxxxxxxxxx allocPixelRef failed
    
    • Fraggle
      Fraggle almost 13 years
      I solved this by avoiding Bitmap.decodeStream or decodeFile and using BitmapFactory.decodeFileDescriptor method.
    • Shailendra Singh Rajawat
      Shailendra Singh Rajawat about 10 years
      I Also faced similar issue couple of weeks back and i solved it by scaling down images upto optimal point. I have written complete approach in my blog codingjunkiesforum.wordpress.com/2014/06/12/… and uploaded complete sample project with OOM prone code vs OOM Proof code athttps://github.com/shailendra123/BitmapHandlingDemo
    • Fattie
      Fattie almost 10 years
    • rene
      rene almost 9 years
      The accepted answer on this question is being discussed on meta
    • Developine
      Developine almost 8 years
    • Access Denied
      Access Denied over 6 years
      This happens because of bad android architecture. It should resize images itself like ios and UWP does this. I don't have to do this stuff myself. Android developers get used to that hell and think it works the way it should.
    • kaay
      kaay over 2 years
      The last time I touched Android (years ago), this was still an unsolved problem, even WITH resampling, caching, manual recycling, gc() and larger heap sizes - they just push the problem further back and can't all be always used: stackoverflow.com/questions/8240502 and can't be fixed because Bitmap is a final class.
    • Chrispix
      Chrispix over 2 years
      @kaay Not seeing any issues with this anymore.. Actually since learning this, I have not experienced any OOM on Android...
  • Fedor
    Fedor over 14 years
    This approach scales the bitmap. But it doesn't solve the OutOfMemory issue because the full bitmap is being decoded anyway.
  • Mirko N.
    Mirko N. about 14 years
    Note that 10 may not be the best value for inSampleSize though, the documentation suggests using powers of 2.
  • Flynn81
    Flynn81 almost 14 years
    I'm facing the same problem as Chrispix, but I don't think the solution here really solves the problem, but rather sidesteps it. Changing the sample size reduces the amount of memory used (at the cost of image quality, which is probably okay for an image preview), but it will not prevent the exception if a large enough image stream is decoded, of if multiple image streams are decoded. If I find a better solution (and there may not be one) I'll post an answer here.
  • stealthcopter
    stealthcopter almost 14 years
    You only need an appropriate size to match the screen in pixel density, for zooming in and such you can take a sample of the image at a higher density.
  • Fedor
    Fedor almost 14 years
    Yes you're right while is not so beautiful. I just tried to make it clear to everyone. Thanks for your code.
  • Chrispix
    Chrispix almost 14 years
    I will see if I can look at my old code, but I think it did solve my out of memory issues. Will double check my old code.
  • DougW
    DougW over 13 years
    @Thomas Vervest - There's a big problem with that code. ^ doesn't raise 2 to a power, it xors 2 with the result. You want Math.pow(2.0, ...). Otherwise, this looks good.
  • Thomas Vervest
    Thomas Vervest over 13 years
    Ooh, that's a very good one! My bad, I'll correct it immediately, thanks for the reply!
  • matsev
    matsev over 13 years
    You are creating two new FileInputStreams, one for each call to the BitmapFactory.decodeStream(). Don't you have to save a reference to each of them so that they can be closed in a finally block?
  • sgarman
    sgarman about 13 years
    Can anyone explain what the REQUIRED_SIZE corresponds to? Is that pixels of one side, dips? Thanks!
  • Fedor
    Fedor about 13 years
    REQUIRED_SIZE is the new size you want to scale to.
  • Vincent
    Vincent about 13 years
    "and then cache it in a map against its name." How exactly do you cache your images?
  • ErikR
    ErikR about 13 years
    Have you actually tried this? Even though the pixel data is not actually stored within the Dalvik heap, its size in native memory is reported to the VM and counted against its available memory.
  • Rafael T
    Rafael T almost 13 years
    @Vincent I think its not hard to store them in a Map. I would suggest something like HashMap<KEY, Bitmap> map, where the Key can be a String of the source or anything that makes sense for you. Lets assume you take a path as KEY, you store it as map.put(Path, Bitmap) and recieve it through map.get(Path)
  • Dori
    Dori almost 13 years
    you prob would want to use HashMap<String, SoftReference<Bitmap>> if you are implementing an image Cache otherwise you may run out of memory anyway - also i dont think that "it allocates memory outside of VM heap which is never reclaimed by GC" is true, the memory is reclaimed as i understand just may be a delay, which is what bitmap.recycle() is for, as a hint to reclaim the mem early...
  • Artem Russakovskii
    Artem Russakovskii over 12 years
    According to the API, calling recycle() is not needed.
  • Artem Russakovskii
    Artem Russakovskii over 12 years
    inPurgeable fixed OOM for me.
  • PiyushMishra
    PiyushMishra over 12 years
    same result out of memeory, actually it wont matter which method you are using it depend upon the number of bytes you are holding on to read the data that gives out of memory.
  • Jan-Terje Sørensen
    Jan-Terje Sørensen over 12 years
    BitmapFactory.Options options = new BitmapFactory.Options(); options.inPurgeable = true; and Bitmap.createScaledBitmap(srcBitmap, width, height, false); solved my issue I had with out of memory exception on android 4.0.0. Thanks mate!
  • rOrlig
    rOrlig over 12 years
    In Bitmap.createScaledBitmap() call you should probably use true as the flag parameter. Otherwise the quality of the image will not be smooth when scaling up. Check this thread stackoverflow.com/questions/2895065/…
  • ana
    ana about 12 years
    Since you're doing powers of 2, instead of scale *=2, you should do scale >> 2. For divide, you can do scale << 2.
  • Stefan Anca
    Stefan Anca almost 12 years
    Great answer! But how do you get REQUIRED_SIZE dynamically at runtime (catering for different size displays)? This must be done once the View is being drawn but before the Bitmap is expanded.
  • Yevgeny Simkin
    Yevgeny Simkin almost 12 years
    That really is fabulous advice. Wish I could give you an extra +1 for taking Google to task for this amazingly rinky dink bug. I mean... if it's not a bug then the documentation really needs to have some seriously flashing neon signs saying "THIS IS HOW YOU PROCESS PHOTOS", cause I've been struggling with this for 2 years and just now found this post. Great find.
  • Mahesh
    Mahesh over 11 years
    And if setImageURI still getting exception then refer this stackoverflow.com/questions/15377186/…
  • Thomas Vervest
    Thomas Vervest about 11 years
    @Babibu The documentation doesn't state that the stream is closed for you, therefore I assume it should still be closed. An interesting, and related, discussion can be found here. Note the comment by Adrian Smith, which relates directly to our debate.
  • NoBugs
    NoBugs about 11 years
    In this example at least, it looks like you aren't keeping the reference to the full bitmap, thus the memory savings.
  • user1106888
    user1106888 almost 11 years
    this solution helped me but the image quality is terrible. I am using a viewfilpper to display the images any suggestions?
  • PeteH
    PeteH almost 11 years
    I can't thank you enough for this! I was chasing the wrong problem before seeing this. Question for you though: Since each or my list rows has a unique name and photo I had to use a convertView array to retain each of the rows' values. I couldn't see how using a single variable would allow you to do so. Am I missing something?
  • Nguyen  Minh Binh
    Nguyen Minh Binh over 10 years
    I usually set options.inPreferredConfig = Bitmap.Config.ALPHA_8;. With this setting, each pixcel will be save by 1 byte instead of 4 bytes as default.
  • Travis
    Travis over 10 years
    @Dopyiii FYI *=2 is equivalent to >> 1, not >> 2
  • Denys Kniazhev-Support Ukraine
    Denys Kniazhev-Support Ukraine over 9 years
    As of Lollipop, BitmapFactory.Options.inPurgeable and BitmapFactory.Options.inInputShareable are deprecated developer.android.com/reference/android/graphics/…
  • rene
    rene almost 9 years
    This answer is being discussed on meta
  • FallenAngel
    FallenAngel almost 9 years
    This answer (except the information reached through the link) do not offer much of a solution as for an answer. The important parts of the link should be merged into the question.
  • Martijn Pieters
    Martijn Pieters almost 9 years
    This answer, like the question and the other answers are Community Wiki, so this is something the community can fix by editing, something that does not require moderator intervention.
  • Stealth Rabbi
    Stealth Rabbi about 8 years
    Can you explain what this actually does? Simply telling people to add this doesn't help.
  • Prakash
    Prakash almost 7 years
    This is a very bad solution. Basically you are not trying to fix the problem. Instead asking android system to allocate more heap space for your application. This will have very bad implications on your app like your app consuming lot of battery power as GC has to run through large heap space to clean up memory and also your app performance will be slower.
  • Himanshu Mori
    Himanshu Mori almost 7 years
    then why android is allowing us add this android:largeHeap="true" in our manifest? Now you are challenging Android.
  • Ezio
    Ezio about 6 years
    It does not handle all the scenarios. Glide is not a one stop solution, we are using Glide but still facing many OOM crashes
  • CBMurphy
    CBMurphy about 6 years
    I wasn't saying it was a one stop solution. I was adding it to the toolbox for those that haven't heard of it.
  • Vaibhav Vishal
    Vaibhav Vishal over 5 years
    please format your code properly, also this doesn't looks like valid xml
  • abhiTronix
    abhiTronix almost 4 years
    @HimanshuMori You may want to reconsider your decision about using android:largeHeap="true". See this answer stackoverflow.com/a/30930239/10158117 or any other answer in that thread. It might help you understand what you're doing wrong.
  • TwoFingerRightClick
    TwoFingerRightClick about 2 years
    Really helpful in 2022.. Trying to run an app on an old HTC One S. 31mb image in a memory stream is too much lol.
  • TwoFingerRightClick
    TwoFingerRightClick about 2 years
    Helpful in 2022. Trying to run an app on an HTC One S. Cant load 31mb stream lol, this did the trick, as I am compressing images already to upload to a ML api.