Skip to content

james-codersHT/ImagePickerKMP

 
 

CI Code Coverage License Kotlin

Platform Maven Central GitHub Release GitHub Repo stars

GitHub last commit PRs Welcome Discord

Compose Multiplatform Android iOS Coverage Status Detekt


ImagePickerKMP

Cross‑platform Image Picker & Camera Library (Android & iOS)
Built with Kotlin Multiplatform + Compose Multiplatform + Kotlin/Native

EspañolGitHubMaven CentralDiscord


Demo Android And IOS

Demo ImagePickerKMP


About ImagePickerKMP

  • Cross-platform: Works seamlessly on Android and iOS
  • Camera Integration: Direct camera access with photo capture
  • Customizable UI: Custom dialogs and confirmation views
  • Permission Handling: Smart permission management for both platforms
  • Easy Integration: Simple API with Compose Multiplatform
  • Highly Configurable: Extensive customization options

Quick Start – Kotlin Multiplatform Image Picker Integration

Installation

Using ImagePickerKMP in Kotlin Multiplatform / Compose Multiplatform

Step 1: Add the dependency

In your commonMain build.gradle.kts:

dependencies {
    implementation("io.github.ismoy:imagepickerkmp:1.0.21")//lastversion
}

iOS Permissions Setup

Don't forget to configure iOS-specific permissions in your Info.plist file:

<key>NSCameraUsageDescription</key>
<string>We need access to the camera to capture a photo.</string>

Step 2: Launch the Camera

 var showCamera by remember { mutableStateOf(false) }
 var capturedPhoto by remember { mutableStateOf<CameraPhotoHandler.PhotoResult?>(null) }
if (showCamera) {
    ImagePickerLauncher(
        config = ImagePickerConfig(
            onPhotoCaptured = { result ->
                capturedPhoto = result
                showCamera = false
            },
            onError = {
                showCamera = false
            },
            onDismiss = { 
                showImagePicker = false // Reset state when user doesn't select anything
            },
            // Custom dialog only IOS optional delete it for use default UI
            customPickerDialog = { onTakePhoto, onSelectFromGallery, onCancel ->
                MyCustomBottomSheet(
                    onTakePhoto = onTakePhoto,
                    onSelectFromGallery = onSelectFromGallery,
                    onDismiss = {
                        isPickerSheetVisible = false
                        onCancel()
                        showCameraPicker = false
                    }
                )
            },
            // Only Android optional delete it for use default UI
            cameraCaptureConfig = CameraCaptureConfig(
                permissionAndConfirmationConfig = PermissionAndConfirmationConfig(
                    customConfirmationView = { photoResult, onConfirm, onRetry ->
                        YourCustomConfirmationView(
                            result = photoResult,
                            onConfirm = onConfirm,
                            onRetry = onRetry
                        )
                    },
                    // Optional: custom permission handler delete it for use default UI
                    customPermissionHandler = { config ->
                        // Handle permissions here
                    }
                )
            )
        )
    )
}

Step 3: Pick from the Gallery

var showGallery by remember { mutableStateOf(false) }
var selectedImages by remember { mutableStateOf<List<GalleryPhotoHandler.PhotoResult>>(emptyList()) }
if (showGallery) {
    GalleryPickerLauncher(
        onPhotosSelected = { photos ->
            selectedImages = photos
            showGallery = false
        },
        onError = { error ->
            showGallery = false
        },
        onDismiss = { 
            println("User cancelled or dismissed the picker")
            showGallery = false // Reset state when user doesn't select anything
        }
        allowMultiple = true, // False for single selection
        mimeTypes = listOf("image/jpeg", "image/png") ,// Optional: filter by type
        // Only Android optional delete it for use default UI
        cameraCaptureConfig = CameraCaptureConfig(
            permissionAndConfirmationConfig = PermissionAndConfirmationConfig(
                customConfirmationView = { photoResult, onConfirm, onRetry ->
                    YourCustomConfirmationView(
                        result = photoResult,
                        onConfirm = onConfirm,
                        onRetry = onRetry
                    )
                }
            )
        )
    )
}

Button(onClick = { showGallery = true }) {
    Text("Choose from Gallery")
}

For more customization (confirmation views, MIME filtering, etc.), check out the integration guide for KMP.

Using ImagePickerKMP in Android Native (Jetpack Compose)

Even if you're not using KMP, you can use ImagePickerKMP in pure Android projects with Jetpack Compose.

Step 1: Add the dependency

implementation("io.github.ismoy:imagepickerkmp:1.0.21")

Step 2: Camera Launcher Example

var showCamera by remember { mutableStateOf(false) }
var capturedPhoto by remember { mutableStateOf<CameraPhotoHandler.PhotoResult?>(null) }
if (showCamera) {
    ImagePickerLauncher(
        config = ImagePickerConfig(
            onPhotoCaptured = { result ->
                capturedPhoto = result
                showCamera = false
            },
            onError = {
                showCamera = false
            },
            onDismiss = {
                showImagePicker = false // Reset state when user doesn't select anything
            },
            // Custom dialog only IOS optional delete it for use default UI
            customPickerDialog = { onTakePhoto, onSelectFromGallery, onCancel ->
                MyCustomBottomSheet(
                    onTakePhoto = onTakePhoto,
                    onSelectFromGallery = onSelectFromGallery,
                    onDismiss = {
                        isPickerSheetVisible = false
                        onCancel()
                        showCameraPicker = false
                    }
                )
            },
            // Only Android optional delete it for use default UI
            cameraCaptureConfig = CameraCaptureConfig(
                permissionAndConfirmationConfig = PermissionAndConfirmationConfig(
                    customConfirmationView = { photoResult, onConfirm, onRetry ->
                        YourCustomConfirmationView(
                            result = photoResult,
                            onConfirm = onConfirm,
                            onRetry = onRetry
                        )
                    },
                    // Optional: custom permission handler delete it for use default UI
                    customPermissionHandler = { config ->
                        // Handle permissions here
                    }
                )
            )
        )
    )
}

