Android OutOfMemoryError:?

54,285

Solution 1

maybe this help you ?

add manifest

android > v3

<application
    ....
       android:largeHeap="true"> 

Solution 2

Common fixes:

1. Fix your contexts:

Try using the appropiate context: For example since a Toast can be seen in many activities instead of in just one, use getApplicationContext() for toasts, and since services can keep running even though an activity has ended start a service with:

Intent myService = new Intent(getApplicationContext(), MyService.class)

Use this table as a quick guide for what context is appropiate: enter image description here

Original article on context here.

2. Check that you're actually finishing your services.

For example I have an intentService that use google location service api. And I forgot to call googleApiClient.disconnect();:

//Disconnect from API onDestroy()
    if (googleApiClient.isConnected()) {
        LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, GoogleLocationService.this);
        googleApiClient.disconnect();
    }

3. Check image and bitmaps usage:

If you are using square's library Picasso I found I was leaking memory by not using the .fit(), that drastically reduced my memory footprint from 50MB in average to less than 19MB:

Picasso.with(ActivityExample.this)                   //Activity context
                .load(object.getImageUrl())           
                .fit()                                //This avoided the OutOfMemoryError
                .centerCrop()                         //makes image to not stretch
                .into(imageView);

4. If you are using broadcast receivers unregister them.

5. If you are using java.util.Observer (Observer pattern):

Make sure to to use deleteObserver(observer);

Solution 3

You can do following to avoid this.

Drawable drawable = resultMatchHeaderContainer.getDrawable();

if (drawable instanceof BitmapDrawable) {
    BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
    if (bitmapDrawable != null) {
        Bitmap bitmap = bitmapDrawable.getBitmap();

        if (bitmap != null && !bitmap.isRecycled())
           bitmap.recycle();
    }
}

Loading Bitmap in Imageview always been a cause of out of memory issue it is very common so we have to handle imageview and bitmaps very carefully. What you can do is While setting any background bitmap to your imageview first get the drawable and recycle it so that it is removed from memory and then set the new bitmap. This will help to avoid any OOM issue. Further. You can use BitmapFactoryOptions to reduce the size of your bitmap. like:

// 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;
        FileInputStream stream1 = new FileInputStream(f);
        BitmapFactory.decodeStream(stream1, null, o);
        stream1.close();

        // Find the correct scale value. It should be the power of 2.
        int width_tmp = o.outWidth, height_tmp = o.outHeight;
        int scale = 1;
        while (true) {
            if (width_tmp / 2 < REQUIRED_WIDTH
                    || height_tmp / 2 < REQUIRED_HIGHT)
                break;
            width_tmp /= 2;
            height_tmp /= 2;
            scale *= 2;
        }

        // decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        FileInputStream stream2 = new FileInputStream(f);
        Bitmap bitmap = BitmapFactory.decodeStream(stream2, null, o2);
        stream2.close();
        return bitmap;
    } catch (FileNotFoundException e) {
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

Solution 4

This could occur for several reasons, you might be keeping references to other parts of your code too long. You might be loading to large bitmaps which together with holding on to many references gives you OOM, etc.

Normally when an OOM occurs a hprof (snapshot of the Heap) is created on the root of the sdcard (or internal storage if sdcard does not exist), which can be read by tools like Eclipse MAT (included in the android tools if you use Eclipse). First one might need to convert the hprof with hprof-conv tool. Here's one tutorial of how to use Eclipse MAT: Investigating Your RAM Usage. The leak suspects report is a good first read when hprof is loaded in Eclipse MAT

After profiling you you could read up on how to load images effectively from Displaying Bitmaps Efficiently

There's also several popular image loading libraries such as universal image loader and picasso available, that do what you need with ease.

Solution 5

final Bitmap smile = BitmapFactory.decodeResource(getResources(), R.drawable.emo_im_happy);

Call

String pathname=BitMapToString(smile);

and then call

setImagesNew(linearview,pathname,activity);

...

public String BitMapToString(Bitmap bitmap) { 
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
             bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); 
        byte[] b = baos.toByteArray();
      String temp = Base64.encodeToString(b, Base64.DEFAULT);
      return temp;
 }


 public static void setImagesNew(LinearLayout linearLayout, String pathName,
                Activity activity) {

            Bitmap bmp = decodeSampledBitmapFromResource(pathName,
                    getDeviceWidth(activity), getDeviceHeight(activity));

linearLayout.setBackgroundDrawable(bmp);


            bmp = null;
            System.gc();
            Runtime.getRuntime().gc();

        }
    public static Bitmap decodeSampledBitmapFromResource(String pathName,
            int reqWidth, int reqHeight) {

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

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

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(pathName, options);
    }

    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;
    }

    @SuppressLint("NewApi")
    public static int getDeviceWidth(Activity activity) {
        int deviceWidth = 0;

        Point size = new Point();
        WindowManager windowManager = activity.getWindowManager();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            windowManager.getDefaultDisplay().getSize(size);
            deviceWidth = size.x;
        } else {
            Display display = windowManager.getDefaultDisplay();
            deviceWidth = display.getWidth();
        }
        return deviceWidth;
    }

    @SuppressLint("NewApi")
    public static int getDeviceHeight(Activity activity) {
        int deviceHeight = 0;

        Point size = new Point();
        WindowManager windowManager = activity.getWindowManager();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            windowManager.getDefaultDisplay().getSize(size);
            deviceHeight = size.y;
        } else {
            Display display = windowManager.getDefaultDisplay();
            deviceHeight = display.getHeight();
        }
        return deviceHeight;
    }

