or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

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

albums.mddocs/

Album Management

Album creation, management, and asset organization with support for both user-created albums and smart albums (iOS), including comprehensive album operations and platform-specific migration features.

Capabilities

Query Albums

Retrieves all user-created albums with optional smart album inclusion on iOS.

/**
 * Queries for user-created albums with optional smart album inclusion
 * @param options - Album query options (optional)
 * @returns Promise resolving to array of Album objects
 */
function getAlbumsAsync(options?: AlbumsOptions): Promise<Album[]>;

interface AlbumsOptions {
  /** Include smart albums in results - iOS only */
  includeSmartAlbums?: boolean;
}

Usage Examples:

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

// Get all user-created albums
const albums = await MediaLibrary.getAlbumsAsync();
console.log(`Found ${albums.length} albums`);

// Include smart albums (iOS only)
const allAlbums = await MediaLibrary.getAlbumsAsync({
  includeSmartAlbums: true
});

// List album details
albums.forEach(album => {
  console.log(`Album: ${album.title} (${album.assetCount} assets)`);
});

Find Album by Name

Searches for a specific album by its title.

/**
 * Finds album by name
 * @param title - Album name to search for
 * @returns Promise resolving to Album object or null if not found
 */
function getAlbumAsync(title: string): Promise<Album | null>;

Usage Examples:

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

// Find specific album
const myAlbum = await MediaLibrary.getAlbumAsync('My Photos');
if (myAlbum) {
  console.log(`Found album with ${myAlbum.assetCount} assets`);
} else {
  console.log('Album not found');
}

// Check if album exists before operations
const targetAlbum = await MediaLibrary.getAlbumAsync('Screenshots');
if (!targetAlbum) {
  // Create album if it doesn't exist
  const newAlbum = await MediaLibrary.createAlbumAsync('Screenshots');
}

Create Album

Creates a new album with optional initial asset.

/**
 * Creates new album with optional initial asset
 * @param albumName - Name for the new album
 * @param asset - Initial asset or asset ID to add (optional)
 * @param copyAsset - Whether to copy asset instead of moving (Android only, optional)
 * @param initialAssetLocalUri - Local URI for initial asset (optional)
 * @returns Promise resolving to the created Album object
 */
function createAlbumAsync(
  albumName: string,
  asset?: AssetRef,
  copyAsset?: boolean,
  initialAssetLocalUri?: string
): Promise<Album>;

Usage Examples:

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

// Create empty album
const emptyAlbum = await MediaLibrary.createAlbumAsync('My New Album');

// Create album with initial asset
const photos = await MediaLibrary.getAssetsAsync({ first: 1 });
const albumWithPhoto = await MediaLibrary.createAlbumAsync(
  'Photo Album',
  photos.assets[0]
);

// Create album with asset copy (Android)
const copiedAlbum = await MediaLibrary.createAlbumAsync(
  'Copied Photos',
  photos.assets[0],
  true // Copy instead of move on Android
);

// Create album with local URI
const savedPhoto = await MediaLibrary.createAssetAsync('file:///path/to/photo.jpg');
const albumFromUri = await MediaLibrary.createAlbumAsync(
  'Saved Photos',
  savedPhoto,
  false,
  'file:///path/to/photo.jpg'
);

Delete Albums

Deletes one or more albums from the media library.

/**
 * Deletes albums from the media library
 * @param albums - Single album or array of albums/album IDs to delete
 * @param assetRemove - Also delete contained assets (iOS only, optional)
 * @returns Promise resolving to boolean indicating success
 */
function deleteAlbumsAsync(
  albums: AlbumRef[] | AlbumRef,
  assetRemove?: boolean
): Promise<boolean>;

Usage Examples:

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

// Delete single album
const album = await MediaLibrary.getAlbumAsync('Old Album');
if (album) {
  const success = await MediaLibrary.deleteAlbumsAsync(album);
  console.log(`Delete ${success ? 'successful' : 'failed'}`);
}