Button(onClick = { showCamera = true }) {
    Text("Take Photo")
}

Step 3: Gallery Picker Example

var showGallery by remember { mutableStateOf(false) }
var selectedImages by remember { mutableStateOf<List<GalleryPhotoHandler.PhotoResult>>(emptyList()) }
if (showGallery) {
    GalleryPickerLauncher(
        onPhotosSelected = { photos ->
            selectedImages = photos
            showGallery = false
        },
        onError = { error ->
            showGallery = false
        },
        onDismiss = {
            showCamera = false
           },
        allowMultiple = true, // False for single selection
        mimeTypes = listOf("image/jpeg", "image/png"), // Optional: filter by type
        // Only Android optional 
        cameraCaptureConfig = CameraCaptureConfig(
            permissionAndConfirmationConfig = PermissionAndConfirmationConfig(
                customConfirmationView = { photoResult, onConfirm, onRetry ->
                    YourCustomConfirmationView(
                        result = photoResult,
                        onConfirm = onConfirm,
                        onRetry = onRetry
                    )
                }
            )
        )
    )
}

Button(onClick = { showGallery = true }) {
    Text("Choose from Gallery")
}

See the Android Native integration guide for more usage details.

  • On Android, the user will see the system gallery picker.
  • On iOS, the native gallery picker is used. On iOS 14+, multiple selection is supported. The system handles permissions and limited access natively.
  • The callback onPhotosSelected always receives a list, even for single selection.
  • You can use allowMultiple to enable or disable multi-image selection.
  • The mimeTypes parameter is optional and lets you filter selectable file types.

GalleryPickerLauncher Dismiss Fix

The GalleryPickerLauncher now includes an onDismiss callback to handle cases where users dismiss the picker without selecting any images. This resolves the issue where the picker couldn't be reopened after being dismissed.

The onDismiss callback is triggered when:

  • User cancels the selection dialog (Android)
  • User taps "Cancel" (iOS)
  • User cancels camera permission request (iOS)
  • User cancels the camera interface (taps "Cancel" or "X") (iOS)

Platform Support

Cross-platform compatibility with intelligent context management

  • Android: The library automatically manages the context using LocalContext.current. No need to pass context manually.
  • iOS: Context is not required as the library uses native iOS APIs.
Platform Minimum Version Status
Android API 21+
iOS iOS 12.0+
Compose Multiplatform 1.5.0+

Why Choose ImagePickerKMP?

The most comprehensive and developer-friendly image picker for Kotlin Multiplatform

Comparison with Other Libraries

Feature ImagePickerKMP Peekaboo KMPImagePicker
Compose Multiplatform Support ✅ Native ❌ Android only ⚠️ Limited
UI Customization ✅ Full control ⚠️ Basic ⚠️ Basic
Unified Permissions ✅ Smart handling ❌ Manual ⚠️ Platform-specific
Error Handling ✅ Comprehensive ⚠️ Basic ⚠️ Basic
Camera Integration ✅ Direct access ✅ Direct access ⚠️ Gallery only
Gallery Support ✅ Multi-select ✅ Multi-select ✅ Multi-select
Cross-platform API ✅ Single codebase ❌ Platform-specific ⚠️ Partial

Key Advantages

  • ** Compose Multiplatform Native**: Built specifically for Compose Multiplatform, ensuring consistent behavior across platforms
  • ** Full UI Customization**: Complete control over dialogs, confirmation views, and camera UI
  • ** Smart Permission Management**: Unified permission handling with intelligent fallbacks
  • ** Performance Optimized**: Efficient image processing and memory management
  • ** Developer Friendly**: Simple API with comprehensive error handling

Requirements

Android

  • Minimum SDK: 21
  • Kotlin 1.8+
  • Compose Multiplatform

iOS

  • iOS 12.0+
  • Xcode 14+
  • Kotlin Multiplatform

Platform-Specific Integration

Android Native (Jetpack Compose)

For detailed Android integration guide, see: Android Integration Guide

iOS Native (Swift/SwiftUI)

For detailed iOS integration guide, see: iOS Integration Guide

Kotlin Multiplatform/Compose Multiplatform

For detailed KMP integration guide, see: Kotlin Multiplatform Integration Guide

Documentation

Comprehensive guides and references for every aspect of ImagePickerKMP

Contributing

We welcome contributions from the community!
See our Contributing Guide for details.


License

This project is licensed under the MIT License
See the LICENSE file for details.


Support & Community

Get help, report issues, or join our community

📧 Email🐛 Issues📖 Wiki💬 Discord

Changelog

See CHANGELOG.md for a complete list of changes and updates.


Made with ❤️ for the Kotlin Multiplatform community
Star ⭐ this repo if it helped you!

⭐ Star on GitHub🍴 Fork🐛 Report Bug💡 Request Feature

About

ImagePickerKMP – Cross‑platform Image Picker & Camera Library (Android & iOS) built with Kotlin Multiplatform + Compose Multiplatform.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • Kotlin 100.0%