[go: up one dir, main page]

adaptive_media_picker 0.0.9 copy "adaptive_media_picker: ^0.0.9" to clipboard
adaptive_media_picker: ^0.0.9 copied to clipboard

Adaptive Flutter media picker for images & videos with smart permissions, limited access UI, and cross-platform support (Android, iOS, Web, Desktop).

πŸ“Έ Adaptive Media Picker #

Pub.dev Badge Build Badge MIT License Flutter Badge

πŸš€ Adaptive, permission-aware media picker for Flutter
Handles limited & full access gracefully β€” with native-like UX on Android, iOS, Web, and Desktop.

Adaptive Media Picker


✨ Why Adaptive Media Picker? #

Most media pickers only open the gallery or camera β€” but fail when permissions are limited or restricted. adaptive_media_picker is designed to handle every case automatically, making your UX seamless.

πŸ’‘ What makes it different? #

  • βœ… Auto permission handling
  • βœ… Built-in limited-access sheet (for iOS & Android)
  • βœ… Optional image cropping (Android / iOS / Web)
  • βœ… Works seamlessly on Web, Desktop, and Mobile
  • βœ… Single unified API for images & videos

Pick image Pick multiple images Pick video

✨ Built-in limited access bottom sheet UI (native full-access flow on Android/iOS)


πŸš€ Features at a Glance #

Feature Description
πŸ“· Image & Video Picker Pick single/multiple images or single videos
βœ‚οΈ Cropping Optional crop (Android, iOS, Web)
πŸ” Permission-aware Handles full, limited, denied states
🧭 Cross-platform Works on mobile, web, and desktop
πŸ–ΌοΈ Built-in Limited Access UI Native-like bottom sheet
🧩 Fallbacks Smart fallbacks for unsupported platforms
🎯 Web Safe No dart:io β€” works on Flutter Web

⚠️ Multiple video selection is not supported by native APIs.


πŸ—‚οΈ Platform Support Matrix #

Feature Android iOS Web macOS Windows Linux
Single image pick βœ… βœ… βœ… βœ… βœ… βœ…
Multi-image pick βœ… βœ… βœ… βœ… βœ… βœ…
Single video pick βœ… βœ… βœ… βœ… βœ… βœ…
Multiple videos ❌ ❌ ❌ ❌ ❌ ❌
Camera capture βœ… βœ… ❌ ❌ ❌ ❌
Limited-access UX βœ… βœ… ❌ βœ… ❌ ❌
Cropping (single image) βœ… βœ… βœ… ❌ ❌ ❌

⚑ Quick Start #

final picker = AdaptiveMediaPicker();

// Pick a single image
final singleImage = await picker.pickImage(
  context: context,
  options: const PickOptions(source: ImageSource.gallery, imageQuality: 80),
);

// Pick and crop
final croppedImage = await picker.pickImage(
  context: context,
  options: const PickOptions(source: ImageSource.gallery, wantToCrop: true),
);

// Pick multiple images
final multiImages = await picker.pickMultiImage(
  context: context,
  options: const PickOptions(maxImages: 5, source: ImageSource.gallery),
);

// Pick a single video
final singleVideo = await picker.pickVideo(
  context: context,
  options: const PickOptions(source: ImageSource.gallery),
);

🎨 Theming #

Both the built-in limited-access bottom sheet and the optional cropper can follow your app theme or be overridden via PickOptions:

  • Automatic: By default, the package uses Theme.of(context) for surfaces and text.
  • Override: Set these optional fields on PickOptions:
    • themeBrightness: Brightness.light or Brightness.dark
    • primaryColor: the primary accent color (e.g. Colors.blue)

Example:

final result = await picker.pickImage(
  context: context,
  options: const PickOptions(
    wantToCrop: true,
    themeBrightness: Brightness.dark,
    primaryColor: Colors.blue,
  ),
);

Notes:

  • Limited-access bottom sheet inherits your app theme when overrides are not provided.
  • Android cropper toolbar, controls, and grid/frame colors derive from themeBrightness and primaryColor.
  • Web cropper uses the provided context (dialog/page) and will follow your theme colors; primary accent applies to available UI elements.

πŸ“Œ Common Use Cases #

  • πŸ–ΌοΈ Select & crop a profile picture
  • πŸ“Έ Capture or choose multiple images for a gallery/post
  • πŸŽ₯ Pick single video from camera or gallery
  • πŸ” Handle limited access permissions gracefully

βœ‚οΈ Cropping Setup #

Cropping is supported on Android, iOS, and Web.

πŸ“± Android #

Add UCropActivity to your AndroidManifest.xml:

<activity
  android:name="com.yalantis.ucrop.UCropActivity"
  android:screenOrientation="portrait"
  android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>

βœ… Android embedding v2 required

ℹ️ If you enable cropping and build a release APK/AAB (R8/minify), UCrop may reference OkHttp classes. Add these dependencies to your app’s build.gradle(.kts) to avoid missing-class errors (only needed when cropping on Android):

