Edit

Media picker for photos and videos

Browse sample. Browse the sample

This article describes how you can use the .NET Multi-platform App UI (.NET MAUI) IMediaPicker interface. This interface lets a user pick or take a photo or video on the device.

The default implementation of the IMediaPicker interface is available through the MediaPicker.Default property. Both the IMediaPicker interface and MediaPicker class are contained in the Microsoft.Maui.Media namespace.

Get started

To access the media picker functionality, the following platform-specific setup is required.

The CAMERA permission is required and must be configured in the Android project. In addition:

  • If your app targets Android 12 or lower, you must request the READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions.

  • If your app targets Android 13 or higher and needs access to media files that other apps have created, you must request one or more of the following granular media permissions instead of the READ_EXTERNAL_STORAGE permission:

    • READ_MEDIA_IMAGES
    • READ_MEDIA_VIDEO
    • READ_MEDIA_AUDIO

These permissions can be added in the following ways:

  • Add the assembly-based permissions:

    Open the Platforms/Android/MainApplication.cs file and add the following assembly attributes after using directives:

    // Needed for Picking photo/video
    [assembly: UsesPermission(Android.Manifest.Permission.ReadExternalStorage, MaxSdkVersion = 32)]
    [assembly: UsesPermission(Android.Manifest.Permission.ReadMediaAudio)]
    [assembly: UsesPermission(Android.Manifest.Permission.ReadMediaImages)]
    [assembly: UsesPermission(Android.Manifest.Permission.ReadMediaVideo)]
    
    // Needed for Taking photo/video
    [assembly: UsesPermission(Android.Manifest.Permission.Camera)]
    [assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage, MaxSdkVersion = 32)]
    
    // Add these properties if you would like to filter out devices that do not have cameras, or set to false to make them optional
    [assembly: UsesFeature("android.hardware.camera", Required = true)]
    [assembly: UsesFeature("android.hardware.camera.autofocus", Required = true)]
    

    - or -

  • Update the Android Manifest:

    Open the Platforms/Android/AndroidManifest.xml file and add the following in the manifest node:

    <!-- Needed for Picking photo/video -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
    
    <!-- Needed for Taking photo/video -->
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
    
    <!-- Add these properties if you would like to filter out devices that do not have cameras, or set to false to make them optional -->
    <uses-feature android:name="android.hardware.camera" android:required="true" />
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="true" />
    

    - or -

  • Update the Android Manifest in the manifest editor:

    In Visual Studio double-click on the Platforms/Android/AndroidManifest.xml file to open the Android manifest editor. Then, under Required permissions check the permissions listed above. This will automatically update the AndroidManifest.xml file.

If your project's Target Android version is set to Android 11 (R API 30) or higher, you must update your Android Manifest with queries that use Android's package visibility requirements.

In the Platforms/Android/AndroidManifest.xml file, add the following queries/intent nodes in the manifest node:

<queries>
  <intent>
    <action android:name="android.media.action.IMAGE_CAPTURE" />
  </intent>
</queries>

Using media picker

The IMediaPicker interface has the following methods that return a FileResult, which can be used to get the file's location or read it.

Each method optionally takes a MediaPickerOptions parameter that allows the Title to be set on some operating systems, which is displayed to the user.

In .NET 10, the media picker adds multi-select support and new processing options. Use the following methods:

  • PickPhotosAsync (returns List<FileResult>)
    Opens the media browser to select one or more photos.

  • CapturePhotoAsync (returns FileResult?)
    Opens the camera to take a photo.

  • PickVideosAsync (returns List<FileResult>)
    Opens the media browser to select one or more videos.

  • CaptureVideoAsync (returns FileResult?)
    Opens the camera to take a video.

The MediaPickerOptions parameter exposes additional fields such as SelectionLimit, MaximumWidth, MaximumHeight, CompressionQuality, RotateImage, and PreserveMetaData.

Important

