1

I'm pretty bewildered here and have tried numerous suggestions I've seen on SO. 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.myapp.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).

Architekt
  • 2,141
  • 1
  • 22
  • 27

1 Answers1

0

OMG, I just figured it out after 2 days of banging my head against a wall. It turns out that taking a nap is in fact quite helpful. I thought I had got all my permission requests dealt with. But then I started exploring my device's file structure and noticed that the images weren't being saved. Which is really odd because last night the images were in fact saving. I can see them and the date stamp. Anyway I decided to try to prompt for WRITE_EXTERNAL_STORAGE permission (already did this with READ and CAMERA) and all problems solved.

Architekt
  • 2,141
  • 1
  • 22
  • 27
  • how was it even working without the permission the moment it tried writing it should've crashed. – FreakyAli Mar 30 '18 at 05:05
  • My guess is it had something to do with playing around with the target SDK. Must have at some point set it to < 23. – Architekt Mar 30 '18 at 16:57
  • Doesn't matter you still have to have it in the manifest file to work – FreakyAli Mar 30 '18 at 21:08
  • It was in the manifest. However the checking of the permission to write wasn't being done. Once I added the check for write after I was targeting >= 23 it worked. – Architekt Mar 30 '18 at 23:51