1

I have published my app in play store. Now In Crashes and ANRs I am getting following errors on 2 devices (Galaxy Note3 and Galaxy Note II). I dont know how to solve these errors and what type of error is this? So please help me to fix these errors. On other devices I am not getting any report there.

Errors-

java.lang.OutOfMemoryError
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:677)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:507)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:872)
at android.content.res.Resources.loadDrawable(Resources.java:3022)
at android.content.res.Resources.getDrawable(Resources.java:1586)
at android.view.View.setBackgroundResource(View.java:16120)
at com.info.laughingbuddha.Buddha4.onCreateView(Buddha4.java:21)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1500)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:927)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1467)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:472)
at android.support.v4.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:163)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1068)
at android.support.v4.view.ViewPager.populate(ViewPager.java:914)
at android.support.v4.view.ViewPager$3.run(ViewPager.java:244)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:803)
at android.view.Choreographer.doCallbacks(Choreographer.java:603)
at android.view.Choreographer.doFrame(Choreographer.java:572)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:789)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5293)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1259)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1075)
at dalvik.system.NativeStart.main(Native Method)

Buddha4.java-

package com.info.laughingbuddha;


import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.method.ScrollingMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

public class Buddha4 extends Fragment{

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.buddha, container, false);
    TextViewEx t = (TextViewEx) rootView.findViewById(R.id.textView2);
    t.setText("The Standing Happy Buddha brings riches and happiness.",true);
    t.setMovementMethod(new ScrollingMovementMethod());
    ImageView iv = (ImageView) rootView.findViewById(R.id.image1);
    iv.setBackgroundResource(R.drawable.buddha4);
    return rootView;
    }
}

I dont know what code I need to post so If anyone require any code related to this please comment. Thanks.

Ajay S
  • 48,003
  • 27
  • 91
  • 111
John R
  • 2,078
  • 8
  • 35
  • 58

7 Answers7

6

Try to create scaled bitmap using following line of the code:

Bitmap scaledBitmap = Bitmap.createScaledBitmap(myBitmap, width,
                height, true);

Check the following links:

android - out of memory exception when creating bitmap

Android out of memory exception with bitmaps

Can I catch out of memory exception in Android in Bitmap allocation for decoding a picture file?

Community
  • 1
  • 1
rupesh
  • 2,865
  • 4
  • 24
  • 50
  • I have to use some number instead of height and width in above code? – John R Feb 25 '14 at 06:00
  • yes that you have to figure it out According to your device size and density. @JohnR – rupesh Feb 25 '14 at 06:05
  • @JohnR did u find the solution? – rupesh Mar 01 '14 at 05:20
  • Answer suggested by Andrew is right. I am using all images in only drawable-mdpi folder. But the solution provided by him is not good as I want to scale images for large screens. – John R Mar 01 '14 at 05:30
  • And the answer provided by you confusing for me as I am using weights in Xml. So dont know how to set height and width in equation provided by you. And For your solution I have to test my app again on all virtual devices. – John R Mar 01 '14 at 05:33
  • I am using weight attribute in xml. So What width and height I have to use in code suggested by you? And Is it support all screen sizes? – John R Mar 01 '14 at 06:15
  • see you have to get the width and height of the device by programatically then in that size what width and height you wat to set just put that thats all or you can use the desity – rupesh Mar 01 '14 at 06:18
  • @JohnR you want me to give the sample? – rupesh Mar 01 '14 at 06:18
2

If you have high resolution image , you should scale them down to avoid different devices to load the image without facing a memory problem. In your case, some phones may not exhibit the same behavior on the first run, but eventually, without handling an optimized image loading solution, app will crash.

Check more on the "memory problem":

Topic under Load a Scaled Down Version into Memory.
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
Out of memory error on Android

On how to avoid them:
How to avoid an out of memory error while using bitmaps in Android

