Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/Essentials/samples/Samples/View/MediaPickerPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,17 @@
IsToggled="{Binding PickerPreserveMetaData, Mode=TwoWay}"
OnColor="{AppThemeBinding Light=#007BFF, Dark=#0D6EFD}" />
</Grid>

<!-- Save to Gallery -->
<Grid ColumnDefinitions="2*,Auto">
<Label Grid.Column="0"
Text="Save to Gallery (Capture)"
VerticalOptions="Center"
TextColor="{AppThemeBinding Light=#6C757D, Dark=#CED4DA}" />
<Switch Grid.Column="1"
IsToggled="{Binding PickerSaveToGallery, Mode=TwoWay}"
OnColor="{AppThemeBinding Light=#007BFF, Dark=#0D6EFD}" />
</Grid>
</VerticalStackLayout>
</Border>

Expand Down
15 changes: 13 additions & 2 deletions src/Essentials/samples/Samples/ViewModel/MediaPickerViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class MediaPickerViewModel : BaseViewModel
int pickerMaximumHeight = 0;
bool pickerRotateImage = false;
bool pickerPreserveMetaData = true;
bool pickerSaveToGallery = false;
long imageByteLength = 0;
string imageDimensions = "";
private ObservableCollection<PhotoInfo> photoList = [];
Expand Down Expand Up @@ -88,6 +89,12 @@ public bool PickerPreserveMetaData
set => SetProperty(ref pickerPreserveMetaData, value);
}

public bool PickerSaveToGallery
{
get => pickerSaveToGallery;
set => SetProperty(ref pickerSaveToGallery, value);
}

public long ImageByteLength
{
get => imageByteLength;
Expand Down Expand Up @@ -160,7 +167,8 @@ async void DoCapturePhoto()
MaximumWidth = PickerMaximumWidth > 0 ? PickerMaximumWidth : null,
MaximumHeight = PickerMaximumHeight > 0 ? PickerMaximumHeight : null,
RotateImage = PickerRotateImage,
PreserveMetaData = PickerPreserveMetaData
PreserveMetaData = PickerPreserveMetaData,
SaveToGallery = PickerSaveToGallery
});

await LoadPhotoAsync(photo);
Expand Down Expand Up @@ -204,7 +212,10 @@ async void DoCaptureVideo()
{
try
{
var video = await MediaPicker.CaptureVideoAsync();
var video = await MediaPicker.CaptureVideoAsync(new MediaPickerOptions
{
SaveToGallery = PickerSaveToGallery
});

ShowPhoto = false;
ShowMultiplePhotos = false;
Expand Down
90 changes: 88 additions & 2 deletions src/Essentials/src/MediaPicker/MediaPicker.android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ public async Task<FileResult> CaptureAsync(MediaPickerOptions options, bool phot
}

await Permissions.EnsureGrantedAsync<Permissions.Camera>();
// StorageWrite no longer exists starting from Android API 33
if (!OperatingSystem.IsAndroidVersionAtLeast(33))
// Only request storage write permission when saving to gallery on older Android versions
if (options?.SaveToGallery == true && !OperatingSystem.IsAndroidVersionAtLeast(29))
await Permissions.EnsureGrantedAsync<Permissions.StorageWrite>();

var captureIntent = new Intent(photo ? MediaStore.ActionImageCapture : MediaStore.ActionVideoCapture);
Expand Down Expand Up @@ -120,6 +120,12 @@ public async Task<FileResult> CaptureAsync(MediaPickerOptions options, bool phot
captureResult = await CaptureVideoAsync(captureIntent);
}

// Save to gallery if requested
if (captureResult is not null && options?.SaveToGallery == true)
{
await SaveToGalleryAsync(captureResult, photo);
}

// Return the file that we just captured
return captureResult is not null ? new FileResult(captureResult) : null;
}
Expand Down Expand Up @@ -415,6 +421,86 @@ void OnResult(Intent intent)
return path;
}

