AgentStack
SKILL verified MIT Self-run

Maui Media Picker

skill-davidortinau-maui-skills-maui-media-picker · by davidortinau

>-

No reviews yet
0 installs
3 views
0.0% view→install

Install

$ agentstack add skill-davidortinau-maui-skills-maui-media-picker

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Maui Media Picker? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

.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 `` 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

| Scenario | Method | |---|---| | User picks one photo | PickPhotoAsync() | | User picks multiple (.NET 10+) | PickPhotosAsync() with SelectionLimit | | App needs camera capture | Check IsCaptureSupportedCapturePhotoAsync() | | Save picked file permanently | Copy stream to FileSystem.AppDataDirectory | | Need photo metadata | Set 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 `` block for camera intent
  • [ ] iOS Info.plist has all four usage description keys
  • [ ] SelectionLimit validated in code, not trusted from platform

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.