Replies: 2 comments
-
I've managed to get as far as physically asking the user to give file system access using the following, but I can't seem to get any further than this as it just complains about permissions still. if (Android.OS.Environment.IsExternalStorageManager)
{
await App.Current.MainPage.DisplayAlert("Permission", "MANAGE_EXTERNAL_STORAGE permissions granted", "ОК");
}
else
{
await App.Current.MainPage.DisplayAlert("Permission", "MANAGE_EXTERNAL_STORAGE permissions not granted", "ОК");
string package = AppInfo.Current.PackageName;
var uri = Android.Net.Uri.Parse($"package:{package}");
Platform.CurrentActivity.StartActivityForResult(new Android.Content.Intent(Android.Provider.Settings.ActionManageAppAllFilesAccessPermission, uri), 10);
} |
Beta Was this translation helpful? Give feedback.
-
I had the exact same requirement last week and I implemented like below in Xamarin.Forms. From Api level 29 onwards WRITE_EXTERNAL_STORAGE will not work. We have to use MediaStore which does not require you to ask for permission to the user. You have to ask permissions when Api level is below 29. Here is the code. I am saving the backup under "Downloads" folder. I intentionally rename the backup file as .zip (in reality it is just the db file and not .zip file). I doing so because the Downloads app doesn't show all types of files by default. It does recognize .zip file. private bool TakeManualBackup(string dataFilePath)
{
bool ret = false;
if (Build.VERSION.SdkInt < BuildVersionCodes.Q)
{
if (ContextCompat.CheckSelfPermission(_context, Android.Manifest.Permission.WriteExternalStorage)
!= Android.Content.PM.Permission.Granted)
{
RequestExternalStoragePermission();
return false;
}
}
long fileSize = new FileInfo(dataFilePath).Length;
string backupFileName = string.Format("AppName Backup {0}.zip", DateTime.Now.ToString("yyyy-MM-dd-HH-mm"));
string backupFilePath = "";
string mimeType = "application/octet-stream";
try
{
ContentResolver contentResolver = CrossCurrentActivity.Current.AppContext.ContentResolver;
Android.Net.Uri newUri = null;
Android.Net.Uri inputUri = Android.Net.Uri.FromFile(new Java.IO.File(dataFilePath));
System.IO.Stream inputStream = contentResolver.OpenInputStream(inputUri);
byte[] byteArray;
using (var memoryStream = new MemoryStream())
{
inputStream.CopyTo(memoryStream);
byteArray = memoryStream.ToArray();
}
System.IO.Stream saveStream;
if (Build.VERSION.SdkInt >= BuildVersionCodes.Q)
{
ContentValues values = new ContentValues();
values.Put(Android.Provider.MediaStore.IMediaColumns.Title, backupFileName);
values.Put(Android.Provider.MediaStore.IMediaColumns.MimeType, mimeType);
values.Put(Android.Provider.MediaStore.Downloads.InterfaceConsts.DisplayName, backupFileName);
values.Put(Android.Provider.MediaStore.IMediaColumns.Size, byteArray.Length);
newUri = contentResolver.Insert(Android.Provider.MediaStore.Downloads.ExternalContentUri, values);
backupFilePath = newUri.Path;
saveStream = contentResolver.OpenOutputStream(newUri);
} else {
string downloadsFolderPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).Path;
backupFilePath = Path.Combine(downloadsFolderPath, backupFileName);
newUri = Android.Net.Uri.FromFile(new Java.IO.File(backupFilePath));
saveStream = contentResolver.OpenOutputStream(newUri);
}
using (StreamWriter writer = new StreamWriter(saveStream))
{
writer.BaseStream.Write(byteArray, 0, byteArray.Length);
writer.Close();
}
ret = true;
saveStream.Close();
if (Build.VERSION.SdkInt < BuildVersionCodes.Q)
{
DownloadManager dm = (DownloadManager)_context.GetSystemService(Context.DownloadService);
if (dm != null)
{
dm.AddCompletedDownload(backupFileName, "AppName Backup File", false, mimeType, backupFilePath, byteArray.Length, true);
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.Assert(false);
}
return ret;
} |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
What is the correct process for writing to external storage on API 33 for Android?
Previously you could just use android.permission.WRITE_EXTERNAL_STORAGE and this would allow users to save data wherever they wanted. On API 33 they've removed this and replaced it with READ_MEDIA_*, but I've been unable to get it to work in the same fashion.
To give some context, I have a local SQLite database which I would like the end users to be able to backup and import at their leisure, but this requires the ability to save to the file system.
I've came across this but have not been able to get it to work https://developer.android.com/training/data-storage/manage-all-files#operations-allowed-manage-external-storage and the documentation for .NET MAUI and the .NET MAUI CommunityToolkit still refer to the pre-API 33 options.
Beta Was this translation helpful? Give feedback.
All reactions