or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

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

assets.mddocs/

Asset Management

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.

Capabilities

Query Assets

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

Create Asset

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

Save to Library

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

Get Asset Information

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

Delete Assets

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

Types

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;

Platform-Specific Features

iOS

  • Live Photos: Access paired video assets through pairedVideoAsset
  • Media Subtypes: Rich filtering by photo/video types like HDR, panorama, Live Photo
  • Favorites: Access favorite status through isFavorite
  • Network Assets: Handle iCloud photos with isNetworkAsset and download options
  • Orientation: Access image orientation metadata

Android

  • Scoped Storage: Full support for Android R+ scoped storage requirements
  • Album IDs: Direct access to album associations through albumId
  • Full Resolution: Access to full resolution assets without iOS limitations
  • Media Location: Optional ACCESS_MEDIA_LOCATION permission for GPS data

Web

  • Limited Support: Basic asset listing and file access through browser APIs
  • No Native Features: EXIF, GPS, and advanced metadata not available