🎥 Demo Android And IOS
Watch the demo above to see ImagePickerKMP in action - camera capture, gallery selection, and custom UI in action!
📱 Demo Features Showcased:
- 📸 Camera Capture: Direct camera access with flash control
- 🔄 Camera Switching: Seamless front/back camera toggle
- 🎨 Custom UI: Personalized confirmation dialogs
- 📁 Gallery Selection: Multi-image selection from gallery
- ⚡ Performance: Smooth, responsive interactions
- 🔒 Permissions: Smart permission handling
ImagePickerKMP
Cross‑platform Image Picker & Camera Library (Android & iOS)
Built with Kotlin Multiplatform + Compose Multiplatform + Kotlin/Native.
Este documento también está disponible en español: README.es.md
Features – Camera, Image Picker & Gallery for Android & iOS
- 📱 Cross-platform: Works 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
Add the dependency to your build.gradle.kts:
dependencies {
implementation("io.github.ismoy:imagepickerkmp:1.0.1")
}
Basic Usage
@Composable
fun MyImagePicker() {
var showImagePicker by remember { mutableStateOf(false) }
var capturedImage by remember { mutableStateOf<PhotoResult?>(null) }
if (showImagePicker) {
ImagePickerLauncher(
context = LocalContext.current,
config = ImagePickerConfig(
onPhotoCaptured = { result ->
// Handle captured photo
capturedImage = result
showImagePicker = false
},
onError = { exception ->
// Handle errors
showImagePicker = false
}
)
)
}
Button(onClick = { showImagePicker = true }) {
Text("Take Photo")
}
}
💡 Real-World Use Case
Here's a practical example showing camera capture with preview and upload:
@Composable
fun AdvancedImagePicker() {
var showPicker by remember { mutableStateOf(false) }
var capturedImage by remember { mutableStateOf<PhotoResult?>(null) }
var isUploading by remember { mutableStateOf(false) }
if (showPicker) {
ImagePickerLauncher(
context = LocalContext.current,
config = ImagePickerConfig(
onPhotoCaptured = { result ->
capturedImage = result
showPicker = false
uploadImage(result)
},
onError = { exception ->
showPicker = false
// Custom error handling here
},
cameraCaptureConfig = CameraCaptureConfig(
permissionAndConfirmationConfig = PermissionAndConfirmationConfig(
customConfirmationView = { result, onConfirm, onRetry ->
ImageConfirmationViewWithCustomButtons(
result = result,
onConfirm = onConfirm,
onRetry = onRetry,
questionText = "Use this photo?",
retryText = "Retake",
acceptText = "Use Photo"
)
}
)
)
)
)
}
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
// Display captured image
capturedImage?.let { photo ->
AsyncImage(
model = photo.uri,
contentDescription = "Captured photo",
modifier = Modifier
.size(200.dp)
.clip(RoundedCornerShape(8.dp))
)
if (isUploading) {
CircularProgressIndicator()
Text("Uploading...")
}
}
Button(
onClick = { showPicker = true },
enabled = !isUploading
) {
Icon(Icons.Default.Camera, contentDescription = null)
Spacer(Modifier.width(8.dp))
Text("Take Photo")
}
}
}
private fun uploadImage(photoResult: PhotoResult) {
// Example upload implementation
lifecycleScope.launch(Dispatchers.IO) {
try {
// Upload logic here
withContext(Dispatchers.Main) {
// Show success message
}
} catch (e: Exception) {
withContext(Dispatchers.Main) {
// Show error message
}
}
}
}
Gallery Picker Usage
You can also allow users to pick images directly from the gallery:
Note: You do not need to request gallery permissions manually. The library automatically handles permission requests and user flows for both Android and iOS, providing a native experience on each platform.
@Composable
fun MyGalleryPicker() {
var showGalleryPicker by remember { mutableStateOf(false) }
var selectedImages by remember { mutableStateOf<List<PhotoResult>>(emptyList()) }
if (showGalleryPicker) {
GalleryPickerLauncher(
context = LocalContext.current, // Android only; ignored on iOS
onPhotosSelected = { results ->
selectedImages = results
showGalleryPicker = false
},
onError = { exception ->
// Handle errors
showGalleryPicker = false
},
allowMultiple = true // or false for single selection
// mimeTypes = listOf("image/jpeg", "image/png") // Optional: filter by type
)
}
Button(onClick = { showGalleryPicker = true }) {
Text("Pick from Gallery")
}
}
- On Android, the user will see the system gallery picker, and permissions are requested automatically if needed.
- 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
onPhotosSelectedalways receives a list, even for single selection. - You can use
allowMultipleto enable or disable multi-image selection. - The
mimeTypesparameter is optional and lets you filter selectable file types.
Platform Support
| Platform | Minimum Version | Status |
|---|---|---|
| Android | API 21+ | ✅ |
| iOS | iOS 12.0+ | ✅ |
| Compose Multiplatform | 1.5.0+ | ✅ |
Why Choose ImagePickerKMP?
🆚 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
- Integration Guide - Complete setup and integration guide
- Customization Guide - UI and behavior customization
- Internationalization Guide - Multi-language support guide
- Permissions Guide - Permission handling details
- Coverage Guide - Code coverage and testing guide
- Notifications Setup - Discord notifications setup
- API Reference - Complete API documentation
- Examples - Code examples and use cases
Contributing
We welcome contributions! See our Contributing Guide for details.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
- 📧 Email: belizairesmoy72@gmail.com
- 🐛 Issues: GitHub Issues
- 📖 Documentation: Wiki
- 💬 Discord: Community Channel
Changelog
See CHANGELOG.md for a complete list of changes and updates.
Made with ❤️ for the Kotlin Multiplatform community
Built With
- kotlin

Log in or sign up for Devpost to join the conversation.