or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

albums.mdassets.mdevents.mdindex.mdpermissions.md
tile.json

index.mddocs/

Expo Media Library

Expo Media Library provides comprehensive access to the user's media library for React Native and Expo applications. It enables cross-platform reading, writing, and management of photos, videos, and audio files on iOS, Android, and Web platforms with proper permission handling and platform-specific features.

Package Information

  • Package Name: expo-media-library
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install expo-media-library
  • Peer Dependencies: expo, react-native

Core Imports

import * as MediaLibrary from "expo-media-library";

For individual imports:

import {
  getAssetsAsync,
  createAssetAsync,
  getPermissionsAsync,
  requestPermissionsAsync,
  MediaType,
  SortBy
} from "expo-media-library";

Basic Usage

import * as MediaLibrary from "expo-media-library";

// Request permissions first
const { status } = await MediaLibrary.requestPermissionsAsync();
if (status !== 'granted') {
  console.log('Permission not granted');
  return;
}

// Get recent photos
const photos = await MediaLibrary.getAssetsAsync({
  mediaType: MediaLibrary.MediaType.photo,
  first: 20,
  sortBy: [MediaLibrary.SortBy.creationTime, false],
});

// Save a new asset
const asset = await MediaLibrary.createAssetAsync('file:///path/to/image.jpg');

// Create an album
const album = await MediaLibrary.createAlbumAsync('My Photos', asset);

Architecture

Expo Media Library is designed as a cross-platform Expo module with several key components:

  • Permission System: Granular permission management with support for iOS limited access and Android 13+ granular permissions
  • Asset Management: CRUD operations for photos, videos, and audio files with metadata access
  • Album Management: Create, delete, and manage albums with cross-platform compatibility
  • Event System: Real-time notifications for media library changes
  • Platform Bridge: Native implementations in Swift (iOS) and Kotlin/Java (Android) with web fallback

Core Constants

const MediaType: {
  readonly audio: 'audio';
  readonly photo: 'photo';
  readonly video: 'video';
  readonly unknown: 'unknown';
};

const SortBy: {
  readonly default: 'default';
  readonly mediaType: 'mediaType';
  readonly width: 'width';
  readonly height: 'height';
  readonly creationTime: 'creationTime';
  readonly modificationTime: 'modificationTime';
  readonly duration: 'duration';
};

Capabilities

API Availability and Permission Management

Comprehensive permission system supporting iOS limited access, Android 13+ granular permissions, system permission picker integration, and React hooks for state management.

function isAvailableAsync(): Promise<boolean>;

function getPermissionsAsync(
  writeOnly?: boolean,
  granularPermissions?: GranularPermission[]
): Promise<PermissionResponse>;

function requestPermissionsAsync(
  writeOnly?: boolean,
  granularPermissions?: GranularPermission[]
): Promise<PermissionResponse>;

function presentPermissionsPickerAsync(
  mediaTypes?: MediaTypeFilter[]
): Promise<void>;

const usePermissions: (
  options?: { writeOnly?: boolean; granularPermissions?: GranularPermission[] }
) => [
  PermissionResponse | null,
  () => Promise<PermissionResponse>,
  () => Promise<PermissionResponse>
];

Permission Management

Asset Management

Core asset operations including creating, querying, retrieving detailed information, saving, and deleting media assets with comprehensive metadata support.

function getAssetsAsync(
  assetsOptions: AssetsOptions = {}
): Promise<PagedInfo<Asset>>;

function createAssetAsync(
  localUri: string,
  album?: AlbumRef
): Promise<Asset>;

function saveToLibraryAsync(localUri: string): Promise<void>;

function getAssetInfoAsync(
  asset: AssetRef,
  options?: MediaLibraryAssetInfoQueryOptions
): Promise<AssetInfo>;

function deleteAssetsAsync(
  assets: AssetRef[] | AssetRef
): Promise<boolean>;

Asset Management

Album Management

Album creation, management, and asset organization with support for both user-created and smart albums (iOS).

function getAlbumsAsync(
  options?: AlbumsOptions
): Promise<Album[]>;

function getAlbumAsync(title: string): Promise<Album>;

function createAlbumAsync(
  albumName: string,
  asset?: AssetRef,
  copyAsset?: boolean,
  initialAssetLocalUri?: string
): Promise<Album>;

function deleteAlbumsAsync(
  albums: AlbumRef[] | AlbumRef,
  assetRemove?: boolean
): Promise<boolean>;

function addAssetsToAlbumAsync(
  assets: AssetRef[] | AssetRef,
  album: AlbumRef,
  copy?: boolean
): Promise<boolean>;

function removeAssetsFromAlbumAsync(
  assets: AssetRef[] | AssetRef,
  album: AlbumRef
): Promise<boolean>;

function getMomentsAsync(): Promise<Album[]>;

function migrateAlbumIfNeededAsync(album: AlbumRef): Promise<void>;

function albumNeedsMigrationAsync(album: AlbumRef): Promise<boolean>;

Album Management

Event Listeners

Real-time media library change notifications with incremental update support for efficient UI updates.

function addListener(
  listener: (event: MediaLibraryAssetsChangeEvent) => void
): EventSubscription;

function removeSubscription(subscription: EventSubscription): void;

function removeAllListeners(): void;

Event Listeners

Core Types

type MediaTypeValue = 'audio' | 'photo' | 'video' | 'unknown' | 'pairedVideo';

type GranularPermission = 'audio' | 'photo' | 'video';

type MediaTypeFilter = 'photo' | 'video';

type SortByValue = [SortByKey, boolean] | SortByKey;

type AssetRef = Asset | string;

type AlbumRef = Album | string;

interface PermissionResponse extends EXPermissionResponse {
  accessPrivileges?: 'all' | 'limited' | 'none';
}

interface Asset {
  id: string;
  filename: string;
  uri: string;
  mediaType: MediaTypeValue;
  mediaSubtypes?: MediaSubtype[];
  width: number;
  height: number;
  creationTime: number;
  modificationTime: number;
  duration: number;
  albumId?: string;
}

interface Album {
  id: string;
  title: string;
  assetCount: number;
  type?: AlbumType;
  startTime: number;
  endTime: number;
  approximateLocation?: Location;
  locationNames?: string[];
}

interface PagedInfo<T> {
  assets: T[];
  endCursor: string;
  hasNextPage: boolean;
  totalCount: number;
}

Re-exported Types

// Re-exported from expo-modules-core
type PermissionStatus = 'granted' | 'denied' | 'undetermined' | 'restricted';

type PermissionExpiration = 'never' | number;

interface EXPermissionResponse {
  status: PermissionStatus;
  expires: PermissionExpiration;
  granted: boolean;
  canAskAgain: boolean;
}

interface PermissionHookOptions<T> {
  request?: () => Promise<T>;
  get?: () => Promise<T>;
}

interface EventSubscription {
  remove(): void;
}

// EventSubscription is also exported as 'Subscription'
type Subscription = EventSubscription;

Platform Support

  • iOS: Full feature support including Live Photos, moments, smart albums, and limited access permissions
  • Android: Full support with scoped storage migration (Android R+) and granular permissions (Android 13+)
  • Web: Limited web implementation available

Permission Requirements

  • iOS: NSPhotoLibraryUsageDescription, NSPhotoLibraryAddUsageDescription in Info.plist
  • Android: READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE, optional ACCESS_MEDIA_LOCATION in AndroidManifest.xml