All skills
davidortinau avatar

/maui-media-picker

@a0cf477

Guidance for picking photos/videos, capturing from camera, multi-select (.NET 10), MediaPickerOptions, platform permissions, and FileResult handling in .NET MAUI. USE FOR: "pick photo", "capture photo", "take picture", "pick video", "camera capture", "MediaPicker", "photo gallery", "image picker", "multi-select photos", "MediaPickerOptions". DO NOT USE FOR: general file picking (use maui-file-handling), image display or optimization (use maui-performance), or camera streaming (use maui-platform-invoke).

Use this Skill: https://skilld.dev/gh/davidortinau/maui-skills/maui-media-picker

This session only. Nothing lands on disk.

referencesmedia-picker-api.md

≈1.1k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Media Picker API Reference

Core API

Use MediaPicker.Default to pick or capture photos and videos. All methods must run on the UI thread.

Single-select methods (all .NET versions)

Method Purpose
MediaPicker.Default.PickPhotoAsync() Pick one photo from gallery
MediaPicker.Default.PickVideoAsync() Pick one video from gallery
MediaPicker.Default.CapturePhotoAsync() Capture a photo with the camera
MediaPicker.Default.CaptureVideoAsync() Capture a video with the camera

All return Task<FileResult?>. A null result means the user cancelled.

Multi-select methods (.NET 10+)

Method Purpose
MediaPicker.Default.PickPhotosAsync() Pick multiple photos
MediaPicker.Default.PickVideosAsync() Pick multiple videos

These return Task<IEnumerable<FileResult>>. An empty list means the user cancelled.

MediaPickerOptions (.NET 10+)

Pass MediaPickerOptions to any pick/capture method to control behavior:

var options = new MediaPickerOptions
{
    Title = "Select photos",        // Picker dialog title
    SelectionLimit = 5,             // Max items (0 = unlimited; multi-select only)
    MaximumWidth = 1024,            // Resize max width in pixels
    MaximumHeight = 1024,           // Resize max height in pixels
    CompressionQuality = 80,       // JPEG quality 0–100
    RotateImage = true,             // Auto-rotate per EXIF
    PreserveMetaData = true         // Keep EXIF/metadata
};

var photos = await MediaPicker.Default.PickPhotosAsync(options);

FileResult Usage

var photo = await MediaPicker.Default.PickPhotoAsync();
if (photo is null)
    return; // user cancelled

// Read the stream
using var stream = await photo.OpenReadAsync();

// Useful properties
string fullPath    = photo.FullPath;
string fileName    = photo.FileName;
string contentType = photo.ContentType;

Save to app storage

async Task<string> SaveToAppDataAsync(FileResult fileResult)
{
    var targetPath = Path.Combine(FileSystem.AppDataDirectory, fileResult.FileName);
    using var sourceStream = await fileResult.OpenReadAsync();
    using var targetStream = File.OpenWrite(targetPath);
    await sourceStream.CopyToAsync(targetStream);
    return targetPath;
}

Check Availability Before Capture

if (MediaPicker.Default.IsCaptureSupported)
{
    var photo = await MediaPicker.Default.CapturePhotoAsync();
    // ...
}

Multi-select Example (.NET 10+)

var options = new MediaPickerOptions { SelectionLimit = 10 };
var results = await MediaPicker.Default.PickPhotosAsync(options);

if (!results.Any())
    return; // user cancelled

foreach (var file in results)
{
    using var stream = await file.OpenReadAsync();
    // process each selected photo
}

Platform Permissions

Android

Add to Platforms/Android/AndroidManifest.xml:

<!-- Camera capture -->
<uses-permission android:name="android.permission.CAMERA" />

<!-- Storage: API ≤ 32 (Android 12 and below) -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
                 android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
                 android:maxSdkVersion="32" />

<!-- Storage: API ≥ 33 (Android 13+) -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />

Also add inside <application>:

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

iOS / Mac Catalyst

Add to Platforms/iOS/Info.plist (and Platforms/MacCatalyst/Info.plist):

<key>NSCameraUsageDescription</key>
<string>This app needs camera access to take photos</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app needs microphone access to record video</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs photo library access to pick media</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>This app needs permission to save photos</string>

Windows

No additional permissions required.

Source: SKILL.md on GitHub

No alerts15d4 checks · Risk SAFE
  • Gen Agent Trust Hub15d

    This skill provides instructional guidance and code examples for using the .NET MAUI Media Picker API. It covers best practices for picking and capturing media, handling platform permissions, and managing file streams. No security risks were identified.

  • Socket15d

    No alerts

  • Snyk15d

    Risk: LOW · No issues

  • Runlayer7mo

    1 file scanned · No issues

Signed by skilld at a0cf477. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 6 months ago

README badge

README badge for davidortinau/maui-skills/maui-media-picker