Skip to content

[image_picker] getMedia platform changes #4174

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.8.0

* Adds `getMedia` method.

## 2.7.0

* Adds `CameraDelegatingImagePickerPlatform` as a base class for platform
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,30 @@ class MethodChannelImagePicker extends ImagePickerPlatform {
return paths.map((dynamic path) => XFile(path as String)).toList();
}

@override
Future<List<XFile>> getMedia({
required MediaOptions options,
}) async {
final ImageOptions imageOptions = options.imageOptions;

final Map<String, dynamic> args = <String, dynamic>{
'maxImageWidth': imageOptions.maxWidth,
'maxImageHeight': imageOptions.maxHeight,
'imageQuality': imageOptions.imageQuality,
'allowMultiple': options.allowMultiple,
};

final List<XFile>? paths = await _channel
.invokeMethod<List<dynamic>?>(
'pickMedia',
args,
)
.then((List<dynamic>? paths) =>
paths?.map((dynamic path) => XFile(path as String)).toList());

return paths ?? <XFile>[];
}

@override
Future<XFile?> getVideo({
required ImageSource source,
Expand Down Expand Up @@ -280,13 +304,21 @@ class MethodChannelImagePicker extends ImagePickerPlatform {
assert(result.containsKey('path') != result.containsKey('errorCode'));

final String? type = result['type'] as String?;
assert(type == kTypeImage || type == kTypeVideo);
assert(
type == kTypeImage || type == kTypeVideo || type == kTypeMedia,
);

RetrieveType? retrieveType;
if (type == kTypeImage) {
retrieveType = RetrieveType.image;
} else if (type == kTypeVideo) {
retrieveType = RetrieveType.video;
switch (type) {
case kTypeImage:
retrieveType = RetrieveType.image;
break;
case kTypeVideo:
retrieveType = RetrieveType.video;
break;
case kTypeMedia:
retrieveType = RetrieveType.media;
break;
}

PlatformException? exception;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,24 @@ abstract class ImagePickerPlatform extends PlatformInterface {
throw UnimplementedError('getMultiImage() has not been implemented.');
}

/// Returns a [List<XFile>] with the images and/or videos that were picked.
/// The images and videos come from the gallery.
///
/// Where iOS supports HEIC images, Android 8 and below doesn't. Android 9 and
/// above only support HEIC images if used in addition to a size modification,
/// of which the usage is explained below.
///
/// In Android, the MainActivity can be destroyed for various reasons.
/// If that happens, the result will be lost in this call. You can then
/// call [getLostData] when your app relaunches to retrieve the lost data.
///
/// If no images or videos were picked, the return value is an empty list.
Future<List<XFile>> getMedia({
required MediaOptions options,
}) {
throw UnimplementedError('getMedia() has not been implemented.');
}

/// Returns a [XFile] containing the video that was picked.
///
/// The [source] argument controls where the video comes from. This can
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,40 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'types.dart';

/// Specifies options for picking a single image from the device's camera or gallery.
///
/// This class inheritance is a byproduct of the api changing over time.
/// It exists solely to avoid breaking changes.
class ImagePickerOptions extends ImageOptions {
/// Creates an instance with the given [maxHeight], [maxWidth], [imageQuality],
/// [referredCameraDevice] and [requestFullMetadata].
const ImagePickerOptions({
super.maxHeight,
super.maxWidth,
super.imageQuality,
super.requestFullMetadata,
this.preferredCameraDevice = CameraDevice.rear,
}) : super();

/// Creates an instance with the given [maxHeight], [maxWidth], [imageQuality],
/// [referredCameraDevice] and [requestFullMetadata].
ImagePickerOptions.createAndValidate({
super.maxHeight,
super.maxWidth,
super.imageQuality,
super.requestFullMetadata,
this.preferredCameraDevice = CameraDevice.rear,
}) : super.createAndValidate();

/// Used to specify the camera to use when the `source` is [ImageSource.camera].
///
/// Ignored if the source is not [ImageSource.camera], or the chosen camera is not
/// supported on the device. Defaults to [CameraDevice.rear].
final CameraDevice preferredCameraDevice;
}

/// Specifies image-specific options for picking.
class ImageOptions {
/// Creates an instance with the given [maxHeight], [maxWidth], [imageQuality]
Expand All @@ -13,6 +47,18 @@ class ImageOptions {
this.requestFullMetadata = true,
});

/// Creates an instance with the given [maxHeight], [maxWidth], [imageQuality]
/// and [requestFullMetadata]. Throws if options are not valid.
ImageOptions.createAndValidate({
this.maxHeight,
this.maxWidth,
this.imageQuality,
this.requestFullMetadata = true,
}) {
_validateOptions(
maxWidth: maxWidth, maxHeight: maxHeight, imageQuality: imageQuality);
}

/// The maximum width of the image, in pixels.
///
/// If null, the image will only be resized if [maxHeight] is specified.
Expand All @@ -38,4 +84,19 @@ class ImageOptions {
//
// Defaults to true.
final bool requestFullMetadata;

/// Validates that all values are within required ranges. Throws if not.
static void _validateOptions(
{double? maxWidth, final double? maxHeight, int? imageQuality}) {
if (imageQuality != null && (imageQuality < 0 || imageQuality > 100)) {
throw ArgumentError.value(
imageQuality, 'imageQuality', 'must be between 0 and 100');
}
if (maxWidth != null && maxWidth < 0) {
throw ArgumentError.value(maxWidth, 'maxWidth', 'cannot be negative');
}
if (maxHeight != null && maxHeight < 0) {
throw ArgumentError.value(maxHeight, 'maxHeight', 'cannot be negative');
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ class LostDataResponse {
/// An empty response should have [file], [exception] and [type] to be null.
bool get isEmpty => _empty;

/// The file that was lost in a previous [getImage], [getMultiImage] or [getVideo] call due to MainActivity being destroyed.
/// The file that was lost in a previous [getImage], [getMultiImage],
/// [getVideo] or [getMedia] call due to MainActivity being destroyed.
///
/// Can be null if [exception] exists.
final XFile? file;
Expand All @@ -51,7 +52,7 @@ class LostDataResponse {
/// Note that it is not the exception that caused the destruction of the MainActivity.
final PlatformException? exception;

/// Can either be [RetrieveType.image] or [RetrieveType.video];
/// Can either be [RetrieveType.image], [RetrieveType.video], or [RetrieveType.media].
///
/// If the lost data is empty, this will be null.
final RetrieveType? type;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/foundation.dart';

import '../../image_picker_platform_interface.dart';

/// Specifies options for selecting items when using [ImagePickerPlatform.getMedia].
@immutable
class MediaOptions {
/// Construct a new MediaOptions instance.
const MediaOptions({
this.imageOptions = const ImageOptions(),
required this.allowMultiple,
});

/// Options that will apply to images upon selection.
final ImageOptions imageOptions;

/// Whether to allow for selecting multiple media.
final bool allowMultiple;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import '../../image_picker_platform_interface.dart';

/// The type of media to allow the user to select with [ImagePickerPlatform.getMedia].
enum MediaSelectionType {
/// Static pictures.
image,

/// Videos.
video,
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@ enum RetrieveType {
image,

/// A video. See [ImagePicker.pickVideo].
video
video,

/// Either a video or a static picture. See [ImagePicker.pickMedia].
media,
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
export 'camera_delegate.dart';
export 'camera_device.dart';
export 'image_options.dart';
export 'image_picker_options.dart';
export 'image_source.dart';
export 'lost_data_response.dart';
export 'media_options.dart';
export 'media_selection_type.dart';
export 'multi_image_picker_options.dart';
export 'picked_file/picked_file.dart';
export 'retrieve_type.dart';
Expand All @@ -17,3 +18,6 @@ const String kTypeImage = 'image';

/// Denotes that a video is being picked.
const String kTypeVideo = 'video';

/// Denotes that either a video or image is being picked.
const String kTypeMedia = 'media';
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ repository: https://github.com/flutter/packages/tree/main/packages/image_picker/
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
version: 2.7.0
version: 2.8.0

environment:
sdk: ">=2.18.0 <4.0.0"
Expand Down
Loading