For an overview:
http://blogs.innovationm.com/android-out-of-memory-error-causes-solution-and-best-practices/ http://android-developers.blogspot.de/2009/01/avoiding-memory-leaks.html

Before setting a drawable as the background for your imageview, i.e.:

iv.setBackgroundResource(R.drawable.buddha4);  

as @rup35h suggested in the answer, get a scaled bitmap or try other options like inSampleSize, do check how your solution affects the quality of your image too.

Community
  • 1
  • 1
Pararth
  • 8,114
  • 4
  • 34
  • 51
2

Sometimes when we use so many images & backgrounds in applications, it takes lot of space on android RAM. This leads to force close your application by “Out of memory Bound Exception”.

It seems from your crash logs that you have drawable which is quite large, so to avoid the OutOfMemory you have keep drawables that would not take much memory. You can scale down the drawable either as some guys suggested in the answers.

If you don't want go through that and you have not much large size drawable then you can opt to increase your application heap size to large that would increase the heap memory.

How to increase heap size

You can use android:largeHeap="true" in application tag of Android manifest(Reference here) to request a larger heap size, but this will not work on any pre Honeycomb devices.

On pre 2.3 devices, you can use the VMRuntime class, but this will not work on Gingerbread and above See below how to do it.

VMRuntime.getRuntime().setMinimumHeapSize(BIGGER_SIZE);

Before Setting HeapSize make sure that you have entered the appropriate size which will not affect other application or OS functionality.

Before settings just check how much size your app takes & then set the size just to fulfill your job. Dont use so much of memory otherwise other apps might affect.

Update

Note : It is always best practice to free the allocated memory of the bitmaps when these wont longer required, you can this bitmap.recycle()

Ajay S
  • 48,003
  • 27
  • 91
  • 111
  • but why these errors not come on any other devices even those devices have old API versions. Why only on these 2 devices? – John R Feb 22 '14 at 09:24
  • @JohnR This is not specifically for these, you might have same error on other devices also in future, there is no bug in your code but somewhat drawable taking more memory at runtime than available then Android OS opts in those devices to kill the application. – Ajay S Feb 22 '14 at 09:26
  • If I try largeHeap attribute in manifest file. Is it enough to solve this problem? – John R Feb 22 '14 at 09:56
  • @JohnR Yes, most probably it will solve the issue, but please read my complete answer where I wrote what would be effect of this – Ajay S Feb 22 '14 at 09:57
  • I am using min version 8. So which solution I have to use. I am little confuse with your answer. – John R Feb 22 '14 at 10:00
  • You can use `android:largeHeap="true"` if your targetVersionSDK is 11+ – Ajay S Feb 22 '14 at 10:02
  • And for below levels? – John R Feb 22 '14 at 10:36
  • I have covered all these in the answers, for below you can use `VMRuntime.getRuntime().setMinimumHeapSize(BIGGER_SIZE);` – Ajay S Feb 22 '14 at 10:51
  • I have one question In my app I am using min SDK version 8. android:largeHeap="true" is introduced from API level 11. So this code ignored by API level below 11 and work on API level above 11? Right? – John R Feb 28 '14 at 11:21
1

