20

I have a very simple application with one ImageView and a Button. The first Drawable resource loaded by my ImageView is specified with the "android:src" tag in the XML Layout, however at runtime i want to change the picture displayed by it. To do so i start an Activity for result to pick an image from the sd card (intent sent to MediaStore.Images.Media.EXTERNAL_CONTENT_URI). However when the picture is selected, i try to update the ImageView with the chosen Picture's URI but i get the message "java.lang.OutOfMemoryError: bitmap size exceeds VM budget"

I'am trying to load pictures taken with the camera (pics size are around 1.1M) of my HTC-Hero but no success, seems to work only with pictures that are less than 500KB.However i need to load pictures taken with the camera. How can i solve this? what am I doing wrong. Seem to me that the code is very simple and should work.

public void onClick(View v){
 Intent selectImageIntent=new Intent(Intent.ACTION_PICK , 
   android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
   startActivityForResult(selectImageIntent,1);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
 super.onActivityResult(requestCode, resultCode, data);
 if(resultCode==Activity.RESULT_OK){
   Uri selectedImageUri = data.getData();
   Log.i(TAG,"chosen image: "+selectedImageUri.toString());
   ImageView imageView = (ImageView) this.findViewById(R.id.ImageView01);
   imageView.setImageURI(selectedImageUri);//here I get the OutOfMemoryError
   imageView.invalidate();

 }else{
  //canceled
 }

}

p.s. that is the only thing the App should do, I'm not creating other objects so I will like to point out that I am not using heap space for other stuff besides displaying the image.

Solin
  • 756
  • 1
  • 6
  • 8

5 Answers5

43

Seems like before loading a new Bitmap I had to recycle the Bitmap displayed by the ImageView, now it is working without a problem. Hope this helps someone else, just call the folowing method before setting the new ImageView's content.

((BitmapDrawable)imageView.getDrawable()).getBitmap().recycle();

so the code now looks like this:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
    super.onActivityResult(requestCode, resultCode, data);
    switch(requestCode){
        case INTENT_REQUEST_SELECT_IMAGE:
            if(resultCode==Activity.RESULT_OK){
                Uri selectedImageUri = data.getData();
                Log.i(TAG,"selectedImageUri.getPath()"+selectedImageUri.getPath() );
                ImageView imageView = (ImageView) this.findViewById(R.id.ImageView_of_text);
                ((BitmapDrawable)imageView.getDrawable()).getBitmap().recycle();
                imageView.setImageURI(selectedImageUri);
                imageView.invalidate();

            }else{
                //TODO define what to do in case the user canceled OCR or any other event
            }
            break;
        default:
            break;
    }
}

Please note the call to recycle on the Bitmap of the ImageView.

Vladimir Ivanov
  • 42,730
  • 18
  • 77
  • 103
Solin
  • 756
  • 1
  • 6
  • 8
6

This was driving me nuts.

I'm building for a Xoom with very large, hi-res, full screen images (800x1232).

The following code worked for me:

public void onStop()
{
    super.onStop();
    imageView.setImageBitmap(null);
}

Good luck!!!

Caleb
  • 3,692
  • 3
  • 24
  • 28
  • This method will save you if you are using a FragmentStatePagerAdapter with ImageViews since recycling the bitmap will cause an error when re-inflating the view. – Error 454 Apr 27 '12 at 00:17
2

The problem has now been solved. rather than only one line:

((BitmapDrawable)imageView.getDrawable()).getBitmap().recycle(); 

add this code before updating ImageView content:

Drawable toRecycle= gallerypic.getDrawable();
if (toRecycle != null) {
    ((BitmapDrawable)gallerypic.getDrawable()).getBitmap().recycle();
}
gallerypic.setImageURI(selectedimage);
Carl Manaster
  • 39,912
  • 17
  • 102
  • 155
Shawn
  • 157
  • 1
  • 2
  • 14
1

only use this before update imageview: imageView1.setImageURI(null);

Omid Omidi
  • 1,670
  • 2
  • 16
  • 23
1

I used every solution of this post and many more but no one worked.Finally I used android:largeHeap="true" in manifest and that solves my problem.

Hope this helps someone.

Lakhan Sharma
  • 1,741
  • 1
  • 12
  • 19