When the user cancels a multi-select operation, the returned list is empty. On Android, some picker UIs may not enforce SelectionLimit; on Windows, SelectionLimit isn't supported. Implement your own logic to enforce limits or notify the user on these platforms.

Pick multiple photos

var results = await MediaPicker.PickPhotosAsync(new MediaPickerOptions
{
  // Default is 1; set to 0 for no limit
  SelectionLimit = 10,
  // Optional processing for images
  MaximumWidth = 1024,
  MaximumHeight = 768,
  CompressionQuality = 85,
  RotateImage = true,
  PreserveMetaData = true,
});

foreach (var file in results)
{
  using var stream = await file.OpenReadAsync();
  // Process the stream
}

Pick multiple videos

var results = await MediaPicker.PickVideosAsync(new MediaPickerOptions
{
  SelectionLimit = 3,
  Title = "Select up to 3 videos",
});

foreach (var file in results)
{
  using var stream = await file.OpenReadAsync();
  // Process the stream
}

Tip

For single selection, prefer PickPhotosAsync/PickVideosAsync as well. Set SelectionLimit = 1 (the default) and read the first item if present.

Important

Media picker methods that open the camera or picker UI must be called on the UI thread because permission checks and requests are automatically handled by .NET MAUI.

Recover interrupted Android media picker operations

On Android, the system can destroy and recreate your app while the camera or photo picker UI is in front. If the original media picker task is gone when your app resumes, use the Android-only recovery APIs to retrieve any accepted results.

Recovery is available for AndroidX-backed media picker operations: capture photo, capture video, pick a photo, pick photos, pick a video, and pick videos. Each RecoveredMediaPickerResult has an Id, a Kind, and a Files collection containing recovered FileResult objects. The RecoveredMediaPickerResultKind value identifies the operation as CapturePhoto, CaptureVideo, PickPhoto, PickPhotos, PickVideo, or PickVideos.

Because the recovery APIs are Android-only, place recovery code in an Android-specific file or guard it with #if ANDROID in shared code.

using System.IO;
using Microsoft.Maui.Media;
using Microsoft.Maui.Storage;

#if ANDROID
async Task RecoverMediaPickerResultsAsync()
{
    var results = await MediaPicker.GetRecoveredMediaPickerResultsAsync();

    foreach (var result in results)
    {
        foreach (var file in result.Files)
        {
            var destination = Path.Combine(FileSystem.CacheDirectory, file.FileName);

            using var source = await file.OpenReadAsync();
            using var target = File.Create(destination);
            await source.CopyToAsync(target);
        }

        await MediaPicker.ClearRecoveredMediaPickerResultAsync(result.Id);
    }
}
#endif

Use MediaPicker.GetRecoveredMediaPickerResultsAsync to query already recovered results, and call MediaPicker.ClearRecoveredMediaPickerResultAsync after your app handles each result. If your startup or resume flow needs to wait for recovery reconciliation, call MediaPicker.WaitForRecoveredMediaPickerResultsAsync with a CancellationToken. If the app should abandon a pending media picker operation instead, call MediaPicker.DiscardPendingMediaPickerOperationAsync.

Important

Media picker result recovery is Android-only and doesn't change media picker behavior on iOS, Mac Catalyst, or Windows.

Take a photo

Call the CapturePhotoAsync method to open the camera and let the user take a photo. If the user takes a photo, the return value of the method will be a non-null value. The following code sample uses the media picker to take a photo and save it to the cache directory:

public async void TakePhoto()
{
    if (MediaPicker.Default.IsCaptureSupported)
    {
        FileResult photo = await MediaPicker.Default.CapturePhotoAsync();

        if (photo != null)
        {
            // save the file into local storage
            string localFilePath = Path.Combine(FileSystem.CacheDirectory, photo.FileName);

            using Stream sourceStream = await photo.OpenReadAsync();
            using FileStream localFileStream = File.OpenWrite(localFilePath);

            await sourceStream.CopyToAsync(localFileStream);
        }
    }
}

Tip

The FullPath property doesn't always return the physical path to the file. To get the file, use the OpenReadAsync method.