2

In my android application i need to take a picture. The first picture goes fine and uploads great to the server so it can be sent by email to the user. That's working fine. Yet when i want to upload an 2nd image it says Out Of Memory Exception. I don't know why, but somehow it does.

My logcat output can be found at this pastebin link: http://pastebin.com/uVduy3d9

My code for handling the image is as following:

First check if phone has a camera:

Camera cam = Camera.open();
    if (cam != null) {
        if (savedInstanceState != null
                && savedInstanceState.getBoolean("Layout")) {
            setContentView(R.layout.registration_edit);
            initializeAccountDetails((User) savedInstanceState
                    .getSerializable(EXTRA_MESSAGE));
            inAccountDetails = true;
        } else {
            setContentView(R.layout.step_4);
            ((Button) findViewById(R.id.snap)).setOnClickListener(this);
            ((Button) findViewById(R.id.rotate)).setOnClickListener(this);
            cam.stopPreview();
            cam.release();
            cam = null;
        }
    } else {
        if (savedInstanceState != null
                && savedInstanceState.getBoolean("Layout")) {
            setContentView(R.layout.registration_edit);
            initializeAccountDetails((User) savedInstanceState
                    .getSerializable(EXTRA_MESSAGE));
            inAccountDetails = true;
        } else {
            setContentView(R.layout.step_4b);
        }
    }

When clicking on the button Snap the following onClick event is fired:

@Override
public void onClick(View v) {
    if (v.getId() == R.id.snap) {
        File directory = new File(Environment.getExternalStorageDirectory()
                + "/BandenAnalyse/Images/");
        if (directory.exists()) {
            Intent i = new Intent("android.media.action.IMAGE_CAPTURE");
            File f = new File(Environment.getExternalStorageDirectory(),
                    "/BandenAnalyse/Images/IMG_" + _timeStamp + ".jpg");
            _mUri = Uri.fromFile(f);
            i.putExtra(MediaStore.EXTRA_OUTPUT, _mUri);
            startActivityForResult(i, TAKE_PICTURE);
        } else {
            directory.mkdir();
            this.onClick(v);
        }
    } else {
        if (_mPhoto != null) {
            Matrix matrix = new Matrix();
            matrix.postRotate(90);
            _mPhoto = Bitmap.createBitmap(_mPhoto, 0, 0,
                    _mPhoto.getWidth(), _mPhoto.getHeight(), matrix, true);
            ((ImageView) findViewById(R.id.photo_holder))
                    .setImageBitmap(_mPhoto);
_mPhoto.recycle();
        }
    }
}

When the picture is taken the result method will be fired:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
    case TAKE_PICTURE:
        if (resultCode == Activity.RESULT_OK) {
            getContentResolver().notifyChange(_mUri, null);
            ContentResolver cr = getContentResolver();
            try {
                _mPhoto = android.provider.MediaStore.Images.Media
                        .getBitmap(cr, _mUri);

                Display display = getWindowManager().getDefaultDisplay();
                Point size = new Point();
                display.getSize(size);
                int width = size.x;
                int scale = _mPhoto.getWidth() / width;
                BitmapFactory.Options o = new BitmapFactory.Options();
                o.inSampleSize = 8;
                Debug.out(PATH_TO_PHOTO);
                Bitmap temp = BitmapFactory.decodeFile(PATH_TO_PHOTO, o);

                _mPhoto = Bitmap.createScaledBitmap(
                                            temp,
                                            _mPhoto.getWidth() / scale, _mPhoto.getHeight()
                                                    / scale, false);

                temp.recycle();
                ((ImageView) findViewById(R.id.photo_holder))
                        .setImageBitmap(_mPhoto);
            } catch (Exception e) {
                Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT)
                        .show();
            }
        }
    }
}

The error should be in the last method, as when i'm in the cameramode and want to get back to my application the error occurs. How to fix this error? Did i miss something?

EDIT:

Added Code in the function: OnActivityResult. Created a temp object as one of the solutions said. Too bad this didn't help solving the error.

The error Out of memory Exception occurs at the line:

_mPhoto = android.provider.MediaStore.Images.Media.getBitmap(cr, _mUri);
4
  • I think your image is not getting compressed. Because in the 1st line of your logcat, it specifies i/p and o/p, width & height are same. Commented Nov 4, 2013 at 10:13
  • The image is not compressed, but i don't want it to be compressed cause of quality loss? Commented Nov 4, 2013 at 10:28
  • You want to send the image to server. And you are also setting it to imageview. Try commenting that code(setting to imageview) and check if it works. Commented Nov 4, 2013 at 10:32
  • Why would i do so? Then the image won't be shown at the activity anymore. But still the error occurs. Commented Nov 4, 2013 at 10:38

1 Answer 1

3

You shouldn't create a bitmap and using it without keeping a reference on it since you have to release it for good memory management.

what you do :

_mPhoto = Bitmap.createScaledBitmap(
                        BitmapFactory.decodeFile(PATH_TO_PHOTO, o),
                        _mPhoto.getWidth() / scale, _mPhoto.getHeight()
                                / scale, false);

is bad ! ;)

prefer :

Bitmap temp = BitmapFactory.decodeFile(PATH_TO_PHOTO, o);

_mPhoto = Bitmap.createScaledBitmap(
                            temp,
                            _mPhoto.getWidth() / scale, _mPhoto.getHeight()
                                    / scale, false);

temp.recycle(); //this call is the key ;) 

Read your code with in mind : "every bitmap created has to be recycle or it will crash with OOM error at some point".

hope that helps !

you should read more about android Bitmaps and memory management for a complete understanding ;)

Sign up to request clarification or add additional context in comments.

7 Comments

I did as you said, yet the error still occurs I'll update the question with the edited part :)
The question is updated with your code. You are right about the mindthinking. Yet somehow the error ain't solved by that :(
Then maybe your bitmap is too large. Try to get a prefered size. see calculateInSampleSize method at developer.android.com/training/displaying-bitmaps/…
If my Bitmap is too large, it should already fail at the 1st attempt to create a bitmap right? Yet in fact the error occurs at the 2nd time. After the error it takes me to the previous activity, and then when i go to the photograph activity again and take the photo everything is fine again
And when i don't compress my Bitmap the upload time just gets a bit longer. When i do compress the upload time gets less
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.