「这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战」。
Flutter应用中要选择图片或视频的话,可以使用图片选取组件 image_picker 。
内容肉翻自 image_picker 的 pub 。
image_picker | Flutter Package (pub.dev)
image_picker 是用在 iOS 和 Android 两个平台上的 Flutter 图片选取组件。
该组件可从图片库中选择图片或者用相机拍新的照片。
安装
首先,在 pubspec.yaml 中添加 image_picker 的依赖。
dependencies:
image_picker: ^0.8.4+4
iOS
该插件需要 iOS 9.0 或更高版本。
该插件从 0.8.1 版本开始,在 iOS 14 或更高版本上的实现是使用 PHPicker 选择(多选)图片。
用 PHPicker 实现会导致无法在 iOS14 或更高版本的虚拟机上选择 HEIC 图片。
这是一个已知的问题。请在真机上测试这个问题,或直到 Apple 修复这个问题前使用非 HEIC 格式的图片。
该链接为 google 搜索链接。
在 Info.plist 中添加以下的 key, Info.plist 位于 <project>/ios/Runner/Info.plist :
-
NSPhotoLibraryUsageDescription: 描述 APP 需要访问图片库权限的理由。在可视化编辑器中是 Privacy - Photo Library Usage Description。 -
NSCameraUsageDescription: 描述 APP 需要访问相机权限的理由。在可视化编辑器中是 Privacy - Camera Usage Description。 -
NSMicrophoneUsageDescription: 描述APP 需要访问麦克风权限的理由(如果想要记录视频的话)。在可视化编辑器中是 Privacy - Microphone Usage Description。
Android
从 0.8.1 版本开始,在 Android 4.3 或更高版本的实现支持选择(多选)图片。
无需配置 - 开箱即用。
不再需要向 AndroidManifest.xml 的 标签中添加 android:requestLegacyExternalStorage="true" 属性, 这是因为 image_picker 已经更新为使用分区存储。
分区存储:Android 11 中的存储机制更新 | Android 开发者 | Android Developers (google.cn)
注: 使用相机捕捉的的图片和视频会保存到应用的本地缓存,因此应该只作临时使用。如果想要永久存储捕捉的图片,需要负责转移到一个更持久化的位置。
示例
import 'package:image_picker/image_picker.dart';
...
final ImagePicker _picker = ImagePicker();
// 选择图片
final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
// 拍照
final XFile? photo = await _picker.pickImage(source: ImageSource.camera);
// 选择视频
final XFile? image = await _picker.pickVideo(source: ImageSource.gallery);
// 录像
final XFile? video = await _picker.pickVideo(source: ImageSource.camera);
// 选择多张图片
final List<XFile>? images = await _picker.pickMultiImage();
...
处理 Android 平台的 MainActivity 销毁
Android 系统有时(即使几乎从不存在这种情况)会在 image_picker 选取完时杀死 MainActivity 。
如果发生这种情况,用 image_picker 选取的数据会丢失。
这种情况,需要使用 retrieveLostData 来找回丢失的数据。
Future<void> getLostData() async {
final LostDataResponse response =
await picker.retrieveLostData();
if (response.isEmpty) {
return;
}
if (response.files != null) {
for(final XFile file in response.files) {
_handleFile(file);
}
} else {
_handleError(response.exception);
}
}
没有方法能检测到 MainActivity 的销毁何时发生,所以在正确的位置调用这个方法是必要的。建议在一些启动检查中来处理。参考示例 APP 来确认如何使用。
迁移到 0.8.2+
image_picker 插件从 0.8.2 版本开始,添加了一些新方法。这些方法返回 XFile (来自cross_file包) 实例,而不是插件自身的 PickedFile 实例。虽然旧方法仍然存在,仍然建议你启动到对应新版本的迁移。到最后,```PickedFile`` 和返回该类型实例的方法会被标记为过时然后移除。
调用新方法
| 旧 API | 新 API |
|---|---|
PickedFile image = await _picker.getImage(...) | XFile image = await _picker.pickImage(...) |
List<PickedFile> images = await _picker.getMultiImage(...) | List<XFile> images = await _picker.pickMultiImage(...) |
PickedFile video = await _picker.getVideo(...) | XFile video = await _picker.pickVideo(...) |
LostData response = await _picker.getLostData() | LostDataResponse response = await _picker.retrieveLostData() |