Provides access to user's media library for React Native and Expo applications.
npx @tessl/cli install tessl/npm-expo-media-library@18.0.0Expo 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.
npm install expo-media-libraryexpo, react-nativeimport * as MediaLibrary from "expo-media-library";For individual imports:
import {
getAssetsAsync,
createAssetAsync,
getPermissionsAsync,
requestPermissionsAsync,
MediaType,
SortBy
} from "expo-media-library";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);Expo Media Library is designed as a cross-platform Expo module with several key components:
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';
};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>
];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>;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>;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;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 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;NSPhotoLibraryUsageDescription, NSPhotoLibraryAddUsageDescription in Info.plistREAD_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE, optional ACCESS_MEDIA_LOCATION in AndroidManifest.xml