Skip to content

Latest commit

 

History

History
1033 lines (786 loc) · 39.6 KB

README-ZH.md

File metadata and controls

1033 lines (786 loc) · 39.6 KB

photo_manager

English | 中文

pub package pub pre-release package Build status GitHub license

GitHub stars GitHub forks Awesome Flutter FlutterCandies

通过相册的抽象 API 对设备中的资源(图片、视频、音频)进行管理,不需要集成 UI。 在 Android、iOS、macOS and OpenHarmony上可用。

集成此插件的推荐项目

name pub github
wechat_assets_picker pub package star
wechat_camera_picker pub package star

关于此插件的文章

破坏性改动迁移指南

查看 迁移指南 了解如何在破坏性改动之间迁移。

目录列表

常见问题

你可以在 GitHub issues 上搜索到经常遇到的问题,比如构建错误,运行时异常等等。

使用前准备

添加依赖

有两种方式可以把依赖添加到你的项目中:

  • (推荐) 运行 flutter pub add photo_manager.
  • 或者直接添加到项目的 pubspec.yaml 中的 dependencies 部分:
dependencies:
  photo_manager: $latest_version

目前最新的版本是: pub package

导入到你的项目中:

import 'package:photo_manager/photo_manager.dart';

原生平台的配置

最低的平台版本: Android API 16, iOS 9.0, macOS 10.15.

Android 配置准备

Kotlin, Gradle, AGP

该插件使用 Kotlin 1.7.22 来构建。 如果你的项目使用了低于此版本的 Kotlin/Gradle/AGP,请升级到大于或等于指定版本。

更具体的做法:

  • 更新你的 Gradle version (gradle-wrapper.properties) 到 7.5.1 或者最新版本。
  • 更新你的 Kotlin version (ext.kotlin_version) 到 1.7.22 或者最新版本。
  • 更新你的 AGP version (com.android.tools.build:gradle) 或者 7.2.2 或者最新版本。
Android 10 (Q, 29)

如果你没有设置 compileSdkVersiontargetSdkVersion29,你可以跳过本节。

Android 10 引入了 Scoped Storage,导致原始资源文件不能通过其文件路径直接访问。

如果你的 compileSdkVersiontargetSdkVersion 为 29, 为了能够成功获取到媒体资源,你可以考虑通过在 AndroidManifest.xml 中添加 android:requestLegacyExternalStorage="true",如下所示:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.fluttercandies.photo_manager_example">

    <application
        android:label="photo_manager_example"
        android:icon="@mipmap/ic_launcher"
        android:requestLegacyExternalStorage="true">
    </application>
</manifest>

注意: 这样设置的应用无法上架 Google Play。

这不是必须的,插件缓存文件的时候还是可以正常工作的。 但是开发者需要主动清理缓存,最佳实践是启动应用时调用 PhotoManager.clearFileCache 清理缓存文件。

Glide

本插件使用 Glide 在 Android 平台上创建缩略图。

如果你发现 Glide 出现了一些警告日志,说明主项目需要实现 AppGlideModule。 请查看 Generated API 的相关文档说明。

iOS 配置准备

添加 NSPhotoLibraryUsageDescription 到你的项目的 ios/Runner/Info.plist 中:

<key>NSPhotoLibraryUsageDescription</key>
<string>In order to access your photo library</string>

在 iOS 11 或者更高版本中,如果你只需要请求相册的写入权限, 仅需要添加 NSPhotoLibraryAddUsageDescription 到你的项目的 ios/Runner/Info.plist

permissions in Xcode

使用方法

请求权限

大部分的 API 只在获取到权限后才能正常使用。

final PermissionState ps = await PhotoManager.requestPermissionExtend();
if (ps.isAuth) {
  // 已获取到权限
} else if (ps.hasAccess) {
  // 已获取到权限(哪怕只是有限的访问权限)。
  // iOS Android 目前都已经有了部分权限的概念。
} else {
  // 权限受限制(iOS)或者被拒绝,使用 `==` 能够更准确的判断是受限还是拒绝。
  // 你可以使用 `PhotoManager.openSetting()` 打开系统设置页面进行进一步的逻辑定制。
}

如果你确定你的应用已经授予了权限,你也可以忽略权限的检查:

PhotoManager.setIgnorePermissionCheck(true);

