2

My activity simply displays an image:

public class PhotoFrameActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        File externalStorageDir = Environment.getExternalStorageDirectory();
        File picturesDir = new File(externalStorageDir, "DCIM/Camera");
        File[] files = picturesDir.listFiles(new FilenameFilter(){
            public boolean accept(File dir, String name) {
                return name.toLowerCase().endsWith(".jpg");
            }});
        List<File> photoFiles = Arrays.asList(files);
        if (!photoFiles.isEmpty()) {
            try {
                Bitmap currentPhoto = BitmapFactory.decodeStream(new FileInputStream(photoFiles.get(3)));
                ImageView view = (ImageView) findViewById(R.id.photo);
                view.setImageBitmap(currentPhoto);
            } catch (FileNotFoundException e) {
                Log.e("SHOWPIC", "Could not find photo", e);
            }
        }
    }

}

If the activity is restarted, memory is not reclaimed. i.e. if I turn the phone twice I get the following FC:

10-01 17:29:06.011: ERROR/AndroidRuntime(8446): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
10-01 17:29:06.011: ERROR/AndroidRuntime(8446):     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
10-01 17:29:06.011: ERROR/AndroidRuntime(8446):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:470)
10-01 17:29:06.011: ERROR/AndroidRuntime(8446):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:525)
10-01 17:29:06.011: ERROR/AndroidRuntime(8446):     at net.badgerhunt.photoframe.PhotoFrameActivity.onCreate(PhotoFrameActivity.java:34)

How am I leaking?

Synesso
  • 37,610
  • 35
  • 136
  • 207

3 Answers3

3

When your image size is large, this out of memory exception occurs. you have to define the sample size in the options while decoding the stream. like

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

look at the following link for more info.

Strange out of memory issue while loading an image to a Bitmap object

Community
  • 1
  • 1
Yashwanth Kumar
  • 28,931
  • 15
  • 65
  • 69
3

As Yashwanth Kumar suggested, it's NOT due to your image being too large. Even if you reduce the sample size you will still (eventually) get an OOM. The memory leak you have will not get fixed by reducing sample size.

It seems you have a memory leak. Either you can go on a memory leak hunt and try to find the root of your problem, or you could just override the ondestroy method of your activity and do

 @Override
    protected void onDestroy() {
        super.onDestroy();
    view.setImageBitmap(null);
    currentPhoto.recycle();
    }

This will make sure your bitmap gets recycled and the memory gets freed when you activity is being destroyed(as in the case of orientation switch). I would however advice you to watch this video and eventually finding the root to your leak: http://www.google.com/events/io/2011/sessions/memory-management-for-android-apps.html

Joel Martinez
  • 46,929
  • 26
  • 130
  • 185
Emir Kuljanin
  • 3,881
  • 1
  • 25
  • 30
  • That video is about honeycomb ui changes to support phones and tablets. Are you sure that will help me debug my bitmap memory leak? – Synesso Oct 02 '11 at 06:19
  • 1
    There appears to be something wrong with the links to the google io videos. Go to http://developer.android.com/videos and find the video named "Google I/O 2011: Memory management for Android Apps". That's the one I intended you to see. – Emir Kuljanin Oct 02 '11 at 08:59
  • Solutions have helped with replacing one image with another, but memory leak persisted with re-orienting the device regardless of how many places I set the bitmap to null and call recycle. Giving tick to this answer because of the link to the tooling for memory management. – Synesso Oct 06 '11 at 01:28
0

I don't think it is the case (your image has to be incredibly large for an Android device), but why don't you try closing this stream?

Bitmap currentPhoto = BitmapFactory.decodeStream(new FileInputStream(photoFiles.get(3)));
Vicente Plata
  • 3,370
  • 1
  • 19
  • 26