Issue
Hey I'm new to Xamarin and I'm hoping you guys could help me. Since there isn't a default folder-picker in xamarin, I want to implement it myself. The problem is that UWP as well as Android throw me this exception:
System.UnauthorizedAccessException HResult=0x80070005 Nachricht = Access to the path 'C:\Users\imtt\AppData\Local\Packages\3ef1aa30-7ffe-4ece-84c7-d2eaf1f8634b_wvdsmkc2tee92\LocalState\Test\199.jpg' is denied. Quelle = System.IO.FileSystem Stapelüberwachung: bei System.IO.FileSystem.DeleteFile(String fullPath) bei System.IO.File.Delete(String path) bei MinimalReproducibleExample.ViewModel.DeleteFiles() in C:\Users\imtt\source\repos\MinimalReproducibleExample\MinimalReproducibleExample\MinimalReproducibleExample\ViewModel.cs: Zeile107 bei Xamarin.Forms.Command.<>c__DisplayClass4_0.<.ctor>b__0(Object o) bei Xamarin.Forms.Command.Execute(Object parameter) bei Xamarin.Forms.ButtonElement.ElementClicked(VisualElement visualElement, IButtonElement ButtonElementManager) bei Xamarin.Forms.Button.SendClicked() bei Xamarin.Forms.Platform.UWP.ButtonRenderer.OnButtonClick(Object sender, RoutedEventArgs e)
Here's the xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MinimalReproducibleExample.MainPage">
<StackLayout>
<Button Text="Add Image" Command="{Binding AddImage}"/>
<Button Text="Delete Images" Command="{Binding DeleteImages}"/>
<Image Source="{Binding CreatedImage}"/>
</StackLayout>
Here's the code-behind:
using Xamarin.Forms;
namespace MinimalReproducibleExample
{
public partial class MainPage : ContentPage
{
public MainPage()
{
BindingContext = new ViewModel();
InitializeComponent();
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace MinimalReproducibleExample
{
public class ViewModel : INotifyPropertyChanged
{
private ImageSource image;
private string fileFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Test");
public ICommand AddImage { get; }
public ICommand DeleteImages { get; }
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public ViewModel()
{
AddImage = new Command(ShowFilePicker);
DeleteImages = new Command(DeleteFiles);
}
public ImageSource CreatedImage
{
get => image;
set
{
image = value;
OnPropertyChanged();
}
}
public async void ShowFilePicker()
{
FilePickerFileType filePickerFileType = new FilePickerFileType(
new Dictionary<DevicePlatform, IEnumerable<string>> {
{ DevicePlatform.iOS, new [] { "jpeg", "png", "mp3", "mpeg4Movie", "plaintext", "utf8PlainText", "html" } },
{ DevicePlatform.Android, new [] { "image/jpeg", "image/png", "audio/mp3", "audio/mpeg", "video/mp4", "text/*", "text/html" } },
{ DevicePlatform.UWP, new []{ "*.jpg", "*.jpeg", "*.png", "*.mp3", "*.mp4", "*.txt", "*.html" } }
});
PickOptions pickOptions = new PickOptions
{
PickerTitle = "Wählen Sie eine oder mehrere Dateien aus",
FileTypes = filePickerFileType,
};
IEnumerable<FileResult> pickedFiles = await FilePicker.PickMultipleAsync(pickOptions);
List<FileResult> results = pickedFiles.ToList();
if (results != null && results.Count > 0)
{
foreach (FileResult fileResult in results)
{
using (Stream stream = await fileResult.OpenReadAsync())
{
DirectoryInfo directoryInfo = Directory.CreateDirectory(fileFolder);
string directoryPath = directoryInfo.FullName;
string filepath = Path.Combine(directoryPath, fileResult.FileName);
try
{
byte[] bArray = new byte[stream.Length];
using (FileStream fs = new FileStream(filepath, FileMode.OpenOrCreate))
{
stream.Read(bArray, 0, (int)stream.Length);
int length = bArray.Length;
fs.Write(bArray, 0, length);
}
CreatedImage = ImageSource.FromFile(filepath);
}
catch (Exception exc)
{
}
}
}
}
}
public void DeleteFiles()
{
string[] filePaths = Directory.GetFiles(fileFolder);
foreach(string filePath in filePaths)
{
File.Delete(filePath);
}
}
}
}
I already gave my app the access to the filesytem via windows settings, also I gave the Android-part read and write access. I even gave the UWP-part "broadFileAccess" and even that didn't make the cut.
This intersects with another problem, where the UWP part can write files into a folder in "Environment.SpecialFolder.LocalApplicationData", but it isn't allowed to delete the files in this folder.
Does this have something to do with the sandboxes of UWP and Android?
Solution
App cannot further process disks / folder in Xamarin
I tested with you code, the problem is the file was using by image control when you delete it, if we disable CreatedImage = ImageSource.FromFile(filepath);
this line. it will work as expect.
I need that image control to display the image
We suggest you render image with stream but not create source from file directly.
For example
CreatedImage = ImageSource.FromStream(() => stream);
Answered By - Nico Zhu - MSFT
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.