Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling Bitmap loading and disposing probably

I'm a newbie to monodroid and I have two killers here I wish someone can help me to resolve:

I have a monodrid app which uploads an image to a web service, the images comes from the device camera or the Pictures gallery.

First thing is I use the following code to take a picture from the device camera:

var intent = new Intent(MediaStore.ActionImageCapture);
var availableActivities = this.PackageManager.QueryIntentActivities(intent, PackageInfoFlags.MatchDefaultOnly);

if (availableActivities != null && availableActivities.Count > 0)
{
    var dir = new Java.IO.File(
        Android.OS.Environment.GetExternalStoragePublicDirectory(
        Android.OS.Environment.DirectoryPictures), "myapp");

        if (!dir.Exists())
        {
            dir.Mkdirs();
        }

        _file = new Java.IO.File(dir, String.Format("image-{0}.jpg", Guid.NewGuid()));
        StaticDataHolder.ImageUri = Android.Net.Uri.FromFile(_file);

        intent.PutExtra(MediaStore.ExtraOutput, Android.Net.Uri.FromFile(_file));
        StartActivityForResult(intent, RESULT_CAMERA_CAPTURE);
}

And this code to read scaled Bitmap from StaticDataHolder.ImageUri into an ImageView control so the user can confirm weather to use the selected image or not:

Bitmap largeBitmap = null;
try
{
    image.SetImageBitmap(null);
    if (Bitmap != null)
    {
        Bitmap.Recycle();
        Bitmap.Dispose();
    }
    largeBitmap = MediaStore.Images.Media.GetBitmap(ContentResolver, StaticDataHolder.ImageUri);
    Bitmap = GetScaledImage(largeBitmap);
    SetImageFromBitmap(image, Bitmap);
    return true;
}
catch (Java.Lang.OutOfMemoryError)
{                
    return false;
}
finally
{
    if (largeBitmap != null)
    {
        largeBitmap.Recycle();
        largeBitmap.Dispose();
    }
}

The second issue is when the user confirm the selected image weather its taken from the camera or picked from the gallery, I create a new Bitmap to be compressed and sent to a web service which I host using the following code:

byte[] buffer = null;

MemoryStream ms = null;
Bitmap bmp = null;

ms = new MemoryStream();
bmp = MediaStore.Images.Media.GetBitmap(ContentResolver, StaticDataHolder.ImageUri);

bmp.Compress(Bitmap.CompressFormat.Jpeg, 60, ms);
buffer = ms.GetBuffer();

ms.Dispose();
bmp.Recycle();
bmp.Dispose();

and then I pass the buffer to the web service method.

This code will work perfectly the first time I start the app, But when I try to load a second image I get OutOfMemoryError exception and the image is not loaded.

How i can load a Bitmap and dispose it probably so I can avoid this exception?. Please note that every step here is managed via separate activities:

1.Take or choose a photo activity. 2.Confirm the selected photo activity. 3.Load the selected photo and send it to the web service activity.

As far as I know the activity is disposed when finished so by default all resources used in it will also be disposed but in my case its appears to be not!.

I have searched it for 3 days with no luck, any help would be much appreciated.

like image 495
Ahmad Sabbagh Avatar asked Aug 16 '26 00:08

Ahmad Sabbagh


1 Answers

Bitmaps in general are a pain on Android since they live in the native heap and are not directly garbage collected, well in Android < 2.3.x at least. Have you tried using BitmapFactory?

For example:

var opts = new BitmapFactory.Options() { InPurgeable = true, InInputShareable = true };
var bitmap = BitmapFactory.DecodeFile (pathToBitmap, opts);

Will cause the result bitmap to be purgeable from memory when needed (http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html)

like image 168
Brett Duncavage Avatar answered Aug 18 '26 12:08

Brett Duncavage



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!