Android outofmemory error bitmap size exceeds vm budget in 2.3.3

I understand that this question is asked few times. None of them is clear on the solution. Let me explain the problem.

  • I have an Activity which loads 4 images at a time.
  • I load the images in the onResume() method.
  • The Activity throws bitmap error when loading.
  • Notes.

  • I am setting image using setImageResource(R.drawable.xxxx) method call and not bitmap/drawables directly.
  • The images are scaled correctly.
  • The activtiy WORKS FINE in all emulators prior to 2.3 and is WORKING FINE in Actual device (Samsung Galaxy 5)
  • The error is appearing on first initialisation and no orientation change event is fired.
  • images are 800 x 600 in scale and averages 15kb(each) in size.
  • Let me know any solutions. Also let me know if you have similar issues with Android 2.3.3 emulator.

    [update] -snippets

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
                ...
        img_topLeft = (ImageView) findViewById(R.id.Img_Alph_Q_TopLeft);
        img_topRight = (ImageView) findViewById(R.id.Img_Alph_Q_TopRight);
        img_bottomLeft = (ImageView) findViewById(R.id.Img_Alph_Q_BottomLeft);
        img_bottomRight = (ImageView) findViewById(R.id.Img_Alph_Q_BottomRight);
       ...
       }
    protected void onResume() {
        super.onResume();
                img_topLeft.setImageResource(R.drawable.xxx);
                img_topRight.setImageResource(R.drawable.xxx);
                img_bottomLeft.setImageResource(R.drawable.xxx);
                img_bottomRight.setImageResource(R.drawable.xxx);
       ...
       }
    

    03-21 08:59:17.362: ERROR/dalvikvm-heap(5883): 4320000-byte external allocation too large for this process. 03-21 08:59:17.412: ERROR/GraphicsJNI(5883): VM won't let us allocate 4320000 bytes 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): FATAL EXCEPTION: main 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): java.lang.OutOfMemoryError: bitmap size exceeds VM budget 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.Bitmap.nativeCreate(Native Method) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.Bitmap.createBitmap(Bitmap.java:477) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.Bitmap.createBitmap(Bitmap.java:444) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:349) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:498) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:473) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.BitmapFact ory.decodeResourceStream(BitmapFactory.java:336) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.content.res.Resources.loadDrawable(Resources.java:1709) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.content.res.Resources.getDrawable(Resources.java:581) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.widget.ImageView.resolveUri(ImageView.java:501) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.widget.ImageView.setImageResource(ImageView.java:280) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at Quiz.java:124) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): Quiz.onResume(Quiz.java:92) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1150) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.Activity.performResume(Activity.java:3832 ) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2110) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2135) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1668) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.ActivityThread.access$1500(ActivityThread.java:117) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.os.Handler.dispatchMessage(Handler.java:99) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.os.Looper.loop(Looper.java:123) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.ActivityThread.main(ActivityThread.java:3683) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at java.lang.reflect.Method.invokeNat ive(Native Method) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at java.lang.reflect.Method.invoke(Method.java:507) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at dalvik.system.NativeStart.main(Native Method)

    Thanks. Managed to resolve it. Sharing the code for benefit of others Custom class that resolved this issue. based on @Janardhanan.S link.

    public class BitmapResizer {
    
    public static Bitmap decodeImage(Resources res, int id ,int requiredSize){
        try {
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeResource(res, id, o);
    
            //Find the correct scale value. It should be the power of 2.
            final int REQUIRED_SIZE=requiredSize;
            int width_tmp=o.outWidth, height_tmp=o.outHeight;
            int scale=1;
            while(true){
                if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                    break;
                width_tmp/=2;
                height_tmp/=2;
                scale*=2;
            }
    
            //decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize=scale;
            return BitmapFactory.decodeResource(res, id, o2);
        } catch (Exception e) {
    
        }
        return null;
    }
    
    }
    
    //Class call
    int requiredsize = 100; // Still playing around with this number to find the optimum value
    img_topLeft.setImageBitmap(BitmapResizer.decodeImage(getResources(),
            AlphResourceSet.R.drawable.xxx, requiredsize));
    

    Bitmap consumes a lot of memory space. dont create a new bitmap variable for all image you load on activity, instead you can create one bitmap variable and reuse them as much as you can.

    you can use this snippet to resize bitmap

    http://pastebin.com/D8vbQd2u


    Can you post a code snippet of the Activity + stacktrace.

    Did you already check the Avoiding memory leaks article ?

    Especially the following part :

    When a Drawable is attached to a view, the view is set as a callback on the drawable. In the code snippet above, this means the drawable has a reference to the TextView which itself has a reference to the activity (the Context) which in turns has references to pretty much anything (depending on your code.)


    It seems the images are very heavy in nature. I recommend to start the AsyncTimer which actually returns the bitmap instance and in the doBackground() of the AsyncTask pass the image id and rescale it to desire size say 32 x 32 using createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) method of the Bitmap class.

    链接地址: http://www.djcxy.com/p/5758.html

    上一篇: 自动化的PayPal付款

    下一篇: 2.3.3中的Android outofmemory错误位图大小超过了vm预算