Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
davidortinau avatar

Maui Media Picker

  • 31 installs
  • 163 repo stars
  • Updated July 6, 2026
  • davidortinau/maui-skills

Picks photos and videos, captures from the camera, and handles multi-select and permissions in .NET MAUI apps.

About

Guides picking photos and videos, capturing from camera, multi-select, MediaPickerOptions, platform permissions and FileResult handling in .NET MAUI. A developer uses it when adding camera capture or media picking to a MAUI app.

  • Pick or capture photos and videos with the camera
  • Multi-select, MediaPickerOptions, and FileResult handling

Maui Media Picker by the numbers

  • 31 all-time installs (skills.sh)
  • Ranked #661 of 1,039 Mobile Development skills by installs in the Skillselion catalog
  • Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/davidortinau/maui-skills --skill maui-media-picker

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs31
repo stars163
Last updatedJuly 6, 2026
Repositorydavidortinau/maui-skills

What it does

Picks photos and videos, captures from the camera, and handles multi-select and permissions in .NET MAUI apps.

Files

SKILL.mdMarkdownGitHub ↗

.NET MAUI Media Picker — Gotchas & Best Practices

Common Mistakes

1. Forgetting to check for cancellation

Single-select returns null, multi-select returns an empty list. Not checking causes NullReferenceException.

// ❌ Crashes when user cancels
var photo = await MediaPicker.Default.PickPhotoAsync();
using var stream = await photo.OpenReadAsync();

// ✅ Always check for null / empty
var photo = await MediaPicker.Default.PickPhotoAsync();
if (photo is null) return;
using var stream = await photo.OpenReadAsync();

2. Calling from a background thread

All MediaPicker methods must run on the UI thread or they throw.

// ❌ Will throw on some platforms
await Task.Run(async () => await MediaPicker.Default.PickPhotoAsync());

// ✅ Call directly from a command or event handler on the UI thread
var photo = await MediaPicker.Default.PickPhotoAsync();

3. Not checking IsCaptureSupported

Devices without cameras (emulators, some tablets) will throw if you call capture methods.

// ❌ Crashes on devices without a camera
var photo = await MediaPicker.Default.CapturePhotoAsync();

// ✅ Guard with capability check
if (MediaPicker.Default.IsCaptureSupported)
{
    var photo = await MediaPicker.Default.CapturePhotoAsync();
}

4. Not disposing streams

OpenReadAsync() returns a stream that must be disposed.

// ❌ Leaks the stream
var stream = await photo.OpenReadAsync();
var bytes = ReadAllBytes(stream);

// ✅ Dispose with using
using var stream = await photo.OpenReadAsync();

Platform Pitfalls

⚠️ SelectionLimit is not enforced on Android/Windows

MediaPickerOptions.SelectionLimit is advisory. Always validate the count yourself:

var options = new MediaPickerOptions { SelectionLimit = 5 };
var results = await MediaPicker.Default.PickPhotosAsync(options);
if (results.Count() > 5)
{
    // Warn user or take only the first 5
    results = results.Take(5);
}

⚠️ Android storage permissions split at API 33

  • API ≤ 32: needs READ_EXTERNAL_STORAGE / WRITE_EXTERNAL_STORAGE
  • API ≥ 33: needs READ_MEDIA_IMAGES / READ_MEDIA_VIDEO (broad storage permissions are ignored)
  • Use android:maxSdkVersion="32" on the old permissions to avoid Play Store warnings

⚠️ iOS requires all four plist keys for full functionality

Missing any one of NSCameraUsageDescription, NSMicrophoneUsageDescription, NSPhotoLibraryUsageDescription, or NSPhotoLibraryAddUsageDescription causes a runtime crash when that feature is accessed.

⚠️ Android requires <queries> for camera intents

Without the IMAGE_CAPTURE query in AndroidManifest.xml, CapturePhotoAsync may fail silently on Android 11+ due to package visibility restrictions.

Decision Framework

ScenarioMethod
User picks one photoPickPhotoAsync()
User picks multiple (.NET 10+)PickPhotosAsync() with SelectionLimit
App needs camera captureCheck IsCaptureSupportedCapturePhotoAsync()
Save picked file permanentlyCopy stream to FileSystem.AppDataDirectory
Need photo metadataSet PreserveMetaData = true in MediaPickerOptions

Checklist

  • [ ] All picker calls run on the UI thread
  • [ ] Null/empty checks after every pick/capture call
  • [ ] IsCaptureSupported guard before capture methods
  • [ ] Streams disposed with using
  • [ ] Android manifest has both old and new storage permissions with maxSdkVersion
  • [ ] Android manifest has <queries> block for camera intent
  • [ ] iOS Info.plist has all four usage description keys
  • [ ] SelectionLimit validated in code, not trusted from platform

Related skills

Mobile Developmentfrontendintegrations

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.