迁移到新的 expo-media-library API
编辑页面
从旧版 expo-media-library API 迁移到基于类的新的 expo-media-library API,包含 Asset、Album 和 Query。
For the complete documentation index, see llms.txt. Use this file to discover all available pages.
新的基于类的 expo-media-library API 现在已经稳定。旧版 API 可从 expo-media-library/legacy 获取。请迁移到根目录的 expo-media-library 导入,以便使用新 API 并获得未来修复。
新的 API 用 Asset、Album 和 Query 类取代了基于函数的 MediaLibrary.getAssetsAsync({ ... }) 风格。相册和资产现在都表示为类实例,仅持有原生资产的 ID。资产属性变为异步 getter,而不是预先获取的字段。Query 用可链式调用的构建器模式替代了 getAssetsAsync 函数。
安装
安装与 SDK 兼容的包:
- npx expo install expo-media-library导入新 API
从 expo-media-library 导入:
import { Asset, Album, Query } from 'expo-media-library';
资产
从文件创建资产
// 之前 await MediaLibrary.saveToLibraryAsync(localUri); // 或者,如果想要获取一个引用: const asset = await MediaLibrary.createAssetAsync(localUri); // 之后 const asset = await Asset.create(localUri);
新 API 中没有 saveToLibraryAsync。请使用 Asset.create,它会将文件保存到媒体库并返回一个 Asset 实例。
查询资产
// 之前 const { assets } = await MediaLibrary.getAssetsAsync({ mediaType: MediaLibrary.MediaType.photo, first: 20, sortBy: [['creationTime', false]], }); // 之后 const assets = await new Query() .eq(AssetField.MEDIA_TYPE, MediaType.IMAGE) .limit(20) .orderBy({ key: AssetField.CREATION_TIME, ascending: false }) .exe();
Query 会直接返回 Asset 实例数组。没有 assets 包装对象,也没有 endCursor。分页通过链式调用 .limit() 和 .offset() 处理。
读取资产属性
// 之前 const info = await MediaLibrary.getAssetInfoAsync(asset); console.log(info.filename, info.width, info.height); // 之后,逐个 getter const filename = await asset.getFilename(); const width = await asset.getWidth(); const height = await asset.getHeight(); const mediaType = await asset.getMediaType(); // 之后,一次获取所有属性 const info = await asset.getInfo();
属性现在通过异步 getter 访问,而不是预先获取的字段。使用 getInfo() 一次性获取所有属性,返回一个 AssetInfo 对象。
读取 EXIF 数据
// 之前 const info = await MediaLibrary.getAssetInfoAsync(asset); const exif = info.exif; // 之后 const exif = await asset.getExif();
删除资产
// 之前 await MediaLibrary.deleteAssetsAsync([asset]); // 之后,单个资产 await asset.delete(); // 之后,多个资产 await Asset.delete([asset1, asset2]);
相册
通过名称获取相册
// 之前 const album = await MediaLibrary.getAlbumAsync('MyAlbum'); // 之后 const album = await Album.get('MyAlbum'); if (album) { // 找到相册 }
获取所有相册
// 之前 const albums = await MediaLibrary.getAlbumsAsync(); // 之后 const albums = await Album.getAll();
创建相册
// 之前 const album = await MediaLibrary.createAlbumAsync('MyNewAlbum', asset, false); // 之后 const album = await Album.create('MyNewAlbum', [asset]);
获取相册中的所有资产
// 之前 const { assets } = await MediaLibrary.getAssetsAsync({ album: album.id }); // 之后 const assets = await album.getAssets();
获取相册标题
// 之前,title 是同步属性,但需要先获取完整的相册对象 const album = await MediaLibrary.getAlbumAsync('MyAlbum'); console.log(album.title); // 之后 const title = await album.getTitle();
向相册添加资产
// 之前 await MediaLibrary.addAssetsToAlbumAsync([asset], album, false); // 之后 await album.add([asset]);
从相册中移除资产(仅 iOS)
// 之前 await MediaLibrary.removeAssetsFromAlbumAsync(assets, album); // 之后 await album.removeAssets(assets);
删除相册
// 之前 await MediaLibrary.deleteAlbumsAsync([album], false); // 之后,单个相册 await album.delete(); // 之后,多个相册 await Album.delete([album1, album2]);
权限
权限 hooks 和函数保持原名可用。唯一的变化是 presentPermissionsPickerAsync 重命名为 presentPermissionsPicker。
// 之前 await MediaLibrary.presentPermissionsPickerAsync(mediaTypes); // 之后 await presentPermissionsPicker(mediaTypes);
requestPermissionsAsync、getPermissionsAsync 和 usePermissions 保持不变。
监听变化
// 之前 const subscription = MediaLibrary.addListener(event => { ... }); subscription.remove(); // 之后 const subscription = addListener(event => { ... }); subscription.remove(); // 一次移除所有监听器 removeAllListeners();
监听器事件的结构保持不变。
破坏性的语义变化
- 资产属性现在是异步 getter(
getFilename()、getWidth()、...),而不是结果对象上的同步字段。使用asset.getInfo()可一次获取所有属性。 - 去掉了
Async后缀。整个库都是异步的。 Query取代了getAssetsAsync的选项对象。没有endCursor/hasNextPage。分页请使用.limit()和.offset()。- 相册和资产上的操作现在是
Album和Asset实例的方法,而不是接收 ID 或引用的独立函数。 saveToLibraryAsync被Asset.create取代,它会返回一个Asset实例。getMomentsAsync、albumNeedsMigrationAsync和migrateAlbumIfNeededAsync已移除,且没有替代方案。你可以安全地删除对这些函数的任何调用。
参考
查看 expo-media-library 的完整 API 参考。