Install
$ agentstack add skill-davidortinau-maui-skills-maui-media-picker ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo 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.
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 IsCaptureSupported → CapturePhotoAsync() | | 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
- [ ]
IsCaptureSupportedguard 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.plisthas all four usage description keys - [ ]
SelectionLimitvalidated 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.
- Author: davidortinau
- Source: davidortinau/maui-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.