对于一些后台操作(应用未启动等)而言,忽略检查是比较合适的做法。

同时你还可以调用 PhotoManager.getPermissionState 来获取权限状态。 请确保调用该方法使用的权限设置与调用其他方法的权限设置相同。

受限的资源权限

iOS 受限的资源权限

iOS14 引入了部分资源限制的权限 (PermissionState.limited)。 PhotoManager.requestPermissionExtend() 会返回当前的权限状态 PermissionState。 详情请参阅 PHAuthorizationStatus

如果你想要重新选择在应用里能够读取到的资源,你可以使用 PhotoManager.presentLimited() 重新选择资源, 这个方法对于 iOS 14 以上的版本生效。

如果你想要禁止每次应用重新启动后访问媒体时自动弹出提示, 你可以将 Info.plistPrevent limited photos access alert 设置为 YES (或者像下面一样手动编写):

<key>PHPhotoLibraryPreventAutomaticLimitedAccessAlert</key>
<true/>
Android 受限的资源权限

与 iOS 类似,Android 14 (API 34) 中也引入了这个概念。 它们在行为上略有不同(基于模拟器): 在 Android 中一旦授予某个资源的访问权限,就无法撤销, 即使再次使用 presentLimited 时不选中也不会撤销对它的访问权限。

获取相簿或图集 (AssetPathEntity)

相簿或者图集以抽象类 AssetPathEntity 的形式呈现, 在 Android 中它表示为具有相同 bucketIdMediaStore 记录的集合, 在 iOS/macOS 中则是 PHAssetCollection 的记录。

获取所有相册:

final List<AssetPathEntity> paths = await PhotoManager.getAssetPathList();

详情请参阅 getAssetPathList

getAssetPathList 方法的参数

参数名 说明 默认值
hasAll 如果你需要一个包含所有资源(AssetEntity) 的 PathEntity ,传入 true true
onlyAll 如果你只需要一个包含所有资源的,传入true false
type 资源文件的类型(视频、图片、音频) RequestType.common
filterOption 用于筛选 AssetEntity,详情请参阅 过滤资源 FilterOptionGroup()
pathFilterOption 只对 iOS 和 macOS生效,对应原生中的相册类型,详情请参阅 PMPathFilterOption 默认为包含所有

PMPathFilterOption

自 2.7.0 版本开始提供,当前仅支持 iOS 和 macOS。

final List<PMDarwinAssetCollectionType> pathTypeList = []; // 配置为你需要的类型
final List<PMDarwinAssetCollectionSubtype> pathSubTypeList = []; // 配置为你需要的子类型
final darwinPathFilterOption = PMDarwinPathFilter(
      type: pathTypeList,
      subType: pathSubTypeList,
    );
PMPathFilter pathFilter = PMPathFilter();

PMDarwinAssetCollectionType的枚举值一一对应 PHAssetCollectionType | 苹果官网文档.

PMDarwinAssetCollectionSubtype 的枚举值一一对应 PHAssetCollectionSubType | 苹果官网文档.

获取资源 (AssetEntity)

资源(图片/视频/音频)以 AssetEntity 的方式呈现, 它抽象了原生中关于媒体对象的一系列属性和方法。 在 Android 中表示 MediaStore 记录的其中一些字段的集合, 在 iOS/macOS 则是 PHAsset 的记录。

通过 AssetPathEntity 获取

你可以通过 分页方法 获取:

final List<AssetEntity> entities = await path.getAssetListPaged(page: 0, size: 80);

也可以通过 范围索引方法 获取:

final List<AssetEntity> entities = await path.getAssetListRange(start: 0, end: 80);

通过 PhotoManager 方法 (2.6.0+) 获取

首先你需要获取资源的数量:

final int count = await PhotoManager.getAssetCount();

然后通过 分页方法 获取:

final List<AssetEntity> entities = await PhotoManager.getAssetListPaged(page: 0, pageCount: 80);

也通过 范围索引方法 获取:

final List<AssetEntity> entities = await PhotoManager.getAssetListRange(start: 0, end: 80);

注意: pagestart 都从 0 开始。

通过 ID 获取

ID 在不同平台代表:

  • Android 平台 MediaStore_id 字段;
  • iOS/macOS 平台 PHAssetlocalIdentifier 字段。

