CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-expo-image-picker

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
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

media-selection.mddocs/

Media Selection

Core functions for capturing images and videos with the device camera or selecting media from the device's photo library.

Capabilities

Launch Camera

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:

  • Web: Must be called immediately in a user interaction (button press) or browser will block
  • Android: Handle MainActivity destruction using getPendingResultAsync
  • iOS: Requires camera permissions and media library permissions on iOS 10

Usage 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]);
  }
};

Launch Image Library

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:

  • Web: Must be called immediately in a user interaction (button press) or browser will block
  • Android: Animated GIFs preserved only with quality: 1.0 and allowsEditing: false
  • iOS: Supports GIF quality and cropping

Usage 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);
    }
  }
};

Get Pending Result

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:

  • Android: Returns the lost ImagePicker result if MainActivity was destroyed
  • Other platforms: Always returns null

Usage 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();
}, []);

Result Types

// 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
}

docs

configuration.md

index.md

media-selection.md

permissions.md

tile.json