dependencies {
    implementation("com.squareup.okhttp3:okhttp:4.12.0")
    implementation("com.squareup.okio:okio:3.6.0")
}

🍏 iOS #

No additional setup required.

🌐 Web #

Add cropperjs to web/index.html:

<link
  rel="stylesheet"
  href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.6.2/cropper.css"
/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.6.2/cropper.min.js"></script>

πŸ” Limited Access UX #

When the user grants limited access, the picker automatically shows a native-like dialog with options:

  • πŸ“ Manage Selection (iOS only)
  • βš™οΈ Open Settings (iOS/macOS/Android)
  • πŸ•“ Auto-dismisses after interaction

βš™οΈ Permissions Setup #

🧱 Android #

<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_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />

🍎 iOS #

<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs photo library access to pick images.</string>
<key>NSCameraUsageDescription</key>
<string>This app needs camera access to take photos and videos.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app needs microphone access when recording videos.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>This app may save images/videos to your photo library.</string>

πŸ’» macOS #

<key>com.apple.security.files.user-selected.read-only</key>
<true/>

🧩 Desktop platforms use native file dialogs. Camera capture is not supported on desktop.


🧩 API Overview #

Method Description
pickImage() Pick single image (optionally cropped)
pickMultiImage() Pick multiple images
pickVideo() Pick single video

πŸ“˜ Data Models Overview #

🧩 PickOptions #

Configuration options for image/video picking operations.

Field Type Description
maxImages int? Maximum number of images for multi-image pick. Ignored for single image/video.
imageQuality int? JPEG compression quality (0–100).
maxWidth int? Resize width for images when supported.
maxHeight int? Resize height for images when supported.
source ImageSource Source β€” gallery or camera. Falls back to gallery on web/desktop.
showOpenSettingsDialog bool Show β€œOpen Settings” dialog when permission is permanently denied.
settingsDialogTitle String? Custom title for the settings dialog.
settingsDialogMessage String? Custom message for the settings dialog.
settingsButtonLabel String? Label for the confirm button.
cancelButtonLabel String? Label for the cancel button.
wantToCrop bool Enable crop flow (Android/iOS/Web only, single image only).
themeBrightness Brightness? Override theme for limited sheet & cropper (light/dark).
primaryColor Color? Primary accent color for limited sheet & cropper (e.g., blue).
logTag String? Optional debug tag for internal logging.

πŸ–ΌοΈ PickedMedia #

Represents a single picked image or video.

Field Type Description
path String Local file path to the picked media.
mimeType String? MIME type if available.
width int? Image width (when known).
height int? Image height (when known).

🧾 PickResultSingle #

Returned from pickImage() or pickVideo().

Field Type Description
item PickedMedia? Picked item, or null if none.
permissionResolution PermissionResolution Final permission state after operation.
metadata PickMetadata Metadata about crop and sizes.
error PickError? Indicates if operation failed or canceled.

πŸ’‘ Use .isEmpty to check if no item was selected.


🧾 PickResultMultiple #

Returned from pickMultiImage().

Field Type Description
items List<PickedMedia> All picked images. Empty if none.
permissionResolution PermissionResolution Final permission state.

πŸ’‘ Use .isEmpty to check if no images were selected.


🧠 PickMetadata #

Extra info for debugging and analytics.

Field Type Description
cropApplied bool Whether cropping was applied.
originalSize Size? Size before transformations.
finalSize Size? Size after transformations.

⚠️ PickError #

Typed error codes for single-pick operations.

Value Description
canceled User canceled selection.
cropCanceled User canceled cropping.
io I/O or platform failure.
unknown Unknown reason.

πŸ” PermissionResolution #

Represents the final permission outcome.

Field Type Description
granted bool True if any form of access was granted.
limited bool True if access is limited (iOS/Android 14+).
permanentlyDenied bool True if user must change settings manually.

Factories

Factory Description
PermissionResolution.grantedFull() Full access granted.
PermissionResolution.grantedLimited() Limited access granted.
PermissionResolution.denied() Access denied (optionally permanent).

πŸ‘€ Author #

Created with ❀️ by Jaimin Kavathia - πŸ’Ό LinkedIn


πŸ“œ License #

Licensed under the MIT License. Free for personal & commercial use.


⭐ If you like this package, give it a star on GitHub & pub.dev!

11
likes
160
points
495
downloads

Publisher

unverified uploader

Weekly Downloads

Adaptive Flutter media picker for images & videos with smart permissions, limited access UI, and cross-platform support (Android, iOS, Web, Desktop).

Repository (GitHub)
View/report issues

Topics

#image-picker #video-picker #camera #gallery #file-selection

Documentation

API reference

License

MIT (license)

Dependencies

device_info_plus, flutter, image_cropper, image_picker, permission_handler, photo_manager

More

Packages that depend on adaptive_media_picker