Forum Xamarin.Android
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

How do I open a bitmap from a URI that is the result of taking a camera picture?

ArchitektArchitekt USMember ✭✭
edited March 2018 in Xamarin.Android

I'm pretty bewildered here and have tried numerous suggestions I've seen on stack overflow. I was following the Xamarin recipe for accessing the camera on Android and taking a picture. There were some things missing/out of date, but regardless I got to the point where I need to call BitmapFactory.DecodeFile so I can open the image the user just took and resize it to display in my view. The problem I ran into is that I can't use file paths, I have to use URIs. So I followed the instructions in this SO thread

and set up my file provider stuff. I have this file in my resources/xml directory: provider_paths.xml (MyApp being renamed from my actual app details)

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

Then in the manifest I added this inside the section:

<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.burnableapp.provider" android:exported="false" android:grantUriPermissions="true">
    <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" />
</provider>

I ensure the directory exists by doing:

var file = new File(Environment.GetExternalStoragePublicDirectory(Environment.DirectoryPictures), "MyApp");
Directory = file.AbsolutePath;
if (!file.Exists())
    file.Mkdirs();

(Directory being a string variable).
I create the intent and file name like so:

Intent intent = new Intent(MediaStore.ActionImageCapture);              
var file = new File(Directory, $"myPhoto_{Guid.NewGuid()}.jpg");
BaseFilename = file.Name;

_uri = FileProvider.GetUriForFile(MainActivity.Instance, "com.myapp.provider", file);

intent.PutExtra(MediaStore.ExtraOutput, _uri);
intent.AddFlags(ActivityFlags.GrantReadUriPermission);

(BaseFilename being a string variable in this class)

At first I thought maybe I should somehow convert the URI to a file path so that I can call BitmapFactory.DecodeFile. I followed several SO threads and none of them worked. I got various exceptions when they all started doing ContentResolver.Query or cursor operations.

So I figured, well, there's a BitmapFactory.DecodeStream method, why not use that instead? I tried getting a stream from the URI like so:
var stream = MainActivity.Instance.ContentResolver.OpenInputStream(_uri)

But when I do this I get an exception: Java.Lang.Exception: open failed: ENOENT (No such file or directory)

An example of what the URI looks like when I try this:
content://com.myapp.provider/MyApp/Pictures/MyApp/myPhoto_2d13056f-6d23-461a-ad4b-532e10d9cb75.jpg

I'm so confused at this point about what's even the problem, and having a hard time with a lot of outdated Xamarin samples that I don't know where to look or what even is the real underlying problem here. Any insight would be greatly appreciated. BTW in case it matters, I at least go the permission stuff right. I already prompted for camera and storage access (I already dealt with errors regarding not having permission for camera/read/write external storage so at least that's over with).

Answers

Sign In or Register to comment.