如果你想要实现持久化选择的相关功能,你需要存储资源的 ID, 并在之后的使用中通过 AssetEntity.fromId` 来重新持有资源对象。

final AssetEntity? asset = await AssetEntity.fromId(id);

请留意资源可能访问受限,或随时被删除,所以结果可能为空。

通过原始数据获取

你可以从原始数据或文件(如下载的图像、录制的视频等)创建 AssetEntity。 创建的 AssetEntity 将储存到设备的图库中。

final Uint8List rawData = yourRawData;

// 将 `Uint8List` 保存为一张图片。
final AssetEntity? entity = await PhotoManager.editor.saveImage(
  rawData,
  title: 'write_your_own_title.jpg', // 可能影响 EXIF 信息的读取
);

// 通过路径来保存一张已存在的图片。
final AssetEntity? imageEntityWithPath = await PhotoManager.editor.saveImageWithPath(
  path, // 使用源文件的绝对路径来保存,与复制类似。
  title: 'same_as_above.jpg',
);

// 通过文件来保存视频。
final File videoFile = File('path/to/your/video.mp4');
final AssetEntity? videoEntity = await PhotoManager.editor.saveVideo(
  videoFile, // 可以检查文件是否存在以获得更好的测试覆盖率。
  title: 'write_your_own_title.mp4',
);

// [仅 iOS] 通过图片和视频来保存一张实况照片。
// 仅在图片和视频文件为同一张实况照片时才能生效。
final File imageFile = File('path/to/your/livephoto.heic');
final File videoFile = File('path/to/your/livevideo.mp4');
final AssetEntity? entity = await PhotoManager.editor.darwin.saveLivePhoto(
  imageFile: imageFile,
  videoFile: videoFile,
  title: 'write_your_own_title.heic',
);

请留意资源可能访问受限,或随时被删除,所以结果可能为空。

iOS 和 macOS 可能会对资源保存附加额外的限制,目前仅部分资源类型可以保存为图库资源。 该限制由 AVFileType 定义,当你在保存时看到 PHPhotosErrorDomain Code=3302 (或者 330x) 错误时, 确保你的文件类型受支持。

通过 iCloud 获取

iOS 为了节省磁盘空间,可能将资源仅保存在 iCloud 上。 从 iCloud 检索资源文件时,速度会取决于网络状况,可能非常缓慢,使用户感到焦虑。 你可以使用 PMProgressHandler 在加载文件时提示用户当前的进度。

推荐参考的实践是 wechat_asset_picker 中的 LocallyAvailableBuilder,它会在下载文件时提供进度的展示。

有数个方法可以结合 PMProgressHandler 来提供进度反馈:

  • AssetEntity.thumbnailDataWithSize
  • AssetEntity.thumbnailDataWithOption
  • AssetEntity.getMediaUrl
  • AssetEntity.loadFile
  • PhotoManager.plugin.getOriginBytes

iCloud 文件只能在设备上的 Apple ID 正常登录时获取。 当账号要求重新输入密码验证时,未缓存在本地的 iCloud 文件将无法访问, 此时相关方法会抛出 CloudPhotoLibraryErrorDomain 错误。

展示资源

从 v3.0.0 开始,插件不再提供任何 UI 组件。 AssetEntityImageAssetEntityImageProviderphoto_manager_image_provider 插件中提供。

新的插件提供 AssetEntityImage widget 和 AssetEntityImageProvider 来处理资源的展示:

import 'package:photo_manager_image_provider/photo_manager_image_provider.dart';

final Widget image = AssetEntityImage(
  yourAssetEntity,
  isOriginal: false,
  thumbnailSize: const ThumbnailSize.square(200),
  thumbnailFormat: ThumbnailFormat.jpeg,
);

final Widget imageFromProvider = Image(
  image: AssetEntityImageProvider(
    yourAssetEntity,
    isOriginal: false,
    thumbnailSize: const ThumbnailSize.square(200),
    thumbnailFormat: ThumbnailFormat.jpeg,
  ),
);

获取文件

AssetEntity 包含数个获取文件的 getter 和方法:

  • .file
  • .fileWithSubtype
  • .originFile
  • .originFileWithSubtype
  • .loadFile

这些方法会获取与该资源关联的不同类型的文件。阅读它们的文档以了解具体的用途。

另外,你可以使用 PhotoManager.plugin.getFullFile 来获取文件,该方法有完整的获取参数。

获取「实况照片」

该插件支持获取和过滤 iOS 上的实况照片。

仅过滤「实况照片」

只在过滤图片的时候支持过滤「实况照片」:

final List<AssetPathEntity> paths = await PhotoManager.getAssetPathList(
  type: RequestType.image,
  filterOption: FilterOptionGroup(onlyLivePhotos: true),
);

或者你也可以使用 CustomSqlFilter 来获取「实况照片」:

final List<AssetPathEntity> paths = await PhotoManager.getAssetPathList(
  type: RequestType.image,
  filterOption: CustomFilter.sql(
  where: '${CustomColumns.base.mediaType} = 1'
      ' AND '
      '${CustomColumns.darwin.mediaSubtypes} & (1 << 3) = (1 << 3)',
  ),
);
获取「实况照片」的视频
final AssetEntity entity = livePhotoEntity;

// 播放实况照片的视频
final String? mediaUrl = await entity.getMediaUrl();

// 获取缩略图和视频
final File? imageFile = await entity.file;
final File? videoFile = await entity.fileWithSubtype;

// 获取原图和原视频
final File? originImageFile = await entity.originFile;
final File? originVideoFile = await entity.originFileWithSubtype;

// 将实况照片的视频从 mov 转换为 mp4
final File? convertedFile = await entity.loadFile(
  isOriginal: true,
  withSubtye: true,
  darwinFileType: PMDarwinAVFileType.mp4,
);

限制

Android 10 媒体位置权限

在 Android 10 版本中获取带有位置信息和 EXIF 元数据的原始数据时,必须授予媒体位置权限。 若需要获取,请将 ACCESS_MEDIA_LOCATION 权限添加到清单中。

原始数据的使用

originFileoriginBytes 的 getter 会返回资源的原始数据。 然而在 Flutter 中,某些情况的原始数据是无法使用的。以下是一些常见的情况:

  • 在不同平台和版本中,HEIC 文件并未被完全支持。 我们建议你上传 JPEG 文件(HEIC 图片的 .file), 以保持多个平台之间的一致行为。 查看 flutter/flutter#20522 了解更多细节。
  • 视频将仅以原始格式获取,而不是组合过的格式, 这可能会在播放视频时导致某些行为的差异。
iOS 上文件检索时间过长

该插件中有几个针对 AssetEntity 的 I/O 方法:

  • 所有名称带有 file 的方法.
  • AssetEntity.originBytes.

在 iOS 上,文件的检索和缓存受到沙盒机制的限制。 能获取到 PHAsset 并不意味着该资源位于设备上。 一般来说,PHAsset 会有三种状态:

  • isLocallyAvailable 等于 true, 并且已经缓存:可以获取。
  • isLocallyAvailable 等于 true, 但没有缓存:当你调用 I/O 方法时,资源需要缓存在沙盒中才可以获取。
  • isLocallyAvailable 等于 false,通常意味着资源仅保存在 iCloud 上,或者某些视频尚未导出过。 在这种情况下,最好使用 PMProgressHandler 提供响应式的用户界面。

资源变动的通知回调

插件会从原生平台广播资源变更的事件,但是在不同的平台和系统版本之间,事件携带的内容并不相同。 你可以参考 相关日志 了解各个版本和平台之间的事件日志。

要为这些事件注册回调,请使用 PhotoManager.addChangeCallback 添加回调, 并使用 PhotoManager.removeChangeCallback 移除回调, 与 addListenerremoveListener 方法相似。

在添加/移除回调之后,你可以调用 [PhotoManager.startChangeNotify 方法启用通知, 以及 PhotoManager.stopChangeNotify 方法停止通知。

import 'package:flutter/services.dart';

void changeNotify(MethodCall call) {
  // 你的自定义回调。
}

/// 注册你的回调方法。
PhotoManager.addChangeCallback(changeNotify);

/// 启用事件通知订阅。
PhotoManager.startChangeNotify();

/// 移除你的回调方法。
PhotoManager.removeChangeCallback(changeNotify);

/// 取消事件通知订阅。
PhotoManager.stopChangeNotify();

过滤资源

插件包含对资源过滤筛选的支持。 以下的方法包含 filterOption 参数,用于指定资源过滤的条件。

  • PhotoManager
    • getAssetPathList(可以通过 AssetPathEntity.filterOption 获取)
    • getAssetCount
    • getAssetListRange
    • getAssetListPaged
  • AssetPathEntity
    • 构造(不推荐直接使用)
    • fromId
    • obtainPathFromProperties(不推荐直接使用)

插件支持两种形式的资源筛选:

FilterOptionGroup

FilterOptionGroup 是 2.6.0 版本前唯一支持的筛选器实现。

final FilterOptionGroup filterOption = FilterOptionGroup(
  imageOption: FilterOption(
    sizeConstraint: SizeConstraint(
      maxWidth: 10000,
      maxHeight: 10000,
      minWidth: 100,
      minHeight: 100,
      ignoreSize: false,
    ),
  ),
  videoOption: FilterOption(
    durationConstraint: DurationConstraint(
      min: Duration(seconds: 1),
      max: Duration(seconds: 30),
      allowNullable: false,
    ),
  ),
  createTimeCondition: DateTimeCondition(
    min: DateTime(2020, 1, 1),
    max: DateTime(2020, 12, 31),
  ),
  orders: [
    OrderOption(
      type: OrderOptionType.createDate,
      asc: false,
    ),
  ],
  /// 其他选项
);

CustomFilter

注意: CustomFilter 自 v2.6.0 引入。由于其存在时间较短,无法保证其稳定性。 如果在使用时遇到相关问题,请按照模板提交 issue。

CustomFilter 针对不同平台提供了更加灵活的筛选条件。 其使用方法更像平台本身的处理方法,即类 SQL 的筛选方式。

SQL 筛选的字段名称在不同平台上是不一致的, 在使用时请注意区分 CustomColumns.baseCustomColumns.android 以及 CustomColumns.darwin 来获取正确的字段名称。

构造一个 CustomFilter 的例子:

CustomFilter createFilter() {
  return CustomFilter.sql(
    where: '${CustomColumns.base.width} > 100 AND ${CustomColumns.base.height} > 200',
    orderBy: [OrderByItem.desc(CustomColumns.base.createDate)],
  );
}

更高级的 CustomFilter

AdvancedCustomFilter 继承自 CustomFilter, 可以通过 builder 方式创建一个筛选器。

CustomFilter createFilter() {
  final group = WhereConditionGroup()
      .and(
        ColumnWhereCondition(
          column: CustomColumns.base.width,
          value: '100',
          operator: '>',
        ),
      )
      .or(
        ColumnWhereCondition(
          column: CustomColumns.base.height,
          value: '200',
          operator: '>',
        ),
      );
  final filter = AdvancedCustomFilter()
      .addWhereCondition(group)
      .addOrderBy(column: CustomColumns.base.createDate, isAsc: false);
  return filter;
}

相关类定义解释

  • CustomFilter:自定义筛选器的基类。
  • SqlCustomFilter:类 SQL 的筛选器。
  • AdvancedCustomFilter:构建自定义选项的筛选器。
    • OrderByItem:实现排序的类,功能类似于 ORDER BY。
    • WhereConditionItem:条件筛选的抽象类,功能类似于 WHERE。
      • WhereConditionGroup:筛选条件组,将一组条件合并在同一个条件组。
      • TextWhereCondition:字符串筛选条件,在传递时不会检查是否有效。
      • ColumnWhereCondition:字段名筛选条件,在传递时会检查字段名是否有效。
      • DateColumnWhereCondition:日期筛选条件,由于 iOS/macOS 上的日期格式不同,该条件可以帮助处理这些差异。
  • CustomColumns:不同平台的字段名。
    • base:适用于各个平台通用的字段名,但在 iOS 上 "id" 字段无效,甚至可能会导致错误。它只在 Android 上有效。
    • android:适用于 Android 的字段名。
    • darwin:适用于 iOS/macOS 的字段名。

下图为自定义筛选器作用的流程图: flow_chart

缓存机制

Android 缓存

由于 Android 10 限制了直接访问资源路径的能力, 因此图像缓存将在 I/O 处理过程中生成。 更具体地说,当调用 fileoriginFile 或任何 I/O 操作时, 插件将保存一个文件到缓存文件夹以供进一步使用。

幸运的是,在 Android 11 及以上版本中,可以再次直接获取资源路径, 在 Android 10 中,你仍然可以使用 requestLegacyExternalStorage 访问存储中的文件而不缓存它们。 有关如何添加属性,请参见 Android 10 (Q, 29)。 该属性不是必需的。

iOS 缓存

iOS 没有直接提供 API 来访问相册资源的原始文件。 因此,当调用 fileoriginFile 或相关的文件操作时, 将在当前应用程序的沙盒中生成对应的缓存文件。

如果在你的用例中占用磁盘空间很敏感, 那么你可以在使用完成后删除它(仅适用于 iOS)。

import 'dart:io';

Future<void> useEntity(AssetEntity entity) async {
  File? file;
  try {
    file = await entity.file;
    await handleFile(file!); // 处理获取的文件
  } finally {
    if (Platform.isIOS) {
      file?.deleteSync(); // 处理完成后删除
    }
  }
}

清除缓存

你可以使用 PhotoManager.clearFileCache 方法来清除插件生成的所有缓存。 缓存的生成取决于不同平台、类型和分辨率等情况。

平台 缩略图 文件 / 原始文件
Android 生成 生成 (Android 10+)
iOS 不生成 生成

原生额外配置

Android 额外配置

Glide 相关问题

如果你的项目存在 Glide 的版本冲突问题, 那么你需要编辑 android/build.gradle 文件:

rootProject.allprojects {
    subprojects {
        project.configurations.all {
            resolutionStrategy.eachDependency { details ->
                if (details.requested.group == 'com.github.bumptech.glide'
                        && details.requested.name.contains('glide')) {
                    details.useVersion '4.14.2'
                }
            }
        }
    }
}

如果你想了解如何同时使用 ProGuard 和 Glide,请参阅 ProGuard for Glide

Android 14 (API level 34) 额外配置

当你的应用在 API 34 (Android 14) 的设备上运行时, 就算你的 targetSdkVersioncompileSdkVersion 不是 34, 你也需要在清单文件中添加以下权限配置:

<manifest>
   <uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" /> <!-- 如果需要提供可选的资源的功能 -->
</manifest>

Android 13 (API level 33) 额外配置

当你的应用在 API 33 (Android 13) 的设备上运行时, 就算你的 targetSdkVersioncompileSdkVersion 不是 33, 你也需要在清单文件中添加以下权限配置:

注意:READ_MEDIA_IMAGESREAD_MEDIA_VIDEO 无论在请求图片还是请求视频时都需要。

<manifest>
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <!-- 如果需要读取图片或视频 -->
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <!-- 如果需要读取视频或图片 -->
    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> <!-- 如果需要读取音频 -->
</manifest>

iOS 额外配置

配置系统相册名称的国际化

默认情况下,无论设备上设置了什么语言,iOS 都只会以英语检索系统相册的名称。 要更改默认语言,请按照以下步骤操作:

  • 用 Xcode 打开你的 iOS 项目 (Runner.xcworkspace) Edit localizations in Xcode 1

  • 选择你项目的 “Runner”,在本地化表格中单击加号图标。 Edit localizations in Xcode 2

  • 选择你想要检索本地化的语言。

  • 在不进行任何修改的情况下验证弹出屏幕。

  • 重新构建你的 Flutter 项目。

现在系统相册的名称应该能够以对应的语言显示。

注意: 本地化相册名称不代表自定义。

实验性功能

警告: 此处的功能不能保证在所有平台和系统版本下完全可用, 因为它们涉及到数据修改。 它们可能在任何版本中随时被修改或删除。

某些 API 将对数据进行不可逆的修改和删除。 在使用这些功能时,请谨慎操作,并最好实现先行测试

预加载缩略图

你可以使用 PhotoCachingManager.requestCacheAssetsPhotoCachingManager.requestCacheAssetsWithIds 方法 以特定的缩略图选项来加载部分资源的缩略图。

PhotoCachingManager().requestCacheAssets(assets: assets, option: option);

你也可以通过调用 PhotoCachingManager().cancelCacheRequest 方法随时停止预加载。

通常在 app 预览资源时,会使用缩略图进行展示。 但有时我们希望预加载资源以使其显示更快。

PhotoCachingManager 在 iOS 上使用的是 PHCachingImageManager, 在 Android 上使用 Glide 的文件缓存。

删除资源

此方法将从你的图库中完全删除资源,请谨慎使用。

// 调用方法会返回被删除的资源,如果全部失败会返回空列表。
final List<String> result = await PhotoManager.editor.deleteWithIds(
  <String>[entity.id],
);

删除后,你可以调用 refreshPathProperties 方法刷新相应的 AssetPathEntity 以便更新字段。

复制资源

你可以使用 copyAssetToPath 方法将资源 “复制” 到目标 AssetPathEntity 中:

// 确保 anotherPathEntity 对于当前 app 而言可以访问。
final AssetPathEntity anotherPathEntity = anotherAccessiblePath;
final AssetEntity entity = yourEntity;
final AssetEntity? newEntity = await PhotoManager.editor.copyAssetToPath(
  asset: entity,
  pathEntity: anotherPathEntity,
); // 如果 anotherPathEntity 无法访问,结果会返回 null。

“复制” 在 Android 和 iOS 上有不同的含义:

  • 对于 Android,它会插入源资源的副本:
    • 在 SDK <= 28 上,该方法将复制大部分来源信息。
    • 在 SDK >= 29 上,某些字段无法在插入期间修改,如 MediaColumns.RELATIVE_PATH.
  • 对于 iOS,它会创建一个快捷方式,而不是创建一个新的资源。
    • 某些相册是智能相册,它们的内容由系统自动管理,不能手动插入资源。

(对于 Android 30+,由于系统限制,此功能当前被屏蔽。)

仅适用于 Android 的功能

将资源移动到另一个相册
// 确保 accessiblePath 对于当前 app 而言可以访问。
final AssetPathEntity pathEntity = accessiblePath;
final AssetEntity entity = yourEntity;
await PhotoManager.editor.android.moveAssetToAnother(
  entity: entity,
  target: pathEntity,
);

(对于 Android 30+,由于系统限制,此功能当前被屏蔽。)

将资源移动到废纸篓
await PhotoManager.editor.android.moveToTrash(list);

这个方法用于将资源移动到废纸篓,它仅支持安卓 API 30+,低于 30 的 API 会抛出异常。

移除所有不存在的资源

这将删除所有本地不存在的相册条目。 安卓的 MediaStore 中的记录对应的文件可能会被其他的 app 或文件管理器删除。 这些异常行为通常是由文件管理器、辅助工具或 adb 工具造成的。 此操作很消耗资源,请不要重复调用。

await PhotoManager.editor.android.removeAllNoExistsAsset();

某些系统会在每个资源删除时分别弹出确认对话框,这是无法避免的。 请确认你需要调用该方法,并且你的客户接受反复弹窗确认。

适用于 iOS 或 macOS 的功能

创建一个文件夹
PhotoManager.editor.darwin.createFolder(
  name,
  parent: parent, // 应为 null、根目录或者其他可访问的文件夹
);
创建一个相簿
PhotoManager.editor.darwin.createAlbum(
  name,
  parent: parent, // 应为 null、根目录或者其他可访问的文件夹
);
从相册中移除资源

从特定相册中移除资源。 该移除不会从设备中删除,只会从相册中被移除。

// 确保你的路径能够访问。
final AssetPathEntity pathEntity = accessiblePath;
final AssetEntity entity = yourEntity;
final List<AssetEntity> entities = <AssetEntity>[yourEntity, anotherEntity];
// 移除相簿的单个图片
// 这将调用列表移除的方法作为实现。
await PhotoManager.editor.darwin.removeInAlbum(
  yourEntity,
  accessiblePath,
);
// 批量从相册中移除资源。
await PhotoManager.editor.darwin.removeAssetsInAlbum(
  entities,
  accessiblePath,
);
删除 AssetPathEntity

智能相册无法被删除。

PhotoManager.editor.darwin.deletePath();

适用于 OpenHarmony 的功能

鸿蒙官方处于安全考虑已禁止相关资源能力。

目前以支持除缓存相关的其他功能,且只支持图片和视频类型资源。

Feature OpenHarmony
releaseCache
clearFileCache
requestCacheAssetsThumbnail
getSubPathEntities