// Delete multiple albums
const allAlbums = await MediaLibrary.getAlbumsAsync();
const emptyAlbums = allAlbums.filter(album => album.assetCount === 0);
const deleteSuccess = await MediaLibrary.deleteAlbumsAsync(emptyAlbums);

// Delete album and its assets (iOS only)
const albumToDelete = await MediaLibrary.getAlbumAsync('Temporary Album');
if (albumToDelete) {
  await MediaLibrary.deleteAlbumsAsync(albumToDelete, true); // Delete assets too
}

// Delete by album IDs
const albumIds = ['album-id-1', 'album-id-2'];
await MediaLibrary.deleteAlbumsAsync(albumIds);

Add Assets to Album

Adds one or more assets to an existing album.

/**
 * Adds assets to an album
 * @param assets - Single asset or array of assets/asset IDs to add
 * @param album - Target album or album ID
 * @param copy - Copy assets instead of moving (Android only, optional)
 * @returns Promise resolving to boolean indicating success
 */
function addAssetsToAlbumAsync(
  assets: AssetRef[] | AssetRef,
  album: AlbumRef,
  copy?: boolean
): Promise<boolean>;

Usage Examples:

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

// Add single asset to album
const photos = await MediaLibrary.getAssetsAsync({ 
  mediaType: MediaLibrary.MediaType.photo,
  first: 1 
});
const album = await MediaLibrary.getAlbumAsync('My Photos');
if (album && photos.assets.length > 0) {
  const added = await MediaLibrary.addAssetsToAlbumAsync(photos.assets[0], album);
}

// Add multiple assets
const recentPhotos = await MediaLibrary.getAssetsAsync({
  mediaType: MediaLibrary.MediaType.photo,
  first: 10,
  sortBy: [MediaLibrary.SortBy.creationTime, false]
});
const photoAlbum = await MediaLibrary.getAlbumAsync('Recent Photos');
if (photoAlbum) {
  await MediaLibrary.addAssetsToAlbumAsync(recentPhotos.assets, photoAlbum);
}

// Copy assets instead of moving (Android)
await MediaLibrary.addAssetsToAlbumAsync(
  recentPhotos.assets,
  photoAlbum,
  true // Copy on Android
);

// Add newly created asset
const newAsset = await MediaLibrary.createAssetAsync('file:///path/to/new/photo.jpg');
const targetAlbum = await MediaLibrary.getAlbumAsync('New Photos');
if (targetAlbum) {
  await MediaLibrary.addAssetsToAlbumAsync(newAsset, targetAlbum);
}

Remove Assets from Album

Removes assets from an album without deleting the assets themselves.

/**
 * Removes assets from album without deleting the assets
 * @param assets - Single asset or array of assets/asset IDs to remove
 * @param album - Source album or album ID
 * @returns Promise resolving to boolean indicating success
 */
function removeAssetsFromAlbumAsync(
  assets: AssetRef[] | AssetRef,
  album: AlbumRef
): Promise<boolean>;

Usage Examples:

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

// Remove single asset from album
const album = await MediaLibrary.getAlbumAsync('My Album');
const albumAssets = await MediaLibrary.getAssetsAsync({ 
  album: album,
  first: 1 
});
if (album && albumAssets.assets.length > 0) {
  await MediaLibrary.removeAssetsFromAlbumAsync(albumAssets.assets[0], album);
}

// Remove multiple assets
const assetsToRemove = await MediaLibrary.getAssetsAsync({
  album: album,
  first: 5
});
await MediaLibrary.removeAssetsFromAlbumAsync(assetsToRemove.assets, album);

// Remove assets by ID
const assetIds = ['asset-1', 'asset-2', 'asset-3'];
await MediaLibrary.removeAssetsFromAlbumAsync(assetIds, album);

// Clean up album by removing old assets
const oldAssets = await MediaLibrary.getAssetsAsync({
  album: album,
  createdBefore: new Date('2022-01-01'),
  first: 100
});
if (oldAssets.assets.length > 0) {
  await MediaLibrary.removeAssetsFromAlbumAsync(oldAssets.assets, album);
}

