rns-mediapicker
v3.0.0
Published
High-performance React Native module for picking media on Android and iOS.
Maintainers
Readme
🎵 / 🖼️ / 🎥 rns-mediapicker
A high-performance native media picker for React Native and Expo.
Supports audio, image, video, .adp project files from camera or library, automatic JPEG compression, EXIF-safe dimensions, and iterative quality targeting.
🚀 Installation
Choose any method:
yarn add rns-mediapickernpm install rns-mediapickernpx expo install rns-mediapicker⚙️ Expo Configuration
Add the plugin to your app.json or app.config.js.
This automatically configures:
- iOS permissions (
Info.plist) - iOS
.adpcustom UTType declaration - Android intent queries
- Android
FileProvider
{
"expo": {
"plugins": ["rns-mediapicker"]
}
}🧑💻 Usage
Pick from library (image or video)
import MediaPicker from 'rns-mediapicker';
const result = await MediaPicker.pick(
false, // useCamera
'both', // mediaType
'back', // env
0 // targetKB — 0 means no compression
);
console.log(result.uri); // file:///...
console.log(result.type); // 'image' | 'video' | 'audio' | 'adp'
console.log(result.width); // number (0 for audio/adp)
console.log(result.height); // number (0 for audio/adp)
console.log(result.size); // KB (images only — field is absent for video/audio/adp)
console.log(result.isVideo);
console.log(result.isAudio);Open camera
// Photo with back camera
const result = await MediaPicker.pick(true, 'image', 'back', 0);
// Video with front camera
const result = await MediaPicker.pick(true, 'video', 'front', 0);Pick audio
const result = await MediaPicker.pick(false, 'audio', 'back', 0);
console.log(result.uri); // file:///...
console.log(result.type); // 'audio'
console.log(result.isAudio); // truePick with image compression (targetKB)
Compresses the image iteratively until it fits within the target size.
Quality steps down by 10% per iteration (from 100% → minimum 10%).
// Pick an image and compress to max 200KB
const result = await MediaPicker.pick(false, 'image', 'back', 200);
console.log(result.size); // Actual size in KB after compression
console.log(result.uri); // Compressed JPEG file URI
targetKB = 0disables compression and returns the full-quality image.
Pick a .adp project file
.adp is a custom Audipella project file format. This opens the file browser
filtered to .adp files only (iOS) or a general file browser (Android).
const result = await MediaPicker.pick(false, 'adp', 'back', 0);
console.log(result.uri); // file:///...path/to/file.adp
console.log(result.type); // 'adp'Error handling
try {
const result = await MediaPicker.pick(false, 'image', 'back', 0);
} catch (error) {
switch (error.code) {
case 'E_CANCELLED':
console.log('User cancelled');
break;
case 'E_PERMISSION_DENIED':
console.log('Permission denied');
break;
case 'E_CAMERA_UNAVAILABLE':
console.log('Camera not available on this device');
break;
case 'E_PROCESS':
console.log('Failed to process media:', error.message);
break;
default:
console.error('Picker error:', error.message);
}
}🧩 API Reference
pick(useCamera, mediaType, env, targetKB)
| Parameter | Type | Default | Description |
|-------------|----------|------------|-------------|
| useCamera | boolean | — | true opens the camera, false opens the file/media picker |
| mediaType | string | — | 'image', 'video', 'both', 'audio', or 'adp' |
| env | string | 'back' | 'front' or 'back' — camera only, best-effort on Android |
| targetKB | number | 0 | Max image size in KB. 0 = no compression. Images only |
All four parameters must be passed. Use 0 for targetKB to disable compression, and 'back' for env when camera direction is not relevant.
📦 Response Object
{
uri: string; // Local file URI (file://...)
width: number; // Width in pixels (0 for audio and adp)
height: number; // Height in pixels (0 for audio and adp)
size?: number; // File size in KB — present for images only, absent for video/audio/adp
type: 'image' | 'video' | 'audio' | 'adp';
isVideo: boolean;
isAudio: boolean;
}🗂️ Media Type Reference
| mediaType | Opens | Returns |
|-------------|-------|---------|
| 'image' | Photo library / camera | type: 'image' |
| 'video' | Video library / camera | type: 'video' |
| 'both' | Photo + video library / camera | type: 'image' or 'video' |
| 'audio' | File browser (audio files) | type: 'audio' |
| 'adp' | File browser (.adp files on iOS; all files on Android) | type: 'adp' |
🚨 Error Codes
| Code | Description |
|------|-------------|
| E_CANCELLED | User dismissed the picker or cancelled |
| E_PERMISSION_DENIED | Camera or storage permission denied |
| E_NOT_PERMISSION_AWARE | Android activity does not implement PermissionAwareActivity |
| E_CAMERA_UNAVAILABLE | Device has no camera (iOS) |
| E_NO_ACTIVITY | Android activity not found |
| E_NO_URI | No media URI returned from picker |
| E_PROCESS | Failed to decode, compress, or copy the file |
| E_AUDIO_COPY | Failed to copy audio/adp file to temp location |
| E_VIDEO_COPY | Failed to copy video file to temp location |
| E_IMAGE_WRITE | Failed to encode or write image to disk |
| E_LOAD | Failed to load media from PHPicker (iOS) |
✨ Features
- 🖼️ Image / 🎥 Video / 🎵 Audio / 📁
.adpproject file support - 📷 Camera and 📁 Library selection
- 🎬 Camera video capture (Android & iOS)
- 🗜️ Iterative JPEG compression with
targetKBtarget - 🔄 EXIF-safe rotation and accurate dimensions
- 📂 Scoped-storage safe temporary files
- 🤖 Android 11+ intent queries handled automatically
- 🔐 Android
FileProviderpreconfigured - 🍎 iOS swipe-to-dismiss cancellation handling
- 🍎 iOS
.adpUTType auto-registered via Expo plugin - 🧹 Clean promise lifecycle (no leaks)
📝 Notes
- All returned files are copied into the app's temporary cache directory
- Audio files preserve their original encoding and extension
.adpfiles are copied as-is — no processing appliedtargetKBcompression only applies to images, not video or audio- The
sizefield is only present in the response for images; it is absent (not0) for video, audio, and adp results - Front camera selection is best-effort on Android
- On Android,
.adppicker opens a general file browser since Android has no built-in MIME type for.adp; the file is identified by its extension after selection - No external native dependencies required
📄 License
MIT
