Provides access to the system's UI for selecting images and videos from the phone's library or taking a photo with the camera.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Core functions for capturing images and videos with the device camera or selecting media from the device's photo library.
Display the system UI for taking a photo with the camera. Requires camera permissions and media library permissions on iOS 10.
/**
* Display the system UI for taking a photo with the camera.
* @param options Configuration options for camera capture
* @returns Promise resolving to ImagePickerResult with captured media or cancellation
*/
function launchCameraAsync(options?: ImagePickerOptions): Promise<ImagePickerResult>;Platform Notes:
getPendingResultAsyncUsage Example:
import * as ImagePicker from 'expo-image-picker';
const takePicture = async () => {
// Check permissions first
const { status } = await ImagePicker.requestCameraPermissionsAsync();
if (status !== 'granted') {
alert('Camera permission is required!');
return;
}
// Launch camera
const result = await ImagePicker.launchCameraAsync({
mediaTypes: 'images',
allowsEditing: true,
aspect: [1, 1],
quality: 0.8,
});
if (!result.canceled) {
console.log('Photo taken:', result.assets[0]);
}
};Display the system UI for choosing media from the phone's library. Requires media library permissions on iOS 10 only.
/**
* Display the system UI for choosing an image or video from the phone's library.
* @param options Configuration options for media selection
* @returns Promise resolving to ImagePickerResult with selected media or cancellation
*/
function launchImageLibraryAsync(options?: ImagePickerOptions): Promise<ImagePickerResult>;Platform Notes:
quality: 1.0 and allowsEditing: falseUsage Examples:
import * as ImagePicker from 'expo-image-picker';
// Single image selection
const pickImage = async () => {
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: 'images',
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
if (!result.canceled) {
console.log('Selected image:', result.assets[0].uri);
}
};
// Multiple selection
const pickMultipleImages = async () => {
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: 'images',
allowsMultipleSelection: true,
selectionLimit: 5,
quality: 0.8,
});
if (!result.canceled) {
console.log(`Selected ${result.assets.length} images`);
result.assets.forEach((asset, index) => {
console.log(`Image ${index + 1}:`, asset.uri);
});
}
};
// Video selection with editing
const pickVideo = async () => {
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: 'videos',
allowsEditing: true,
videoQuality: ImagePicker.UIImagePickerControllerQualityType.Medium,
});
if (!result.canceled) {
const video = result.assets[0];
console.log('Selected video:', video.uri);
console.log('Duration:', video.duration, 'ms');
}
};
// Live Photos (iOS only)
const pickLivePhoto = async () => {
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ['images', 'livePhotos'],
quality: 1,
});
if (!result.canceled) {
const asset = result.assets[0];
if (asset.type === 'livePhoto' && asset.pairedVideoAsset) {
console.log('Live photo image:', asset.uri);
console.log('Paired video:', asset.pairedVideoAsset.uri);
}
}
};Retrieve lost data on Android when MainActivity is destroyed after ImagePicker finishes.
/**
* Android system sometimes kills the MainActivity after ImagePicker finishes.
* This function retrieves the lost data from a previous picker operation.
* @returns Promise resolving to the previous ImagePicker result or null
*/
function getPendingResultAsync(): Promise<ImagePickerResult | ImagePickerErrorResult | null>;Platform Notes:
nullUsage Example:
import * as ImagePicker from 'expo-image-picker';
import { AppState } from 'react-native';
// Check for pending result when app becomes active
useEffect(() => {
const handleAppStateChange = async (nextAppState: string) => {
if (nextAppState === 'active') {
const pendingResult = await ImagePicker.getPendingResultAsync();
if (pendingResult && !pendingResult.canceled) {
// Handle the recovered result
console.log('Recovered result:', pendingResult.assets);
}
}
};
const subscription = AppState.addEventListener('change', handleAppStateChange);
return () => subscription?.remove();
}, []);// Main result type
type ImagePickerResult = ImagePickerSuccessResult | ImagePickerCanceledResult;
interface ImagePickerSuccessResult {
canceled: false;
assets: ImagePickerAsset[];
}
interface ImagePickerCanceledResult {
canceled: true;
assets: null;
}
// Error result (from getPendingResultAsync)
interface ImagePickerErrorResult {
code: string;
message: string;
exception?: string;
}
// Asset information
interface ImagePickerAsset {
uri: string;
width: number;
height: number;
type?: 'image' | 'video' | 'livePhoto' | 'pairedVideo';
assetId?: string | null;
fileName?: string | null;
fileSize?: number;
base64?: string | null;
exif?: Record<string, any> | null;
duration?: number | null;
mimeType?: string;
pairedVideoAsset?: ImagePickerAsset | null; // iOS Live Photos
file?: File; // Web only
}