'Xamarin Android: System.IO.DirectoryNotFoundException: Could not find a part of the path

I have a Xamarin.Forms Android app where the page in question looks like this:

<Grid>
    <ScrollView>
        <StackLayout Orientation="Vertical" Padding="30,24,30,24" Spacing="10">
            <Image x:Name="CapturedImage" Source="{Binding Capture}" HeightRequest="100" WidthRequest="100"/>
            <Button Margin="0,10,0,0" Text="Capture photo"
                    Command="{Binding OpenCameraCommand}"
                    BackgroundColor="{StaticResource Primary}"
                    TextColor="White" />
            <Label Text="{Binding Description}" />
        </StackLayout>
    </ScrollView>
</Grid>

With the button I open the Android native camera, which works. In the ViewModel the following happens:

public class CaptureViewModel : BaseViewModel
{
    private string _description;
    public string Description
    {
        get => _description;
        set
        {
            _description = value;
            OnPropertyChanged();
        } 
    }

    private ImageSource _capture;
    public ImageSource Capture
    {
        get => _capture;
        set
        {
            _capture = value;
            Description = value.ToString();
            OnPropertyChanged();
        }
    }

    public ICommand OpenCameraCommand { get; }
    
    public CaptureViewModel()
    {
        Title = "Capture";
        OpenCameraCommand = new Command(OnExecute);
    }

    private async void OnExecute()
    {
        await TakePhotoAsync();
    }

    private async Task TakePhotoAsync()
    {
        var mpo = new MediaPickerOptions
        {
            Title = "test"
        };

        var photo = await MediaPicker.CapturePhotoAsync(mpo);

        await LoadPhotoAsync(photo);

        var image = await Image.FromFileAsync(Capture.ToString());

        var client = await ImageAnnotatorClient.CreateAsync();
        var textAnnotations = await client.DetectTextAsync(image);
        foreach (var text in textAnnotations)
        {
            Description = text.Description;
        }

    }

    private async Task LoadPhotoAsync(FileResult photo)
    {
        if (photo == null)
        {
            Capture = null;
            return;
        }
        var path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
        var newFile = Path.Combine(path, photo.FileName);

        using (var stream = await photo.OpenReadAsync())
        {
            var newStream = File.OpenWrite(newFile);
            await stream.CopyToAsync(newStream);

            newStream.Close();
            newStream.Dispose();
        }

        Capture = newFile;
    }
}

I actually want to use the ImageAnnotator seen in the VM, but I always get an error when trying to getting the captured image for processing.

could not find path

System.IO.DirectoryNotFoundException: 'Could not find a part of the path "/File: /data/user/0/com.companyname.app2/files/df033720bb9646928a9626e25e116990.jpg".'

My permissions in AndroidManifest.xml look like:

<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" />
<application android:label="App2.Android" android:theme="@style/MainTheme"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

I don't know what else could be wrong, but I tried a few other things, that didn't help. What might be the problem?

EDIT: I can see the Capture in the view, btw. and the Label for debugging reasons also shows a path (the same as in the pic).



Solution 1:[1]

So the solution here was to use the FullPathproperty from the returned FileResult to get the correct path needed to turn it into a stream.

wrong:

var path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
    var newFile = Path.Combine(path, photo.FileName);

right:

var photo = await MediaPicker.CapturePhotoAsync(mpo);
var photoFullPath = photo.FullPath;

Capture = photoFullPath;

var image = await Image.FromFileAsync(photoFullPath);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 hansoolow