diff --git a/packages/image_picker/CHANGELOG.md b/packages/image_picker/CHANGELOG.md index 96bb4fcad8c3..2aa76e4ce279 100644 --- a/packages/image_picker/CHANGELOG.md +++ b/packages/image_picker/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.3 + +* Video Capture from Camera is supporting Duration and Quality parameters. + ## 0.6.2+1 * Android: Fix a crash when a non-image file is picked. diff --git a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java index e34a3b5632c0..9219f57fdaf9 100644 --- a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java +++ b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java @@ -75,6 +75,16 @@ public class ImagePickerDelegate @VisibleForTesting static final int REQUEST_EXTERNAL_VIDEO_STORAGE_PERMISSION = 2354; @VisibleForTesting static final int REQUEST_CAMERA_VIDEO_PERMISSION = 2355; + @VisibleForTesting static final int VIDEO_QUALITY_HIGH = 1; + @VisibleForTesting static final int VIDEO_QUALITY_LOW = 0; + + @VisibleForTesting static final int FLUTTER_VIDEO_QUALITY_HIGH = 0; + + @VisibleForTesting + static final int FLUTTER_VIDEO_QUALITY_MEDIUM = 1; // Mapped to Low Quality Video Recording + + @VisibleForTesting static final int FLUTTER_VIDEO_QUALITY_LOW = 2; + @VisibleForTesting final String fileProviderName; private final Activity activity; @@ -280,6 +290,27 @@ private void launchTakeVideoWithCameraIntent() { return; } + if (methodCall != null) { + int quality = + methodCall.argument("quality") == null + ? FLUTTER_VIDEO_QUALITY_HIGH + : (int) methodCall.argument("quality"); + int videoQuality = + (quality == FLUTTER_VIDEO_QUALITY_HIGH) ? VIDEO_QUALITY_HIGH : VIDEO_QUALITY_LOW; + intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, videoQuality); + + int durationInSeconds = + methodCall.argument("duration") == null + ? 0 // Zero means a limitless video recording session + : (int) methodCall.argument("duration"); + if (durationInSeconds < 0) { + finishWithError( + "not_valid_duration_input", "Duration in seconds can not be a negative number"); + return; + } + intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, durationInSeconds); + } + File videoFile = createTemporaryWritableVideoFile(); pendingCameraMediaUri = Uri.parse("file:" + videoFile.getAbsolutePath()); diff --git a/packages/image_picker/ios/Classes/ImagePickerPlugin.m b/packages/image_picker/ios/Classes/ImagePickerPlugin.m index 5ac31a695a58..9698ff1de571 100644 --- a/packages/image_picker/ios/Classes/ImagePickerPlugin.m +++ b/packages/image_picker/ios/Classes/ImagePickerPlugin.m @@ -22,6 +22,10 @@ @interface FLTImagePickerPlugin () pickVideo({ @required ImageSource source, + VideoQuality quality = VideoQuality.High, + int durationInSeconds = 0, // Zero Means limitless video duration }) async { assert(source != null); + + if (durationInSeconds != null && durationInSeconds < 0) { + throw ArgumentError.value( + durationInSeconds, 'DurationInSeconds can not be a negative number'); + } + final String path = await _channel.invokeMethod( 'pickVideo', { 'source': source.index, + 'quality': quality.index, + 'duration': durationInSeconds, }, ); return path == null ? null : File(path); diff --git a/packages/image_picker/pubspec.yaml b/packages/image_picker/pubspec.yaml index 0e47c53e6911..c49cc174a9b5 100755 --- a/packages/image_picker/pubspec.yaml +++ b/packages/image_picker/pubspec.yaml @@ -5,7 +5,7 @@ authors: - Flutter Team - Rhodes Davis Jr. homepage: https://github.com/flutter/plugins/tree/master/packages/image_picker -version: 0.6.2+1 +version: 0.6.3 flutter: plugin: diff --git a/packages/image_picker/test/image_picker_test.dart b/packages/image_picker/test/image_picker_test.dart index 28eae8eaa46d..934fa0fec11d 100644 --- a/packages/image_picker/test/image_picker_test.dart +++ b/packages/image_picker/test/image_picker_test.dart @@ -147,20 +147,80 @@ void main() { test('passes the image source argument correctly', () async { await ImagePicker.pickVideo(source: ImageSource.camera); await ImagePicker.pickVideo(source: ImageSource.gallery); + await ImagePicker.pickVideo( + source: ImageSource.camera, + quality: VideoQuality.Medium, + ); + await ImagePicker.pickVideo( + source: ImageSource.camera, + quality: VideoQuality.Low, + ); + await ImagePicker.pickVideo( + source: ImageSource.camera, + quality: VideoQuality.Low, + durationInSeconds: 15, + ); + await ImagePicker.pickVideo( + source: ImageSource.camera, + durationInSeconds: 15, + ); expect( log, [ isMethodCall('pickVideo', arguments: { 'source': 0, + 'quality': 0, + 'duration': 0 }), isMethodCall('pickVideo', arguments: { 'source': 1, + 'quality': 0, + 'duration': 0 + }), + isMethodCall('pickVideo', arguments: { + 'source': 0, + 'quality': 1, + 'duration': 0 + }), + isMethodCall('pickVideo', arguments: { + 'source': 0, + 'quality': 2, + 'duration': 0 + }), + isMethodCall('pickVideo', arguments: { + 'source': 0, + 'quality': 2, + 'duration': 15 + }), + isMethodCall('pickVideo', arguments: { + 'source': 0, + 'quality': 0, + 'duration': 15 }), ], ); }); + test('does not accept a negative durationInSeconds argument', () { + expect( + ImagePicker.pickVideo( + source: ImageSource.camera, + durationInSeconds: -10, + ), + throwsArgumentError, + ); + + expect( + ImagePicker.pickVideo( + source: ImageSource.camera, + quality: VideoQuality.Low, + durationInSeconds: -10, + ), + throwsArgumentError, + ); + }); + test('handles a null image path response gracefully', () async { channel.setMockMethodCallHandler((MethodCall methodCall) => null);