please put all function in your activity and call only setImageNew() and pass parameter in imageview ,sdcardpathname and activity

I hope it will not crash after you implement this code. because I arise same problem as you..

Share:
54,285
NagarjunaReddy
Author by

NagarjunaReddy

My Gitlab Applications http://pnrandroid.blogspot.in/2018/03/how-to-handle-storage-permissions-in.html https://wordpress.com/stats/day/polamreddyn.wordpress.com Usfull Questions: 1) http://stackoverflow.com/questions/424752/any-good-graphing-packages-for-android 2) http://android-graphview.org/ 3) http://jaxenter.com/effort-free-graphs-on-android-with-achartengine-46199.html 4) http://www.dreamincode.net/forums/topic/303235-visualizing-sound-from-the-microphone/ 5) https://github.com/melanke/MlkAndroidChartApi 6) http://www.osciprime.com/?p=source 7) http://android.codeandmagic.org/achartengine-live-scrolling-graph/ 9) http://android-innovation.blogspot.in/2013/07/how-to-implement-pinch-and-pan-zoom-on.html 10) Full to Refresh https://github.com/chrisbanes/Android-PullToRefresh

Updated on August 12, 2020

Comments

  • NagarjunaReddy
    NagarjunaReddy almost 4 years

    I am sporadically getting an OutOfMemoryError: (Heap Size=49187KB, Allocated=41957KB) in one of my apps. What can I do to diagnose this?

      01-09 10:32:02.079: E/dalvikvm(8077): Out of memory: Heap Size=49187KB, Allocated=41957KB, Limit=49152KB
      01-09 10:32:02.079: E/dalvikvm(8077): Extra info: Footprint=48611KB, Allowed Footprint=49187KB, Trimmed=7852KB
      01-09 10:32:02.079: D/skia(8077): --- decoder->decode returned false
      01-09 10:32:02.079: D/AndroidRuntime(8077): Shutting down VM
      01-09 10:32:02.079: W/dalvikvm(8077): threadid=1: thread exiting with uncaught exception (group=0x40a97228)
      01-09 10:32:02.079: E/AndroidRuntime(8077): FATAL EXCEPTION: main
      01-09 10:32:02.079: E/AndroidRuntime(8077): java.lang.OutOfMemoryError: (Heap Size=49187KB, Allocated=41957KB)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:486)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:773)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at android.content.res.Resources.loadDrawable(Resources.java:2044)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at android.content.res.Resources.getDrawable(Resources.java:675)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at android.view.View.setBackgroundResource(View.java:11776)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at com.blsk.bigtoss.ImageLoader.DisplayImage(ImageLoader.java:81)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at com.blsk.bigtoss.MatchActivity$MatchAsyncTask.onPostExecute(MatchActivity.java:1768)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at android.os.AsyncTask.finish(AsyncTask.java:602)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at android.os.AsyncTask.access$600(AsyncTask.java:156)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:615)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at android.os.Handler.dispatchMessage(Handler.java:99)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at android.os.Looper.loop(Looper.java:156)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at android.app.ActivityThread.main(ActivityThread.java:4987)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at java.lang.reflect.Method.invokeNative(Native Method)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at java.lang.reflect.Method.invoke(Method.java:511)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
      01-09 10:32:02.079: E/AndroidRuntime(8077):   at dalvik.system.NativeStart.main(Native Method)
      01-09 10:32:02.099: E/EmbeddedLogger(1612): App crashed! Process: com.blsk.bigtoss
      01-09 10:32:02.099: E/EmbeddedLogger(1612): App crashed! Package: com.blsk.bigtoss v6 (1.2)
      01-09 10:32:02.129: E/EmbeddedLogger(1612): Application Label: Cricket
    

    This is the line where it is happening:

    LinearLayout resultMatchHeaderContainer = new LinearLayout(activity); 
    
    if (!resultImagePath.equals("")) {   
        imageLoader.DisplayImage(resultImagePath,resultMatchHeaderContainer, -1,modifiedHeight, R.drawable.matches_placeholder_result2x);
    } else {
        try {
            resultMatchHeaderContainer.setBackgroundResource(R.drawable.matches_placeholder_result2x); 
        } catch (OutOfMemoryError e) {         
            e.printStackTrace();
        }
    }
    
  • Avtar Guleria
    Avtar Guleria over 10 years
    Why it is downvoted, let me know also the reason for that..Whosover downvoted it please mentioned the reason for it..
  • TheIT
    TheIT over 10 years
    Although this is a nice idea in theory, it doesn't work so well in practice. The call to Recycle() is merely a hint to the GC to reclaim memory. It may not be reclaimed by the time you create your new image and as such may still cause your application to crash. More to the point though, the GC will automatically reclaim the memory when over the next few CG cycles.
  • TheIT
    TheIT over 10 years
    For your second point, I would look at loading the bitmap at a reduced scale if possible using BitmapFactory.Options and the BitmapFactory.decodeResource() method. See developer.android.com/training/displaying-bitmaps/… for more details.
  • Shakeeb Ayaz
    Shakeeb Ayaz over 10 years
    Really why somebody downvoted ,he/she is real nerd ..Most of the time it works ..It worked for me ..in my project..
  • Shakeeb Ayaz
    Shakeeb Ayaz over 10 years
    i was about to answer the same so +1
  • Avtar Guleria
    Avtar Guleria over 10 years
    Thanks. Shakeeb Ayaz. @TheIT, Do you mean that recycle method on bitmap is not useful or what if that then in Which situation we should use it?
  • dipali
    dipali over 10 years
    final Bitmap smile = BitmapFactory.decodeResource(getResources(), R.drawable.emo_im_happy);
  • dipali
    dipali over 10 years
    public String BitMapToString(Bitmap bitmap) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); byte[] b = baos.toByteArray(); String temp = Base64.encodeToString(b, Base64.DEFAULT); return temp; }
  • dipali
    dipali over 10 years
    call BitMapToString(smile);
  • NagarjunaReddy
    NagarjunaReddy over 10 years
  • Magnus
    Magnus over 10 years
    @NagarjunaReddy updated this answer with some more ideas what you could do. I would start off by analyzing the hprof to see if you're holding on to too many refs of some kind, if that's not the case you could consider using some image libraries which are caching images and adapting them to your needed view sizes needs with ease.
  • TheIT
    TheIT over 10 years
    I'm not fully aware of the exact details of it's functionality, but I believe it simply increases the object's GC priority.
  • Mood
    Mood almost 9 years
    The use of largeHeap is not recommended in all cases, please use it very cautiously, it might slow other running application, and also impact your app's reactiveness, since the garbage collector with be solicited more often. For more information check this speech from google i/o youtube.com/watch?v=_CruQY55HOk
  • Adnan Ali
    Adnan Ali almost 8 years
    Never request a large heap simply because you've run out of memory and you need a quick fix—you should use it only when you know exactly where all your memory is being allocated and why it must be retained. Yet, even when you're confident your app can justify the large heap, you should avoid requesting it to whatever extent possible. see developer.android.com/training/articles/memory.html