/// <summary>
/// Saves the captured media file to the device's gallery using MediaStore.
/// On API 29+, uses scoped storage with IsPending flag. On older versions, uses direct file copy.
/// </summary>
static async Task SaveToGalleryAsync(string filePath, bool isPhoto)
{
try
{
var context = Application.Context;
var contentResolver = context.ContentResolver;
if (contentResolver is null)
return;

var fileName = System.IO.Path.GetFileName(filePath);
var extension = System.IO.Path.GetExtension(filePath)?.ToLowerInvariant();
var mimeType = GetMimeType(extension, isPhoto);

var contentValues = new ContentValues();
contentValues.Put(MediaStore.IMediaColumns.DisplayName, fileName);
contentValues.Put(MediaStore.IMediaColumns.MimeType, mimeType);

if (OperatingSystem.IsAndroidVersionAtLeast(29))
{
contentValues.Put(MediaStore.IMediaColumns.RelativePath,
isPhoto ? global::Android.OS.Environment.DirectoryPictures : global::Android.OS.Environment.DirectoryMovies);
contentValues.Put(MediaStore.IMediaColumns.IsPending, 1);
}

var collection = isPhoto
? MediaStore.Images.Media.ExternalContentUri
: MediaStore.Video.Media.ExternalContentUri;

var insertUri = contentResolver.Insert(collection, contentValues);

if (insertUri is not null)
{
using var outputStream = contentResolver.OpenOutputStream(insertUri);
if (outputStream is not null)
{
using var inputStream = File.OpenRead(filePath);
await inputStream.CopyToAsync(outputStream);
}
else
{
// Clean up the pending entry if we couldn't write to it
contentResolver.Delete(insertUri, null, null);
return;
}

if (OperatingSystem.IsAndroidVersionAtLeast(29))
{
contentValues.Clear();
contentValues.Put(MediaStore.IMediaColumns.IsPending, 0);
contentResolver.Update(insertUri, contentValues, null, null);
}
}
Comment on lines +425 to +479
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The XML summary says that on Android versions below API 29 this method uses a direct file copy, but the implementation still uses a MediaStore insert + OpenOutputStream for all API levels. Please either adjust the comment to match the actual approach, or implement the documented pre-29 behavior so the comment stays accurate (and make sure the pre-29 path results in the media being visible in the gallery).

Suggested change
/// Saves the captured media file to the device's gallery using MediaStore.
/// On API 29+, uses scoped storage with IsPending flag. On older versions, uses direct file copy.
/// </summary>
static async Task SaveToGalleryAsync(string filePath, bool isPhoto)
{
try
{
var context = Application.Context;
var contentResolver = context.ContentResolver;
if (contentResolver is null)
return;
var fileName = System.IO.Path.GetFileName(filePath);
var extension = System.IO.Path.GetExtension(filePath)?.ToLowerInvariant();
var mimeType = GetMimeType(extension, isPhoto);
var contentValues = new ContentValues();
contentValues.Put(MediaStore.IMediaColumns.DisplayName, fileName);
contentValues.Put(MediaStore.IMediaColumns.MimeType, mimeType);
if (OperatingSystem.IsAndroidVersionAtLeast(29))
{
contentValues.Put(MediaStore.IMediaColumns.RelativePath,
isPhoto ? global::Android.OS.Environment.DirectoryPictures : global::Android.OS.Environment.DirectoryMovies);
contentValues.Put(MediaStore.IMediaColumns.IsPending, 1);
}
var collection = isPhoto
? MediaStore.Images.Media.ExternalContentUri
: MediaStore.Video.Media.ExternalContentUri;
var insertUri = contentResolver.Insert(collection, contentValues);
if (insertUri is not null)
{
using var outputStream = contentResolver.OpenOutputStream(insertUri);
if (outputStream is not null)
{
using var inputStream = File.OpenRead(filePath);
await inputStream.CopyToAsync(outputStream);
}
else
{
// Clean up the pending entry if we couldn't write to it
contentResolver.Delete(insertUri, null, null);
return;
}
if (OperatingSystem.IsAndroidVersionAtLeast(29))
{
contentValues.Clear();
contentValues.Put(MediaStore.IMediaColumns.IsPending, 0);
contentResolver.Update(insertUri, contentValues, null, null);
}
}
/// Saves the captured media file to the device's gallery.
/// On API 29+, uses MediaStore with scoped storage and IsPending flag. On older versions, uses direct file copy.
/// </summary>
static async Task SaveToGalleryAsync(string filePath, bool isPhoto)
{
try
{
var context = Application.Context;
if (context is null)
return;
var fileName = System.IO.Path.GetFileName(filePath);
var extension = System.IO.Path.GetExtension(filePath)?.ToLowerInvariant();
var mimeType = GetMimeType(extension, isPhoto);
if (OperatingSystem.IsAndroidVersionAtLeast(29))
{
var contentResolver = context.ContentResolver;
if (contentResolver is null)
return;
var contentValues = new ContentValues();
contentValues.Put(MediaStore.IMediaColumns.DisplayName, fileName);
contentValues.Put(MediaStore.IMediaColumns.MimeType, mimeType);
contentValues.Put(MediaStore.IMediaColumns.RelativePath,
isPhoto ? global::Android.OS.Environment.DirectoryPictures : global::Android.OS.Environment.DirectoryMovies);
contentValues.Put(MediaStore.IMediaColumns.IsPending, 1);
var collection = isPhoto
? MediaStore.Images.Media.ExternalContentUri
: MediaStore.Video.Media.ExternalContentUri;
var insertUri = contentResolver.Insert(collection, contentValues);
if (insertUri is not null)
{
using var outputStream = contentResolver.OpenOutputStream(insertUri);
if (outputStream is not null)
{
using var inputStream = File.OpenRead(filePath);
await inputStream.CopyToAsync(outputStream);
}
else
{
// Clean up the pending entry if we couldn't write to it
contentResolver.Delete(insertUri, null, null);
return;
}
contentValues.Clear();
contentValues.Put(MediaStore.IMediaColumns.IsPending, 0);
contentResolver.Update(insertUri, contentValues, null, null);
}
}
else
{
// Pre-29: direct file copy to public external storage, then trigger media scan
var directory = isPhoto
? global::Android.OS.Environment.GetExternalStoragePublicDirectory(global::Android.OS.Environment.DirectoryPictures)
: global::Android.OS.Environment.GetExternalStoragePublicDirectory(global::Android.OS.Environment.DirectoryMovies);
if (directory is null)
return;
var directoryPath = directory.AbsolutePath;
if (string.IsNullOrEmpty(directoryPath))
return;
Directory.CreateDirectory(directoryPath);
var destinationPath = System.IO.Path.Combine(directoryPath, fileName);
File.Copy(filePath, destinationPath, overwrite: true);
// Ensure the copied media appears in the gallery
Android.Media.MediaScannerConnection.ScanFile(
context,
new[] { destinationPath },
new[] { mimeType },
null);
}

Copilot uses AI. Check for mistakes.
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Failed to save to gallery: {ex.Message}");
}
}

static string GetMimeType(string extension, bool isPhoto)
{
return extension switch
{
".jpg" or ".jpeg" => "image/jpeg",
".png" => "image/png",
".heic" or ".heif" => "image/heif",
".webp" => "image/webp",
".gif" => "image/gif",
".mp4" => "video/mp4",
".3gp" => "video/3gpp",
".mkv" => "video/x-matroska",
".webm" => "video/webm",
_ => isPhoto ? "image/jpeg" : "video/mp4",
};
}

async Task<List<FileResult>> PickMultipleUsingIntermediateActivity(MediaPickerOptions options, bool photo)
{
var intent = new Intent(Intent.ActionGetContent);
Expand Down
46 changes: 45 additions & 1 deletion src/Essentials/src/MediaPicker/MediaPicker.ios.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
}
else
{
if (!pickExisting)
if (!pickExisting && options?.SaveToGallery == true)
{
await Permissions.EnsureGrantedAsync<Permissions.PhotosAddOnly>();
}
Expand Down Expand Up @@ -169,6 +169,12 @@
PickerRef?.Dispose();
PickerRef = null;

// Save captured media to the photo gallery if requested
if (!pickExisting && result is not null && options?.SaveToGallery == true)
{
await SaveToPhotoLibraryAsync(result);
}

return result;
}

Expand Down Expand Up @@ -481,6 +487,44 @@
}
}

/// <summary>
/// Saves the captured media file to the device's photo library using PHPhotoLibrary.
/// </summary>
static async Task SaveToPhotoLibraryAsync(FileResult fileResult)
{
try
{
using var stream = await fileResult.OpenReadAsync();
var extension = System.IO.Path.GetExtension(fileResult.FileName);
var tempPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), $"{Guid.NewGuid()}{extension}");
using (var fileStream = File.Create(tempPath))
{
stream.Position = 0;
await stream.CopyToAsync(fileStream);
}
Comment on lines +497 to +504
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the stream copy or PHPhotoLibrary.PerformChangesAsync throws, tempPath won’t be deleted because cleanup happens only after the await. Consider using a try/finally (or similar) so the temporary file is always removed even on failure. Also consider guarding stream.Position = 0 with stream.CanSeek (or removing it) to avoid NotSupportedException for non-seekable streams.

Copilot uses AI. Check for mistakes.

var url = NSUrl.FromFilename(tempPath);

await PHPhotoLibrary.SharedPhotoLibrary.PerformChangesAsync(() =>

Check failure on line 508 in src/Essentials/src/MediaPicker/MediaPicker.ios.cs

View check run for this annotation

Azure Pipelines / maui-pr (Pack .NET MAUI Pack macOS)

src/Essentials/src/MediaPicker/MediaPicker.ios.cs#L508

src/Essentials/src/MediaPicker/MediaPicker.ios.cs(508,45): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'PHPhotoLibrary' does not contain a definition for 'PerformChangesAsync' and no accessible extension method 'PerformChangesAsync' accepting a first argument of type 'PHPhotoLibrary' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 508 in src/Essentials/src/MediaPicker/MediaPicker.ios.cs

View check run for this annotation

Azure Pipelines / maui-pr (Pack .NET MAUI Pack macOS)

src/Essentials/src/MediaPicker/MediaPicker.ios.cs#L508

src/Essentials/src/MediaPicker/MediaPicker.ios.cs(508,45): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'PHPhotoLibrary' does not contain a definition for 'PerformChangesAsync' and no accessible extension method 'PerformChangesAsync' accepting a first argument of type 'PHPhotoLibrary' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 508 in src/Essentials/src/MediaPicker/MediaPicker.ios.cs

View check run for this annotation

Azure Pipelines / maui-pr (Pack .NET MAUI Pack macOS)

src/Essentials/src/MediaPicker/MediaPicker.ios.cs#L508

src/Essentials/src/MediaPicker/MediaPicker.ios.cs(508,45): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'PHPhotoLibrary' does not contain a definition for 'PerformChangesAsync' and no accessible extension method 'PerformChangesAsync' accepting a first argument of type 'PHPhotoLibrary' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 508 in src/Essentials/src/MediaPicker/MediaPicker.ios.cs

View check run for this annotation

Azure Pipelines / maui-pr (Pack .NET MAUI Pack macOS)

src/Essentials/src/MediaPicker/MediaPicker.ios.cs#L508

src/Essentials/src/MediaPicker/MediaPicker.ios.cs(508,45): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'PHPhotoLibrary' does not contain a definition for 'PerformChangesAsync' and no accessible extension method 'PerformChangesAsync' accepting a first argument of type 'PHPhotoLibrary' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 508 in src/Essentials/src/MediaPicker/MediaPicker.ios.cs

View check run for this annotation

Azure Pipelines / maui-pr (Build .NET MAUI Build macOS (Release))

src/Essentials/src/MediaPicker/MediaPicker.ios.cs#L508

src/Essentials/src/MediaPicker/MediaPicker.ios.cs(508,45): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'PHPhotoLibrary' does not contain a definition for 'PerformChangesAsync' and no accessible extension method 'PerformChangesAsync' accepting a first argument of type 'PHPhotoLibrary' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 508 in src/Essentials/src/MediaPicker/MediaPicker.ios.cs

View check run for this annotation

Azure Pipelines / maui-pr (Build .NET MAUI Build macOS (Release))

src/Essentials/src/MediaPicker/MediaPicker.ios.cs#L508

src/Essentials/src/MediaPicker/MediaPicker.ios.cs(508,45): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'PHPhotoLibrary' does not contain a definition for 'PerformChangesAsync' and no accessible extension method 'PerformChangesAsync' accepting a first argument of type 'PHPhotoLibrary' could be found (are you missing a using directive or an assembly reference?)
{
if (IsImageFile(fileResult.FileName))
{
PHAssetChangeRequest.FromImage(url);
}
else
{
PHAssetChangeRequest.FromVideo(url);
}
});

try { File.Delete(tempPath); } catch (IOException) { }
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Failed to save to photo library: {ex.Message}");
}
}