Platform-Specific Features

iOS Moments

Access to moment albums that group assets by location and time.

/**
 * Fetches moments (asset groups by place/time)
 * @platform ios
 * @returns Promise resolving to array of moment Album objects
 */
function getMomentsAsync(): Promise<Album[]>;

Usage Examples:

import * as MediaLibrary from "expo-media-library";
import { Platform } from "react-native";

if (Platform.OS === 'ios') {
  const moments = await MediaLibrary.getMomentsAsync();
  
  moments.forEach(moment => {
    console.log(`Moment: ${moment.title}`);
    console.log(`Assets: ${moment.assetCount}`);
    console.log(`Period: ${new Date(moment.startTime)} - ${new Date(moment.endTime)}`);
    if (moment.locationNames) {
      console.log(`Locations: ${moment.locationNames.join(', ')}`);
    }
  });
}

Android Album Migration

Support for migrating albums to scoped storage directories on Android R+.

/**
 * Checks if album needs migration to scoped storage
 * @platform android R+
 * @param album - Album or album ID to check
 * @returns Promise resolving to boolean indicating if migration is needed
 */
function albumNeedsMigrationAsync(album: AlbumRef): Promise<boolean>;

/**
 * Migrates album to scoped storage directories
 * @platform android R+
 * @param album - Album or album ID to migrate
 * @returns Promise resolving when migration is complete
 */
function migrateAlbumIfNeededAsync(album: AlbumRef): Promise<void>;

Usage Examples:

import * as MediaLibrary from "expo-media-library";
import { Platform } from "react-native";

if (Platform.OS === 'android' && Platform.Version >= 30) {
  const albums = await MediaLibrary.getAlbumsAsync();
  
  for (const album of albums) {
    const needsMigration = await MediaLibrary.albumNeedsMigrationAsync(album);
    if (needsMigration) {
      console.log(`Migrating album: ${album.title}`);
      await MediaLibrary.migrateAlbumIfNeededAsync(album);
      console.log('Migration complete');
    }
  }
}

Types

interface Album {
  /** Unique identifier for the album */
  id: string;
  /** Album title/name */
  title: string;
  /** Estimated number of assets in the album */
  assetCount: number;
  /** Album type - iOS only */
  type?: AlbumType;
  /** Start time for moment albums - iOS only */
  startTime: number;
  /** End time for moment albums - iOS only */
  endTime: number;
  /** Approximate location for moment albums - iOS only */
  approximateLocation?: Location;
  /** Location names for moment albums - iOS only */
  locationNames?: string[];
}

/**
 * Album types available on iOS
 * @platform ios
 */
type AlbumType = 
  | 'album'        // User-created album
  | 'moment'       // Moment album (grouped by time/location)
  | 'smartAlbum';  // Smart album (Favorites, Screenshots, etc.)

interface Location {
  /** Latitude coordinate */
  latitude: number;
  /** Longitude coordinate */
  longitude: number;
  /** Altitude in meters (optional) */
  altitude?: number;
  /** Accuracy in meters (optional) */
  accuracy?: number;
}

type AlbumRef = Album | string;

type AssetRef = Asset | string;

Platform-Specific Behavior

iOS

  • Smart Albums: Built-in albums like Favorites, Screenshots, Recently Added
  • Moments: Automatic grouping by location and time with metadata
  • Album Types: Distinction between user albums, moments, and smart albums
  • Asset Deletion: Option to delete assets when deleting albums

Android

  • Scoped Storage: Full support for Android R+ scoped storage requirements
  • Migration: Automatic migration of albums to scoped directories
  • Copy vs Move: Control over whether assets are copied or moved between albums
  • Album IDs: Direct album references through asset albumId property

Web

  • Limited Support: Basic album operations through browser file system APIs
  • No Advanced Features: Moments, smart albums, and migration not available