Provides access to user's media library for React Native and Expo applications.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
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.
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