One problem I've had a couple of times is having a lot of MDPI drawable resources but no HDPI / XHDPI versions. When loading these on an HDPI or XHDPI device, Android will scale them up by loading the original, then making a a scaled up copy in memory, meaning you've got two copies in memory at once, the original and a scaled up version. If the drawable is being stretched by the renderer (e.g. If it's a background for a view), then there's no need for Android to scale it up when it's loaded, as the renderer does that anyway. So if you only have one MDPI copy of the image and don't want Android to scale it up, you should put it in the drawable-nodpi folder instead of the drawable or drawable-mdpi folders.

EDIT:

You can use the render time scaling available on an image view by setting the android:scaleType attribute. E.g. you could set the image view's width and height to match_parent, then set the scale type to centerCrop or centerInside to have the image scale up when it's drawn while maintaining its aspect ratio. centerCrop will totally fill the image view but potentially cut off some of the image, whereas centerInside ensures that the whole image is visible, but may leave some blank space. The scaling will be done at render time, so won't use any extra memory.

It can all be done in the layout XML like so:

android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="centerCrop"

To have the image displayed fully inside the image view without cropping, change the last line to:

android:scaleType="centerInside"

Finally, if you don't want to maintain the aspect ratio, you can use the following scale type:

android:scaleType="fitXY"
Andrew Porritt
  • 1,716
  • 15
  • 24
  • +1 for your great notice. I have all images in mdpi folder. I've never mention that here. I did not use any other drawable to make app size less. – John R Mar 01 '14 at 03:04
  • I want images to be scaled. So any other option possible? – John R Mar 01 '14 at 03:07
  • You can use the scaling available on an image view by setting the android:scaleType attribute. E.g. you could set the image view's width and height to match_parent, then set the scale type to centerCrop or centerInside to have the image scale up when it's drawn while maintaining its aspect ratio. centerCrop will totally fill the image view but potentially cut off some of the image, whereas centerInside ensures that the whole image is visible, but may leave some blank space. The scaling will be done at render time, so won't use any extra memory. – Andrew Porritt Mar 01 '14 at 12:36
  • You deserve this bounty. But I accept your answer when you provide some code for your above comment. – John R Mar 02 '14 at 02:55
  • It can all be done in the layout XML like so: android:layout_height="match_parent" android:layout_width="match_parent" android:scaleType="centerCrop" – Andrew Porritt Mar 03 '14 at 10:42
  • I do not want any part of the image to be cropped and please provide complete answer in your above answer. – John R Mar 04 '14 at 05:04
0

You have to scale down your image resource when loading it.

If you are loading the image, using a Bitmap variable, you can use the inSample option, using BitmapFactory.Options. Don't use the Bitmap.createScaledBitmap as it will create another bitmap besides the original one!

Try the following code to load the bitmap:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; //This will just get the size of your image
BitmapFactory.decodeFile(pictureFile.getAbsolutePath(), options);
//Get the downscale ratio
options.inJustDecodeBounds = false;
options.inSampleSize = calculateInSampleSize(options, widthOfTheImageView, heightOfTheImageView);
//Decode the bitmap using the downsampled image
Bitmap finalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image_name options);
//Finally, set the bitmap
imageView.setImageBitmap(finalBitmap);

Where widthOfTheImageView and heightOfTheImageView represent the size of your ImageView.

The calculateInSampleSize method (I got it from the Android developers tutorial):

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;
}
jademcosta
  • 1,528
  • 15
  • 23
0

Do not load Bitmap directly if you are not sure about the size of the image. Sample it when the size is too large. At most time, the length of an image loaded should not exceed the length of your phone screen. Use code like this to sample image.

public static Bitmap loadImage(Context cx, Uri uri, int maxLength) {
    InputStream is = cx.getContentResolver().openInputStream(uri);
    Options opts = new Options();
    opts.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(is, null, opts);
    int length = Math.max(opts.outWidth, opts.outHeight);
    int n = 1;
    while (length > maxLength) {
        maxLength /= 2;
        n ++;
    }
    is = cx.getContentResolver().openInputStream(uri);
    opts.inJustDecodeBounds = false;
    opts.inPurgeable = true;
    opts.inDither = true;
    opts.inPurgeable = true;
    opts.inSampleSize = sample;
    Bitmap bm = BitmapFactory.decodeStream(is, null, opts);
    return bm;
}
James Zhao
  • 418
  • 5
  • 13
0

Remove all the views when you exit from an activity. Make it as null in OnDestroy().

if you are using Bitmaps

use

 bitmap.recycle();

when you used it.

you may use

 android:largeHeap="true"

in you manifest.xml to increase the heap size.

Karthick pop
  • 616
  • 3
  • 16