class PhotoPickerDelegate : UIImagePickerControllerDelegate
{
public Action<NSDictionary> CompletedHandler { get; set; }
Expand Down
22 changes: 22 additions & 0 deletions src/Essentials/src/MediaPicker/MediaPicker.shared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,5 +229,27 @@ public int CompressionQuality
/// <para>Currently not supported on Windows.</para>
/// </remarks>
public bool PreserveMetaData { get; set; } = true;

/// <summary>
/// Gets or sets whether the captured image or video should be saved to the device's photo gallery/library.
/// Default value is <see langword="false"/>.
/// </summary>
/// <remarks>
/// <para>This property only applies to capture operations (<see cref="IMediaPicker.CapturePhotoAsync"/> and
/// <see cref="IMediaPicker.CaptureVideoAsync"/>). It has no effect on pick operations.</para>
/// <para>When set to <see langword="true"/>, the necessary platform permissions will be requested automatically:</para>
/// <list type="bullet">
/// <item><description><b>iOS</b>: The <c>NSPhotoLibraryAddUsageDescription</c> key must be present in <c>Info.plist</c>.
/// The <c>PhotosAddOnly</c> permission will be requested.</description></item>
/// <item><description><b>Android</b>: On API &lt; 29, <c>WRITE_EXTERNAL_STORAGE</c> permission is required.
/// On API 29+, <c>MediaStore</c> is used and no additional permission is needed.</description></item>
/// <item><description><b>macOS (Mac Catalyst)</b>: The <c>NSPhotoLibraryAddUsageDescription</c> key must be present in <c>Info.plist</c>.
/// The <c>PhotosAddOnly</c> permission will be requested.</description></item>
/// <item><description><b>Windows</b>: Not supported. This property is ignored on Windows. The captured media is saved to a
/// temporary cache folder and the user can save it manually.</description></item>
/// <item><description><b>Tizen</b>: Not supported. This property is ignored on Tizen.</description></item>
/// </list>
/// </remarks>
public bool SaveToGallery { get; set; } = false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.CanConvertTo(Syste
override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object! value) -> object?
override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type! destinationType) -> object?
static Microsoft.Maui.Storage.FilePicker.PickMultipleAsync(Microsoft.Maui.Storage.PickOptions? options = null) -> System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<Microsoft.Maui.Storage.FileResult!>?>!
Microsoft.Maui.Media.MediaPickerOptions.SaveToGallery.get -> bool
Microsoft.Maui.Media.MediaPickerOptions.SaveToGallery.set -> void
2 changes: 2 additions & 0 deletions src/Essentials/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
Microsoft.Maui.Devices.Sensors.LocationTypeConverter
Microsoft.Maui.Devices.Sensors.LocationTypeConverter.LocationTypeConverter() -> void
Microsoft.Maui.Storage.IFilePicker.PickMultipleAsync(Microsoft.Maui.Storage.PickOptions? options = null) -> System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<Microsoft.Maui.Storage.FileResult!>?>!
Microsoft.Maui.Media.MediaPickerOptions.SaveToGallery.get -> bool
Microsoft.Maui.Media.MediaPickerOptions.SaveToGallery.set -> void
override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type! sourceType) -> bool
override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Type? destinationType) -> bool
override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object! value) -> object?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
Microsoft.Maui.Devices.Sensors.LocationTypeConverter
Microsoft.Maui.Devices.Sensors.LocationTypeConverter.LocationTypeConverter() -> void
Microsoft.Maui.Storage.IFilePicker.PickMultipleAsync(Microsoft.Maui.Storage.PickOptions? options = null) -> System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<Microsoft.Maui.Storage.FileResult!>?>!
Microsoft.Maui.Media.MediaPickerOptions.SaveToGallery.get -> bool
Microsoft.Maui.Media.MediaPickerOptions.SaveToGallery.set -> void
override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type! sourceType) -> bool
override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Type? destinationType) -> bool
override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object! value) -> object?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
Microsoft.Maui.Devices.Sensors.LocationTypeConverter
Microsoft.Maui.Devices.Sensors.LocationTypeConverter.LocationTypeConverter() -> void
Microsoft.Maui.Storage.IFilePicker.PickMultipleAsync(Microsoft.Maui.Storage.PickOptions? options = null) -> System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<Microsoft.Maui.Storage.FileResult!>?>!
Microsoft.Maui.Media.MediaPickerOptions.SaveToGallery.get -> bool
Microsoft.Maui.Media.MediaPickerOptions.SaveToGallery.set -> void
override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Type? destinationType) -> bool
static Microsoft.Maui.Storage.FilePicker.PickMultipleAsync(Microsoft.Maui.Storage.PickOptions? options = null) -> System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<Microsoft.Maui.Storage.FileResult!>?>!
~override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) -> bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.CanConvertTo(Syste
override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object! value) -> object?
override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type! destinationType) -> object?
static Microsoft.Maui.Storage.FilePicker.PickMultipleAsync(Microsoft.Maui.Storage.PickOptions? options = null) -> System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<Microsoft.Maui.Storage.FileResult!>?>!
Microsoft.Maui.Media.MediaPickerOptions.SaveToGallery.get -> bool
Microsoft.Maui.Media.MediaPickerOptions.SaveToGallery.set -> void
2 changes: 2 additions & 0 deletions src/Essentials/src/PublicAPI/net/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.CanConvertTo(Syste
override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object! value) -> object?
override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type! destinationType) -> object?
static Microsoft.Maui.Storage.FilePicker.PickMultipleAsync(Microsoft.Maui.Storage.PickOptions? options = null) -> System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<Microsoft.Maui.Storage.FileResult!>?>!
Microsoft.Maui.Media.MediaPickerOptions.SaveToGallery.get -> bool
Microsoft.Maui.Media.MediaPickerOptions.SaveToGallery.set -> void
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.CanConvertTo(Syste
override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object! value) -> object?
override Microsoft.Maui.Devices.Sensors.LocationTypeConverter.ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type! destinationType) -> object?
static Microsoft.Maui.Storage.FilePicker.PickMultipleAsync(Microsoft.Maui.Storage.PickOptions? options = null) -> System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<Microsoft.Maui.Storage.FileResult!>?>!
Microsoft.Maui.Media.MediaPickerOptions.SaveToGallery.get -> bool
Microsoft.Maui.Media.MediaPickerOptions.SaveToGallery.set -> void
Loading