2

i tried writing some camera intent handler for taking pictures and post-precessing them (if needed). If i take some pictures on high-resolution my programm break with "allocation too large". if i take some with lower resolution i'm able to take more but it'll break too. After some search i found out that i have to recycle bitmaps i'd made manualy. but the problem didn't disapear. my main problem is that i don't know if there is 1. a memory leak in my code 2. i don't know why it's trying to allocate the momory cause i don't show the bitmaps in my programm (for now), i just save them for further reuse.

public void onClick(View view) {
    Intent i = new Intent("android.media.action.IMAGE_CAPTURE");
    this.mLastPic = new File(this.mFs.getDirPath(), this.mFs.getNextPicName()); //create and save a file for pic
    i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(this.mLastPic));
    this.startActivityForResult(i, 0);
}

the on activty result handler

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(resultCode == Activity.RESULT_OK && requestCode == 0) {

        try {
            if(!this.mController.getSetting(R.string.USE_HEIGH_RESOLUTION)) { //use high res or not
                int quality = this.mFs.getPicQuality(); //get compress quality
                Bitmap pic = BitmapFactory.decodeFile(this.mLastPic.getPath());
                ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                pic.compress(Bitmap.CompressFormat.JPEG, quality, outStream);
                String path = this.mLastPic.getPath();
                if(this.mLastPic.delete()) { //replace the old file with a now file
                    File newFile = new File(path);
                    newFile.createNewFile();
                    FileOutputStream os = new FileOutputStream(newFile);
                    os.write(outStream.toByteArray());
                    Log.d("newEntryActivity.onActivityResult", "replaced pic ");
                } else {
                    Log.d("newEntryActivity.onActivityResult", "cant delete old pic");
                }
                pic.recycle(); //cleaning up
                outStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

logcat shows

05-09 14:35:01.694: E/dalvikvm-heap(845): 6380496-byte external allocation too large for this process. 05-09 14:35:01.694: E/(845): VM won't let us allocate 6380496 bytes

05-09 14:35:01.694: D/AndroidRuntime(845): Shutting down VM

05-09 14:35:01.694: W/dalvikvm(845): threadid=3: thread exiting with uncaught exception (group=0x4001b188)

05-09 14:35:01.694: E/AndroidRuntime(845): Uncaught handler: thread main exiting due to uncaught exception

05-09 14:35:01.714: E/AndroidRuntime(845): java.lang.RuntimeException: Unable to start activity ComponentInfo{unicorn.Heurazio/unicorn.Heurazio.SettingsActivity}: android.view.InflateException: Binary XML file line #2: Error inflating class ...

05-09 14:35:01.714: E/AndroidRuntime(845): Caused by: android.view.InflateException: Binary XML file line #2: Error inflating class

05-09 14:35:01.714: E/AndroidRuntime(845): at android.view.LayoutInflater.createView(LayoutInflater.java:513)

05-09 14:35:01.714: E/AndroidRuntime(845): at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:563)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.view.LayoutInflater.inflate(LayoutInflater.java:385)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.view.LayoutInflater.inflate(LayoutInflater.java:320)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.view.LayoutInflater.inflate(LayoutInflater.java:276)

05-09 14:35:01.714: E/AndroidRuntime(845): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:198)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.app.Activity.setContentView(Activity.java:1622)

05-09 14:35:01.714: E/AndroidRuntime(845): at unicorn.Heurazio.SettingsActivity.onCreate(SettingsActivity.java:38)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)

05-09 14:35:01.714: E/AndroidRuntime(845): ... 11 more

05-09 14:35:01.714: E/AndroidRuntime(845): Caused by: java.lang.reflect.InvocationTargetException

05-09 14:35:01.714: E/AndroidRuntime(845): at android.widget.LinearLayout.(LinearLayout.java:92)

05-09 14:35:01.714: E/AndroidRuntime(845): at java.lang.reflect.Constructor.constructNative(Native Method)

05-09 14:35:01.714: E/AndroidRuntime(845): at java.lang.reflect.Constructor.newInstance(Constructor.java:446)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.view.LayoutInflater.createView(LayoutInflater.java:500)

05-09 14:35:01.714: E/AndroidRuntime(845): ... 21 more

05-09 14:35:01.714: E/AndroidRuntime(845): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget

05-09 14:35:01.714: E/AndroidRuntime(845): at android.graphics.Bitmap.nativeCreate(Native Method) > 05-09 14:35:01.714: E/AndroidRuntime(845): at android.graphics.Bitmap.createBitmap(Bitmap.java:468)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.graphics.Bitmap.createBitmap(Bitmap.java:435)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:340)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:488)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:462)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:323)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.content.res.Resources.loadDrawable(Resources.java:1705)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.content.res.TypedArray.getDrawable(TypedArray.java:548)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.view.View.(View.java:1850)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.view.View.(View.java:1799)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.view.ViewGroup.(ViewGroup.java:284)

any help would be great.

regards Alex

Kara
  • 6,115
  • 16
  • 50
  • 57
Alex
  • 1,857
  • 3
  • 36
  • 51
  • EDIT: i've forgotten to say that the problem occurs when i go back to the privios activity and/or start an other intent. – Alex May 09 '12 at 16:41

3 Answers3

1

If you examine your logs, it looks like a large (~6MB) bitmap allocation occurs while inflating a view in unicorn.Heurazio.SettingsActivity. Check your resources to see if you're using a large bitmap for a background somewhere.

kabuko
  • 36,028
  • 10
  • 80
  • 93
  • i've background image in every activity. it's about 75kB in size. it's placed in the layout as background image. diden't android manages create and recycle of 'em ? – Alex May 09 '12 at 21:15
  • 1
    File size isn't always the same as memory size, especially if it's a JPG. Yes, Android should create/recycle/deallocate them, but sometimes it's not very good at doing it in a timely manner and you need to unbind views manually to help prompt it. – kabuko May 09 '12 at 21:58
  • Here's a related post. Read through the answers: http://stackoverflow.com/questions/1949066/java-lang-outofmemoryerror-bitmap-size-exceeds-vm-budget-android – kabuko May 10 '12 at 06:21
0

After some reading and modifying of my program, like adding a reference to the background in an overloaded application, wiping all unneeded context elements I've still the same problem and it seems to be even worser.

if i can trust my calculation for the size of the bitmap

Bitmap tmp = BitmapFactory.decodeResource(this.getResources(), R.drawable.logo);
Log.d("mainApp", tmp.getRowBytes() * tmp.getHeight() / 1024 + "kB");

my 100kB logo (.png) takes 6mB ram (which would fit for the exception message). any ideas would be great.

Piyush
  • 18,895
  • 5
  • 32
  • 63
Alex
  • 1,857
  • 3
  • 36
  • 51
  • 1
    ok, finaly i found the bug. with the aid of MAT i was able to figure out that i had two references to a long runing context. – Alex May 11 '12 at 01:58
-3

Try to add in your manifest in the application android:largeHeap="true"

Piyush
  • 18,895
  • 5
  • 32
  • 63
FUBUs
  • 617
  • 5
  • 9