Core asset operations for creating, querying, retrieving detailed information, and deleting media assets with comprehensive metadata support including EXIF data, GPS location, and platform-specific features.
Fetches paginated assets from the media library with comprehensive filtering and sorting options.
/**
* Fetches paginated assets matching specified criteria
* @param assetsOptions - Options for filtering, sorting, and pagination (optional)
* @returns Promise resolving to PagedInfo containing assets and pagination data
*/
function getAssetsAsync(assetsOptions: AssetsOptions = {}): Promise<PagedInfo<Asset>>;
interface AssetsOptions {
/** Maximum number of assets to return per page (default: 20) */
first?: number;
/** Pagination cursor - asset or asset ID to start after */
after?: AssetRef;
/** Filter by specific album */
album?: AlbumRef;
/** Sort criteria - single value or array for multiple sort keys */
sortBy?: SortByValue[] | SortByValue;
/** Filter by media type(s) */
mediaType?: MediaTypeValue[] | MediaTypeValue;
/** Filter by media subtype(s) - iOS only */
mediaSubtypes?: MediaSubtype[] | MediaSubtype;
/** Filter assets created after this date */
createdAfter?: Date | number;
/** Filter assets created before this date */
createdBefore?: Date | number;
/** Resolve with full asset info on Android (slower but more complete) */
resolveWithFullInfo?: boolean;
}
interface PagedInfo<T> {
/** Array of assets for current page */
assets: T[];
/** Cursor for retrieving next page */
endCursor: string;
/** Whether more pages are available */
hasNextPage: boolean;
/** Estimated total count of matching assets */
totalCount: number;
}Usage Examples:
import * as MediaLibrary from "expo-media-library";
// Get recent photos
const photos = await MediaLibrary.getAssetsAsync({
mediaType: MediaLibrary.MediaType.photo,
first: 20,
sortBy: [MediaLibrary.SortBy.creationTime, false], // Most recent first
});
// Get videos from specific album
const album = await MediaLibrary.getAlbumAsync('My Videos');
const videos = await MediaLibrary.getAssetsAsync({
album: album,
mediaType: MediaLibrary.MediaType.video,
first: 10,
});
// Get assets with date range filtering
const lastWeek = new Date();
lastWeek.setDate(lastWeek.getDate() - 7);
const recentAssets = await MediaLibrary.getAssetsAsync({
createdAfter: lastWeek,
sortBy: MediaLibrary.SortBy.creationTime,
first: 50,
});
// Pagination example
let allAssets = [];
let hasNext = true;
let cursor = undefined;
while (hasNext) {
const result = await MediaLibrary.getAssetsAsync({
first: 100,
after: cursor,
mediaType: MediaLibrary.MediaType.photo,
});
allAssets.push(...result.assets);
hasNext = result.hasNextPage;
cursor = result.endCursor;
}Creates a new asset in the media library from an existing local file, commonly used to save camera photos.
/**
* Creates asset from existing file, commonly used to save Camera photos
* @param localUri - Local file path/URI with proper file extension
* @param album - Album or album ID to add the asset to (optional)
* @returns Promise resolving to the created Asset object
*/
function createAssetAsync(localUri: string, album?: AlbumRef): Promise<Asset>;Usage Examples:
import * as MediaLibrary from "expo-media-library";
import { Camera } from "expo-camera";
// Save camera photo
const photo = await camera.takePictureAsync();
const asset = await MediaLibrary.createAssetAsync(photo.uri);
// Save to specific album
const album = await MediaLibrary.getAlbumAsync('My Photos');
const assetInAlbum = await MediaLibrary.createAssetAsync(photo.uri, album);
// Save downloaded image
const downloadedImage = 'file:///path/to/downloaded/image.jpg';
const savedAsset = await MediaLibrary.createAssetAsync(downloadedImage);Saves a file to the media library without returning an asset object, useful for bulk operations.
/**
* Saves file to media library without returning asset
* @param localUri - Local file path/URI with proper file extension
* @returns Promise resolving when save is complete
*/
function saveToLibraryAsync(localUri: string): Promise<void>;Usage Examples:
import * as MediaLibrary from "expo-media-library";
// Simple save operation
await MediaLibrary.saveToLibraryAsync('file:///path/to/image.jpg');
// Bulk save multiple files
const filesToSave = [
'file:///path/to/image1.jpg',
'file:///path/to/image2.jpg',
'file:///path/to/video.mp4',
];
for (const fileUri of filesToSave) {
await MediaLibrary.saveToLibraryAsync(fileUri);
}Retrieves detailed asset information including GPS location, local URI, EXIF metadata, and platform-specific features.
/**
* Gets detailed asset information including GPS, URI, EXIF data
* @param asset - Asset object or asset ID
* @param options - Query options for network download behavior (optional)
* @returns Promise resolving to AssetInfo with detailed metadata
*/
function getAssetInfoAsync(
asset: AssetRef,
options?: MediaLibraryAssetInfoQueryOptions
): Promise<AssetInfo>;
interface MediaLibraryAssetInfoQueryOptions {
/** Whether to download asset from network if needed - iOS only */
shouldDownloadFromNetwork?: boolean;
}
interface AssetInfo extends Asset {
/** Local URI for accessing the asset file */
localUri?: string;
/** GPS location where asset was captured */
location?: Location;
/** EXIF metadata object */
exif?: object;
/** Whether asset is marked as favorite - iOS only */
isFavorite?: boolean;
/** Whether asset is stored in cloud - iOS only */
isNetworkAsset?: boolean;
/** Image orientation value - iOS only */
orientation?: number;
/** Paired video asset for Live Photos - iOS only */
pairedVideoAsset?: Asset | null;
}Usage Examples:
import * as MediaLibrary from "expo-media-library";
// Get basic asset info
const assets = await MediaLibrary.getAssetsAsync({ first: 1 });
const assetInfo = await MediaLibrary.getAssetInfoAsync(assets.assets[0]);
console.log('Local URI:', assetInfo.localUri);
console.log('Location:', assetInfo.location);
console.log('EXIF data:', assetInfo.exif);
// Get info with network download (iOS)
const networkAssetInfo = await MediaLibrary.getAssetInfoAsync(
assetId,
{ shouldDownloadFromNetwork: true }
);
// Access specific EXIF data
if (assetInfo.exif) {
console.log('Camera make:', assetInfo.exif.Make);
console.log('Camera model:', assetInfo.exif.Model);
console.log('ISO:', assetInfo.exif.ISOSpeedRatings);
}
// Check for Live Photo (iOS)
if (assetInfo.pairedVideoAsset) {
console.log('This is a Live Photo with video:', assetInfo.pairedVideoAsset.uri);
}Deletes one or more assets from the media library permanently.
/**
* Deletes assets from the media library
* @param assets - Single asset or array of assets/asset IDs to delete
* @returns Promise resolving to boolean indicating success
*/
function deleteAssetsAsync(assets: AssetRef[] | AssetRef): Promise<boolean>;Usage Examples:
import * as MediaLibrary from "expo-media-library";
// Delete single asset
const asset = await MediaLibrary.getAssetsAsync({ first: 1 });
const success = await MediaLibrary.deleteAssetsAsync(asset.assets[0]);
// Delete multiple assets
const assets = await MediaLibrary.getAssetsAsync({ first: 5 });
const deleteSuccess = await MediaLibrary.deleteAssetsAsync(assets.assets);
// Delete by asset IDs
const assetIds = ['asset-id-1', 'asset-id-2', 'asset-id-3'];
const deletedIds = await MediaLibrary.deleteAssetsAsync(assetIds);
// Conditional deletion
const oldAssets = await MediaLibrary.getAssetsAsync({
createdBefore: new Date('2020-01-01'),
first: 100,
});
if (oldAssets.assets.length > 0) {
const deleted = await MediaLibrary.deleteAssetsAsync(oldAssets.assets);
console.log(`Deleted ${deleted ? oldAssets.assets.length : 0} old assets`);
}interface Asset {
/** Unique identifier for the asset */
id: string;
/** Asset filename */
filename: string;
/** Asset URI (ph:// on iOS, file:// on Android) */
uri: string;
/** Media type of the asset */
mediaType: MediaTypeValue;
/** Media subtypes array - iOS only */
mediaSubtypes?: MediaSubtype[];
/** Asset width in pixels */
width: number;
/** Asset height in pixels */
height: number;
/** Creation timestamp in milliseconds */
creationTime: number;
/** Last modification timestamp in milliseconds */
modificationTime: number;
/** Duration in seconds (0 for photos) */
duration: number;
/** Album ID containing this asset - Android only */
albumId?: string;
}
interface Location {
/** Latitude coordinate */
latitude: number;
/** Longitude coordinate */
longitude: number;
/** Altitude in meters (optional) */
altitude?: number;
/** Accuracy in meters (optional) */
accuracy?: number;
}
type MediaTypeValue = 'audio' | 'photo' | 'video' | 'unknown' | 'pairedVideo';
/**
* Media subtypes available on iOS
* @platform ios
*/
type MediaSubtype =
| 'depthEffect' // Portrait mode photos
| 'hdr' // HDR photos
| 'highFrameRate' // High frame rate videos
| 'livePhoto' // Live Photos
| 'panorama' // Panorama photos
| 'screenshot' // Screenshots
| 'stream' // Streamed videos
| 'timelapse' // Time-lapse videos
| 'spatialMedia' // Spatial media (Vision Pro)
| 'videoCinematic'; // Cinematic mode videos
type SortByValue = [SortByKey, boolean] | SortByKey;
type SortByKey =
| 'default'
| 'mediaType'
| 'width'
| 'height'
| 'creationTime'
| 'modificationTime'
| 'duration';
type AssetRef = Asset | string;pairedVideoAssetisFavoriteisNetworkAsset and download optionsalbumIdACCESS_MEDIA_LOCATION permission for GPS data