Я создаю проект в .Net MAUI, который делает фотографии, и я потрачу деньги на его сохранение в галерее, создав папку.
Я видел, что Google изменил свои разрешения.
<uses-permission android:name = "android.permission.CAMERA" />
<uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion = "32" />
<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion = "32" />
<uses-permission android:name = "android.permission.MANAGE_EXTERNAL_STORAGE"/>
<!-- Required only if your app needs to access images or photos that other apps created -->
<uses-permission android:name = "android.permission.READ_MEDIA_IMAGES" />
<!-- Required only if your app needs to access videos that other apps created -->
<uses-permission android:name = "android.permission.READ_MEDIA_VIDEO" />
<queries>
<intent>
<action android:name = "android.media.action.IMAGE_CAPTURE" />
</intent>
</queries>
Это код:
string sGpath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
// Crear la ruta completa del archivo
var folderPath = Path.Combine(sGpath, "GPV2");
photo.FileName = $ "{vf.IdVisita}_{DateTime.Now:yy_MM_dd_HH_mm_ss}.jpg";
string uniqueFileName = $ "{vf.IdVisita}_{DateTime.Now:yy_MM_dd_HH_mm_ss}.jpg";
string filePath = Path.Combine(folderPath, photo.FileName);
if (!Directory.Exists(folderPath)) {
Directory.CreateDirectory(folderPath);
}
using Stream sourceStream = await photo.OpenReadAsync();
Console.WriteLine($ "Archivo guardado en {filePath}");
vf.Titulo = uniqueFileName;
using(FileStream fileStream = File.OpenRead(filePath)) {
vf.Foto = ReadFully(fileStream);
}
Путь, по которому он сохраняется для меня,
/data/user/0/com.companyname.photov2/files/Pictures/GPV2/1_24_05_30_10_53_48.jpg
Даже несмотря на это, я не удерживаюсь в галерее, как мне это сделать?
@Jason Какой API может быть мне полезен? например Медиа-плагин?
Вы можете сделать снимок с помощью Android и сохранить его в галерее. Итак, в Android 11 и более поздних версиях вы будете запрашивать доступ к хранилищу из своего приложения, использовать пользовательскую папку и с помощью MediaPicker.CapturePhotoAsync сохранять файлы в этой папке. Таким образом, путь будет примерно таким: /storage/emulated/0/Pictures/GPV2/<unique_file_name>.jpg
@BobSmith Как я могу запросить доступ к хранилищу? с Permissions.CheckStatusAsync<Permissions.Media>()? Это не работает





