Search code examples
c#androidxamarinxamarin.androidcapture

Image thumbnail being saved instead of full-image from MediaStore.ActionImageCapture


I am currently trying to take a picture through android, and save the image where I will upload it to a database later. After following some tutorials online, I have found that the code I am using only saves a low-resolution thumbnail of the image I am capturing instead of the full image.

Is there a way to get the full sized image for saving? The format needs to be Jpeg due to the way the software that uses the database is setup.

Taking the photo works as intended:

    private void _openCamera_Click(object sender, EventArgs e)
    {
       Intent intent = new Intent(MediaStore.ActionImageCapture);
       StartActivityForResult(intent, 0);
    }

This is where the image ends up being saved as a thumbnail. Ideally this section would be the only code we modify:

    protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
    {
       base.OnActivityResult(requestCode, resultCode, data);

       Bitmap bitmap = (Bitmap)data.Extras.Get("data");

       this._photo.SetImageBitmap(bitmap);

       MemoryStream memStream = new MemoryStream();
       bitmap.Compress(Bitmap.CompressFormat.Jpeg, 100, memStream);
       this._tempImageData = memStream.ToArray();
    } 

Update: SushiHangover's response works flawlessly. To work with the cached image I used the following code:

protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
    {
        base.OnActivityResult(requestCode, resultCode, data);

        if (resultCode != Result.Ok || requestCode != 88)
        {
            return;
        }

        Bitmap bitmap = BitmapFactory.DecodeFile(cacheName);

        this._photo.SetImageBitmap(bitmap);

        MemoryStream memStream = new MemoryStream();
        bitmap.Compress(Bitmap.CompressFormat.Jpeg, 100, memStream);
        this._tempImageData = memStream.ToArray();
    }

Solution

  • This is a really simplified C# version of the official Android Photo Basics for a full-size photo.

    Note: This saves the full size photo in the app's sandboxed cache directory

    Add a "Resources/xml/file_paths.xml" file:

    <?xml version="1.0" encoding="UTF-8" ?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
        <cache-path name="cache_images" path="." />
    </paths>
    

    Add a FileProvider within the manifest's application open/close tags:

    <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true">
        <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"></meta-data>
    </provider>
    

    Create photo file and request the photo app:

    cacheName = Path.Combine(CacheDir.AbsolutePath, Path.GetTempFileName());
    
    using (var cacheFile = new Java.IO.File(cacheName)) 
    using (var photoURI = FileProvider.GetUriForFile(this, PackageName + ".fileprovider", cacheFile))
    using (var intent = new Intent(MediaStore.ActionImageCapture))
    {
        intent.PutExtra(MediaStore.ExtraOutput, photoURI);
        StartActivityForResult(intent, 88);
    }
    

    Note: cacheName is a class level variable, it will be needed in the OnActivityResult method

    In OnActivityResult, do something with your photo...

    protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
    {
        if (resultCode == Result.Ok && requestCode == 88)
        {
            // Do something with your photo...
            Log.Debug("SO", cacheName );
        }
    }