I have a Xamarin form application and I want to save file and the file should be shown when user open file manager in his phone or when the phone is connected to computer. I read this article, but the problem is that the file is stored to Environment.SpecialFolder.Personal
and the user can't open this path. Also I found this plugin which does exactly the same thing. It store file to the path Environment.SpecialFolder.Personal
. And when I try to save file in another location, I always get error message says:
Access to the path '..' is denied
Which path should I use to save file?
The
System.Environment.SpecialFolder.Personal
type maps to the path/data/data/[your.package.name]/files
. This is a private directory to your application so you won't be able to see these files using a file browser unless it has root privileges.
So if you want the file to be found by users, you can not save the file in the Personal
folder, but in another folder (such as Downloads
):
string directory = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads);
string file = Path.Combine(directory, "yourfile.txt");
You must also add permissions to AndroidManifest.xml
:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Here is code to save an image for Android, iOS, and UWP:
Android:
public void SaveImage(string filepath)
{
var imageData = System.IO.File.ReadAllBytes(filepath);
var dir = Android.OS.Environment.GetExternalStoragePublicDirectory(
Android.OS.Environment.DirectoryDcim);
var pictures = dir.AbsolutePath;
var filename = System.DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".jpg";
var newFilepath = System.IO.Path.Combine(pictures, filename);
System.IO.File.WriteAllBytes(newFilepath, imageData);
//mediascan adds the saved image into the gallery
var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
mediaScanIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(newFilepath)));
Xamarin.Forms.Forms.Context.SendBroadcast(mediaScanIntent);
}
iOS:
public async void SaveImage(string filepath)
{
// First, check to see if we have initially asked the user for permission
// to access their photo album.
if (Photos.PHPhotoLibrary.AuthorizationStatus ==
Photos.PHAuthorizationStatus.NotDetermined)
{
var status =
await Plugin.Permissions.CrossPermissions.Current.RequestPermissionsAsync(
Plugin.Permissions.Abstractions.Permission.Photos);
}
if (Photos.PHPhotoLibrary.AuthorizationStatus ==
Photos.PHAuthorizationStatus.Authorized)
{
// We have permission to access their photo album,
// so we can go ahead and save the image.
var imageData = System.IO.File.ReadAllBytes(filepath);
var myImage = new UIImage(NSData.FromArray(imageData));
myImage.SaveToPhotosAlbum((image, error) =>
{
if (error != null)
System.Diagnostics.Debug.WriteLine(error.ToString());
});
}
}
Note that for iOS, I am using the Plugin.Permissions nuget packet to request permission from the user.
UWP:
public async void SaveImage(string filepath)
{
var imageData = System.IO.File.ReadAllBytes(filepath);
var filename = System.DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".jpg";
if (Device.Idiom == TargetIdiom.Desktop)
{
var savePicker = new Windows.Storage.Pickers.FileSavePicker();
savePicker.SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
savePicker.SuggestedFileName = filename;
savePicker.FileTypeChoices.Add("JPEG Image", new List<string>() { ".jpg" });
var file = await savePicker.PickSaveFileAsync();
if (file != null)
{
CachedFileManager.DeferUpdates(file);
await FileIO.WriteBytesAsync(file, imageData);
var status = await CachedFileManager.CompleteUpdatesAsync(file);
if (status == Windows.Storage.Provider.FileUpdateStatus.Complete)
System.Diagnostics.Debug.WriteLine("Saved successfully"));
}
}
else
{
StorageFolder storageFolder = KnownFolders.SavedPictures;
StorageFile sampleFile = await storageFolder.CreateFileAsync(
filename + ".jpg", CreationCollisionOption.ReplaceExisting);
await FileIO.WriteBytesAsync(sampleFile, imageData);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With