Используйте класс MediaPicker, чтобы запустить камеру и сделать снимок, не нужно усложнять процесс. Кроме того, вам не нужно было думать о том, как обращаться с устаревшими разрешениями. Если вы создали собственную папку, вам придется сохранить поток захваченных фотографий в пути к файлу, поместив его с помощью функции await photoStream.CopyToAsync(newFileStream).
using System.IO;
using System.Threading.Tasks;
using Microsoft.Maui.Media;
using Microsoft.Maui.Storage;
public async Task TakeAndSavePhoto()
{
// Request storage access (Android 11+)
if (Runtime.OperatingSystem == OperatingSystem.Android && Build.VERSION.SdkInt >= BuildVersionCodes.R)
{
var permissionStatus = await MediaLibrary.RequestPermissionsAsync();
if (permissionStatus != MediaLibraryPermissionStatus.Granted)
{
// Handle permission denied scenario
return;
}
}
// Create custom folder
string sGpath = Environment.GetFolderPath(Environment.SpecialFolder.Pictures);
var folderPath = Path.Combine(sGpath, "GPV2");
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
// Capture photo
FilePickerFileType captureFileType = new FilePickerFileType(PickFileType.Image);
var photo = await MediaPicker.CapturePhotoAsync(captureFileType);
if (photo == null)
{
// Handle user cancellation or error
return;
}
// Save photo to custom folder
string uniqueFileName = $"{DateTime.Now:yy_MM_dd_HH_mm_ss}.jpg";
string filePath = Path.Combine(folderPath, uniqueFileName);
if (!string.IsNullOrEmpty(folderPath))
{
using (var newFileStream = File.OpenWrite(filePath))
{
await photo.OpenReadAsync().CopyToAsync(newFileStream);
}
}
// Save photo to public gallery
using (var photoStream = await photo.OpenReadAsync())
{
await MediaLibrary.SaveToAlbumAsync(photoStream, "GPV2 Photos"); // Replace with a descriptive album name
}
Console.WriteLine($"Photo saved to gallery: {filePath}"); // Optional, for debugging
}
Не забудьте обновить AndroidManifest.xml для Android 11 или более поздней версии.
<uses-permission android:name = "android.permission.MANAGE_EXTERNAL_STORAGE" />
Таким образом, путь будет примерно таким: /storage/emulated/0/Pictures/GPV2/<unique_file_name>.jpg
Проверьте статус разрешения
var mediaPermissionStatus = await Permissions.CheckStatusAsync<Permissions.Media>();
Вот возможные результаты:
Permissions.PermissionStatus.Granted: Пользователь уже предоставил вашему приложению разрешение на хранение.Permissions.PermissionStatus.Denied: Пользователь отклонил разрешение на хранение.Permissions.PermissionStatus.Revoked: Пользователь предоставил разрешение в прошлом, но позже отозвал его.Permissions.PermissionStatus.Unknown: Статус разрешения неизвестен.@Giorgio Чтобы это работало, вам нужно добавить READ_EXTERNAL_STORAGE и WRITE_EXTERNAL_STORAGE разрешение.
Также установите android:maxSdkVersion = "28" для WRITE_PERMISSION.
<uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name = "android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion = "28" />
Прочтите эту ссылку для получения дополнительной информации.
https://developer.android.com/guide/topics/manifest/uses-sdk-element#max
https://developer.android.com/guide/topics/manifest/uses-permission-element
https://developer.android.com/training/data-storage/use-cases
https://developer.android.com/training/data-storage/manage-all-files
https://learn.microsoft.com/en-us/dotnet/api/android.manifest.permission?view=net-android-34.0
У меня есть эта ошибка: MediaLibrary, Runtime, BuildVersionCodes, PickFileType не существует.
вам нужно импортировать эти пакеты
например, для среды выполнения используется ObjCRuntime; и у тебя его нет
@Giorgio Runtime — это встроенное пространство имен, поэтому импорт не требуется. MediaLibrary, PickFileType использует пакет Microsoft.Maui.Media и BuildVersionCodes использует пакет Microsoft.Maui.Platform соответственно.
@Джорджио, вы можете задать его как другой вопрос (поскольку он введен в инфраструктуру .NET 7.0), поскольку добавление этой части в мой ответ превратит его в слишком широкую категорию и запутает будущих читателей.
может кто-нибудь из модераторов поможет мне так выразиться?
Вы можете использовать следующий код, чтобы сохранить поток изображений в галерее вашего устройства Android.
public static class ImageSaveHelper
{
public static async Task SaveImage(Stream imageStream)
{
using var stream = imageStream;
using var memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
stream.Position = 0;
memoryStream.Position = 0;
#if ANDROID
var context = Platform.CurrentActivity;
if (OperatingSystem.IsAndroidVersionAtLeast(29))
{
Android.Content.ContentResolver resolver = context.ContentResolver;
Android.Content.ContentValues contentValues = new();
contentValues.Put(Android.Provider.MediaStore.IMediaColumns.DisplayName, "image.png");
contentValues.Put(Android.Provider.MediaStore.IMediaColumns.MimeType, "image/png");
contentValues.Put(Android.Provider.MediaStore.IMediaColumns.RelativePath, "DCIM/" + "image");
Android.Net.Uri imageUri = resolver.Insert(Android.Provider.MediaStore.Images.Media.ExternalContentUri, contentValues);
var os = resolver.OpenOutputStream(imageUri);
Android.Graphics.BitmapFactory.Options options = new();
options.InJustDecodeBounds = true;
var bitmap = Android.Graphics.BitmapFactory.DecodeStream(stream);
bitmap.Compress(Android.Graphics.Bitmap.CompressFormat.Png, 100, os);
os.Flush();
os.Close();
}
else
{
Java.IO.File storagePath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures);
string path = System.IO.Path.Combine(storagePath.ToString(), "image.png");
System.IO.File.WriteAllBytes(path, memoryStream.ToArray());
var mediaScanIntent = new Android.Content.Intent(Android.Content.Intent.ActionMediaScannerScanFile);
mediaScanIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(path)));
context.SendBroadcast(mediaScanIntent);
}
#endif
}
}
Примечание:
Как я могу запросить доступ к хранилищу? с Permissions.CheckStatusAsync<Permissions.Media>()? Это не работает
Вам необходимо добавить следующие разрешения, если вы хотите сохранять и читать изображения в Галерее, а не Permissions.Media.
<uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-sdk android:minSdkVersion = "21" android:targetSdkVersion = "31" />
Из документа Разрешения мы знаем, что разрешение Permissions.Media всегда будет возвращать значение «Предоставлено», если оно проверено или запрошено.
И еще вам понадобится следующее API на мауи:
PermissionStatus statusread = await Permissions.RequestAsync<Permissions.StorageRead>();
PermissionStatus statuswrite = await Permissions.RequestAsync<Permissions.StorageWrite>();
Есть идеи, как это сделать, но в iOS?
Вы не можете просто записать в системную папку. Android предоставляет API-интерфейсы Media для добавления изображений в системную галерею.