diff --git a/packages/image_picker/image_picker_android/CHANGELOG.md b/packages/image_picker/image_picker_android/CHANGELOG.md index b9ca0c5533f..77b8879117a 100644 --- a/packages/image_picker/image_picker_android/CHANGELOG.md +++ b/packages/image_picker/image_picker_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.8.6+1 + +* Refactors code in preparation for adopting Pigeon. + ## 0.8.6 * Adds `usePhotoPickerAndroid` options. diff --git a/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImageOutputOptions.java b/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImageOutputOptions.java new file mode 100644 index 00000000000..89648dcd24b --- /dev/null +++ b/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImageOutputOptions.java @@ -0,0 +1,29 @@ +// 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. + +package io.flutter.plugins.imagepicker; + +import androidx.annotation.Nullable; + +/** Stores settings for image output options. */ +public class ImageOutputOptions { + /** The maximum width of the image, if the width should be constrained. */ + @Nullable public final Double maxWidth; + /** The maximum height of the image, if the width should be constrained. */ + @Nullable public final Double maxHeight; + /** + * The output quality of the image, as a number from 0 to 100. + * + *

Defaults to 100. + */ + final int quality; + + public ImageOutputOptions( + @Nullable Double maxWidth, @Nullable Double maxHeight, @Nullable Integer quality) { + this.maxWidth = maxWidth; + this.maxHeight = maxHeight; + // Treat any invalid value as full quality. + this.quality = quality == null || quality < 0 || quality > 100 ? 100 : quality; + } +} diff --git a/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java b/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java index 983dbabf66c..86e314d44e0 100644 --- a/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java +++ b/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java @@ -9,7 +9,6 @@ import android.net.Uri; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; -import io.flutter.plugin.common.MethodCall; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -17,6 +16,10 @@ import java.util.Set; class ImagePickerCache { + public enum CacheType { + IMAGE, + VIDEO + } static final String MAP_KEY_PATH = "path"; static final String MAP_KEY_PATH_LIST = "pathList"; @@ -53,44 +56,31 @@ class ImagePickerCache { prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); } - void saveTypeWithMethodCallName(String methodCallName) { - if (methodCallName.equals(ImagePickerPlugin.METHOD_CALL_IMAGE) - | methodCallName.equals(ImagePickerPlugin.METHOD_CALL_MULTI_IMAGE)) { - setType("image"); - } else if (methodCallName.equals(ImagePickerPlugin.METHOD_CALL_VIDEO)) { - setType("video"); + void saveType(CacheType type) { + switch (type) { + case IMAGE: + setType("image"); + break; + case VIDEO: + setType("video"); + break; } } private void setType(String type) { - prefs.edit().putString(SHARED_PREFERENCE_TYPE_KEY, type).apply(); } - void saveDimensionWithMethodCall(MethodCall methodCall) { - Double maxWidth = methodCall.argument(MAP_KEY_MAX_WIDTH); - Double maxHeight = methodCall.argument(MAP_KEY_MAX_HEIGHT); - int imageQuality = - methodCall.argument(MAP_KEY_IMAGE_QUALITY) == null - ? 100 - : (int) methodCall.argument(MAP_KEY_IMAGE_QUALITY); - - setMaxDimension(maxWidth, maxHeight, imageQuality); - } - - private void setMaxDimension(Double maxWidth, Double maxHeight, int imageQuality) { + void saveDimensionWithOutputOptions(ImageOutputOptions options) { SharedPreferences.Editor editor = prefs.edit(); - if (maxWidth != null) { - editor.putLong(SHARED_PREFERENCE_MAX_WIDTH_KEY, Double.doubleToRawLongBits(maxWidth)); - } - if (maxHeight != null) { - editor.putLong(SHARED_PREFERENCE_MAX_HEIGHT_KEY, Double.doubleToRawLongBits(maxHeight)); + if (options.maxWidth != null) { + editor.putLong(SHARED_PREFERENCE_MAX_WIDTH_KEY, Double.doubleToRawLongBits(options.maxWidth)); } - if (imageQuality > -1 && imageQuality < 101) { - editor.putInt(SHARED_PREFERENCE_IMAGE_QUALITY_KEY, imageQuality); - } else { - editor.putInt(SHARED_PREFERENCE_IMAGE_QUALITY_KEY, 100); + if (options.maxHeight != null) { + editor.putLong( + SHARED_PREFERENCE_MAX_HEIGHT_KEY, Double.doubleToRawLongBits(options.maxHeight)); } + editor.putInt(SHARED_PREFERENCE_IMAGE_QUALITY_KEY, options.quality); editor.apply(); } diff --git a/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java b/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java index 8f89e05276c..a28611e5b5d 100644 --- a/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java +++ b/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java @@ -17,11 +17,11 @@ import android.provider.MediaStore; import androidx.activity.result.PickVisualMediaRequest; import androidx.activity.result.contract.ActivityResultContracts; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.core.app.ActivityCompat; import androidx.core.content.FileProvider; -import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.PluginRegistry; import java.io.File; @@ -37,8 +37,8 @@ *

When invoked, both the {@link #chooseImageFromGallery} and {@link #takeImageWithCamera} * methods go through the same steps: * - *

1. Check for an existing {@link #pendingResult}. If a previous pendingResult exists, this - * means that the chooseImageFromGallery() or takeImageWithCamera() method was called at least + *

1. Check for an existing {@link #pendingCallState}. If a previous pendingCallState exists, + * this means that the chooseImageFromGallery() or takeImageWithCamera() method was called at least * twice. In this case, stop executing and finish with an error. * *

2. Check that a required runtime permission has been granted. The takeImageWithCamera() method @@ -85,6 +85,22 @@ public enum CameraDevice { FRONT } + /** Holds call state during intent handling. */ + private static class PendingCallState { + public final @Nullable ImageOutputOptions imageOptions; + public final @Nullable VideoOptions videoOptions; + public final @NonNull MethodChannel.Result result; + + private PendingCallState( + @Nullable ImageOutputOptions imageOptions, + @Nullable VideoOptions videoOptions, + @NonNull MethodChannel.Result result) { + this.imageOptions = imageOptions; + this.videoOptions = videoOptions; + this.result = result; + } + } + @VisibleForTesting final String fileProviderName; private final Activity activity; @@ -115,8 +131,7 @@ interface OnPathReadyListener { } private Uri pendingCameraMediaUri; - private MethodChannel.Result pendingResult; - private MethodCall methodCall; + private @Nullable PendingCallState pendingCallState; public ImagePickerDelegate( final Activity activity, @@ -129,6 +144,7 @@ public ImagePickerDelegate( imageResizer, null, null, + null, cache, new PermissionManager() { @Override @@ -179,8 +195,9 @@ public void onScanCompleted(String path, Uri uri) { final Activity activity, final File externalFilesDirectory, final ImageResizer imageResizer, - final MethodChannel.Result result, - final MethodCall methodCall, + final @Nullable ImageOutputOptions pendingImageOptions, + final @Nullable VideoOptions pendingVideoOptions, + final @Nullable MethodChannel.Result result, final ImagePickerCache cache, final PermissionManager permissionManager, final FileUriResolver fileUriResolver, @@ -189,8 +206,10 @@ public void onScanCompleted(String path, Uri uri) { this.externalFilesDirectory = externalFilesDirectory; this.imageResizer = imageResizer; this.fileProviderName = activity.getPackageName() + ".flutter.image_provider"; - this.pendingResult = result; - this.methodCall = methodCall; + if (result != null) { + this.pendingCallState = + new PendingCallState(pendingImageOptions, pendingVideoOptions, result); + } this.permissionManager = permissionManager; this.fileUriResolver = fileUriResolver; this.fileUtils = fileUtils; @@ -207,12 +226,17 @@ CameraDevice getCameraDevice() { // Save the state of the image picker so it can be retrieved with `retrieveLostImage`. void saveStateBeforeResult() { - if (methodCall == null) { + if (pendingCallState == null) { return; } - cache.saveTypeWithMethodCallName(methodCall.method); - cache.saveDimensionWithMethodCall(methodCall); + cache.saveType( + pendingCallState.imageOptions != null + ? ImagePickerCache.CacheType.IMAGE + : ImagePickerCache.CacheType.VIDEO); + if (pendingCallState.imageOptions != null) { + cache.saveDimensionWithOutputOptions(pendingCallState.imageOptions); + } if (pendingCameraMediaUri != null) { cache.savePendingCameraMediaUriPath(pendingCameraMediaUri); } @@ -228,10 +252,8 @@ void retrieveLostImage(MethodChannel.Result result) { for (String path : pathList) { Double maxWidth = (Double) resultMap.get(ImagePickerCache.MAP_KEY_MAX_WIDTH); Double maxHeight = (Double) resultMap.get(ImagePickerCache.MAP_KEY_MAX_HEIGHT); - int imageQuality = - resultMap.get(ImagePickerCache.MAP_KEY_IMAGE_QUALITY) == null - ? 100 - : (int) resultMap.get(ImagePickerCache.MAP_KEY_IMAGE_QUALITY); + Integer boxedImageQuality = (Integer) resultMap.get(ImagePickerCache.MAP_KEY_IMAGE_QUALITY); + int imageQuality = boxedImageQuality == null ? 100 : boxedImageQuality; newPathList.add(imageResizer.resizeImageIfNeeded(path, maxWidth, maxHeight, imageQuality)); } @@ -246,18 +268,13 @@ void retrieveLostImage(MethodChannel.Result result) { cache.clear(); } - public void chooseVideoFromGallery(MethodCall methodCall, MethodChannel.Result result) { - if (!setPendingMethodCallAndResult(methodCall, result)) { + public void chooseVideoFromGallery( + VideoOptions options, boolean usePhotoPicker, MethodChannel.Result result) { + if (!setPendingOptionsAndResult(null, options, result)) { finishWithAlreadyActiveError(result); return; } - Boolean usePhotoPicker = methodCall.argument("useAndroidPhotoPicker"); - - if (usePhotoPicker == null) { - usePhotoPicker = false; - } - launchPickVideoFromGalleryIntent(usePhotoPicker); } @@ -279,8 +296,8 @@ private void launchPickVideoFromGalleryIntent(Boolean useAndroidPhotoPicker) { activity.startActivityForResult(pickVideoIntent, REQUEST_CODE_CHOOSE_VIDEO_FROM_GALLERY); } - public void takeVideoWithCamera(MethodCall methodCall, MethodChannel.Result result) { - if (!setPendingMethodCallAndResult(methodCall, result)) { + public void takeVideoWithCamera(VideoOptions options, MethodChannel.Result result) { + if (!setPendingOptionsAndResult(null, options, result)) { finishWithAlreadyActiveError(result); return; } @@ -297,8 +314,10 @@ public void takeVideoWithCamera(MethodCall methodCall, MethodChannel.Result resu private void launchTakeVideoWithCameraIntent() { Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); - if (this.methodCall != null && this.methodCall.argument("maxDuration") != null) { - int maxSeconds = this.methodCall.argument("maxDuration"); + if (pendingCallState != null + && pendingCallState.videoOptions != null + && pendingCallState.videoOptions.maxDuration != null) { + int maxSeconds = pendingCallState.videoOptions.maxDuration; intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, maxSeconds); } if (cameraDevice == CameraDevice.FRONT) { @@ -326,33 +345,23 @@ private void launchTakeVideoWithCameraIntent() { } } - public void chooseImageFromGallery(MethodCall methodCall, MethodChannel.Result result) { - if (!setPendingMethodCallAndResult(methodCall, result)) { + public void chooseImageFromGallery( + @NonNull ImageOutputOptions options, boolean usePhotoPicker, MethodChannel.Result result) { + if (!setPendingOptionsAndResult(options, null, result)) { finishWithAlreadyActiveError(result); return; } - Boolean usePhotoPicker = methodCall.argument("useAndroidPhotoPicker"); - - if (usePhotoPicker == null) { - usePhotoPicker = false; - } - launchPickImageFromGalleryIntent(usePhotoPicker); } - public void chooseMultiImageFromGallery(MethodCall methodCall, MethodChannel.Result result) { - if (!setPendingMethodCallAndResult(methodCall, result)) { + public void chooseMultiImageFromGallery( + @NonNull ImageOutputOptions options, boolean usePhotoPicker, MethodChannel.Result result) { + if (!setPendingOptionsAndResult(options, null, result)) { finishWithAlreadyActiveError(result); return; } - Boolean usePhotoPicker = methodCall.argument("useAndroidPhotoPicker"); - - if (usePhotoPicker == null) { - usePhotoPicker = false; - } - launchMultiPickImageFromGalleryIntent(usePhotoPicker); } @@ -395,8 +404,9 @@ private void launchMultiPickImageFromGalleryIntent(Boolean useAndroidPhotoPicker pickMultiImageIntent, REQUEST_CODE_CHOOSE_MULTI_IMAGE_FROM_GALLERY); } - public void takeImageWithCamera(MethodCall methodCall, MethodChannel.Result result) { - if (!setPendingMethodCallAndResult(methodCall, result)) { + public void takeImageWithCamera( + @NonNull ImageOutputOptions options, MethodChannel.Result result) { + if (!setPendingOptionsAndResult(options, null, result)) { finishWithAlreadyActiveError(result); return; } @@ -619,10 +629,10 @@ public void onPathReady(String path) { private void handleMultiImageResult( ArrayList paths, boolean shouldDeleteOriginalIfScaled) { - if (methodCall != null) { + if (pendingCallState != null && pendingCallState.imageOptions != null) { ArrayList finalPath = new ArrayList<>(); for (int i = 0; i < paths.size(); i++) { - String finalImagePath = getResizedImagePath(paths.get(i)); + String finalImagePath = getResizedImagePath(paths.get(i), pendingCallState.imageOptions); //delete original file if scaled if (finalImagePath != null @@ -639,8 +649,8 @@ private void handleMultiImageResult( } private void handleImageResult(String path, boolean shouldDeleteOriginalIfScaled) { - if (methodCall != null) { - String finalImagePath = getResizedImagePath(path); + if (pendingCallState != null && pendingCallState.imageOptions != null) { + String finalImagePath = getResizedImagePath(path, pendingCallState.imageOptions); //delete original file if scaled if (finalImagePath != null && !finalImagePath.equals(path) && shouldDeleteOriginalIfScaled) { new File(path).delete(); @@ -651,26 +661,24 @@ private void handleImageResult(String path, boolean shouldDeleteOriginalIfScaled } } - private String getResizedImagePath(String path) { - Double maxWidth = methodCall.argument("maxWidth"); - Double maxHeight = methodCall.argument("maxHeight"); - Integer imageQuality = methodCall.argument("imageQuality"); - - return imageResizer.resizeImageIfNeeded(path, maxWidth, maxHeight, imageQuality); + private String getResizedImagePath(String path, @NonNull ImageOutputOptions outputOptions) { + return imageResizer.resizeImageIfNeeded( + path, outputOptions.maxWidth, outputOptions.maxHeight, outputOptions.quality); } private void handleVideoResult(String path) { finishWithSuccess(path); } - private boolean setPendingMethodCallAndResult( - MethodCall methodCall, MethodChannel.Result result) { - if (pendingResult != null) { + private boolean setPendingOptionsAndResult( + @Nullable ImageOutputOptions imageOptions, + @Nullable VideoOptions videoOptions, + @NonNull MethodChannel.Result result) { + if (pendingCallState != null) { return false; } - this.methodCall = methodCall; - pendingResult = result; + pendingCallState = new PendingCallState(imageOptions, videoOptions, result); // Clean up cache if a new image picker is launched. cache.clear(); @@ -683,7 +691,7 @@ private boolean setPendingMethodCallAndResult( // A null imagePath indicates that the image picker was cancelled without // selection. private void finishWithSuccess(@Nullable String imagePath) { - if (pendingResult == null) { + if (pendingCallState == null) { // Only save data for later retrieval if something was actually selected. if (imagePath != null) { ArrayList pathList = new ArrayList<>(); @@ -692,17 +700,17 @@ private void finishWithSuccess(@Nullable String imagePath) { } return; } - pendingResult.success(imagePath); - clearMethodCallAndResult(); + pendingCallState.result.success(imagePath); + pendingCallState = null; } private void finishWithListSuccess(ArrayList imagePaths) { - if (pendingResult == null) { + if (pendingCallState == null) { cache.saveResult(imagePaths, null, null); return; } - pendingResult.success(imagePaths); - clearMethodCallAndResult(); + pendingCallState.result.success(imagePaths); + pendingCallState = null; } private void finishWithAlreadyActiveError(MethodChannel.Result result) { @@ -710,17 +718,12 @@ private void finishWithAlreadyActiveError(MethodChannel.Result result) { } private void finishWithError(String errorCode, String errorMessage) { - if (pendingResult == null) { + if (pendingCallState == null) { cache.saveResult(null, errorCode, errorMessage); return; } - pendingResult.error(errorCode, errorMessage, null); - clearMethodCallAndResult(); - } - - private void clearMethodCallAndResult() { - methodCall = null; - pendingResult = null; + pendingCallState.result.error(errorCode, errorMessage, null); + pendingCallState = null; } private void useFrontCamera(Intent intent) { diff --git a/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerPlugin.java b/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerPlugin.java index a1ee1e2f404..4a4b3114c5b 100644 --- a/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerPlugin.java +++ b/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerPlugin.java @@ -351,31 +351,49 @@ public void onMethodCall(MethodCall call, MethodChannel.Result rawResult) { } delegate.setCameraDevice(device); } + + Boolean usePhotoPicker = call.argument("useAndroidPhotoPicker"); + if (usePhotoPicker == null) { + usePhotoPicker = false; + } + switch (call.method) { case METHOD_CALL_IMAGE: imageSource = call.argument("source"); + ImageOutputOptions imageOptions = + new ImageOutputOptions( + call.argument("maxWidth"), + call.argument("maxHeight"), + call.argument("imageQuality")); switch (imageSource) { case SOURCE_GALLERY: - delegate.chooseImageFromGallery(call, result); + delegate.chooseImageFromGallery(imageOptions, usePhotoPicker, result); break; case SOURCE_CAMERA: - delegate.takeImageWithCamera(call, result); + delegate.takeImageWithCamera(imageOptions, result); break; default: throw new IllegalArgumentException("Invalid image source: " + imageSource); } break; case METHOD_CALL_MULTI_IMAGE: - delegate.chooseMultiImageFromGallery(call, result); + delegate.chooseMultiImageFromGallery( + new ImageOutputOptions( + call.argument("maxWidth"), + call.argument("maxHeight"), + call.argument("imageQuality")), + usePhotoPicker, + result); break; case METHOD_CALL_VIDEO: imageSource = call.argument("source"); + VideoOptions videoOptions = new VideoOptions(call.argument("maxDuration")); switch (imageSource) { case SOURCE_GALLERY: - delegate.chooseVideoFromGallery(call, result); + delegate.chooseVideoFromGallery(videoOptions, usePhotoPicker, result); break; case SOURCE_CAMERA: - delegate.takeVideoWithCamera(call, result); + delegate.takeVideoWithCamera(videoOptions, result); break; default: throw new IllegalArgumentException("Invalid video source: " + imageSource); diff --git a/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImageResizer.java b/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImageResizer.java index 2a93785678a..e65f0ad07a1 100644 --- a/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImageResizer.java +++ b/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/ImageResizer.java @@ -29,16 +29,12 @@ class ImageResizer { *

If no resizing is needed, returns the path for the original image. */ String resizeImageIfNeeded( - String imagePath, - @Nullable Double maxWidth, - @Nullable Double maxHeight, - @Nullable Integer imageQuality) { + String imagePath, @Nullable Double maxWidth, @Nullable Double maxHeight, int imageQuality) { Bitmap bmp = decodeFile(imagePath); if (bmp == null) { return null; } - boolean shouldScale = - maxWidth != null || maxHeight != null || isImageQualityValid(imageQuality); + boolean shouldScale = maxWidth != null || maxHeight != null || imageQuality < 100; if (!shouldScale) { return imagePath; } @@ -54,15 +50,11 @@ String resizeImageIfNeeded( } private File resizedImage( - Bitmap bmp, Double maxWidth, Double maxHeight, Integer imageQuality, String outputImageName) + Bitmap bmp, Double maxWidth, Double maxHeight, int imageQuality, String outputImageName) throws IOException { double originalWidth = bmp.getWidth() * 1.0; double originalHeight = bmp.getHeight() * 1.0; - if (!isImageQualityValid(imageQuality)) { - imageQuality = 100; - } - boolean hasMaxWidth = maxWidth != null; boolean hasMaxHeight = maxHeight != null; @@ -128,10 +120,6 @@ private Bitmap createScaledBitmap(Bitmap bmp, int width, int height, boolean fil return Bitmap.createScaledBitmap(bmp, width, height, filter); } - private boolean isImageQualityValid(Integer imageQuality) { - return imageQuality != null && imageQuality > 0 && imageQuality < 100; - } - private File createImageOnExternalDirectory(String name, Bitmap bitmap, int imageQuality) throws IOException { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); diff --git a/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/VideoOptions.java b/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/VideoOptions.java new file mode 100644 index 00000000000..e3d73204d45 --- /dev/null +++ b/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/VideoOptions.java @@ -0,0 +1,16 @@ +// 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. + +package io.flutter.plugins.imagepicker; + +import androidx.annotation.Nullable; + +/** Stores settings for video selection and output options. */ +public class VideoOptions { + @Nullable public final Integer maxDuration; + + public VideoOptions(@Nullable Integer maxDuration) { + this.maxDuration = maxDuration; + } +} diff --git a/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/ImagePickerCacheTest.java b/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/ImagePickerCacheTest.java index 7d871665978..01bdd6768dc 100644 --- a/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/ImagePickerCacheTest.java +++ b/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/ImagePickerCacheTest.java @@ -4,7 +4,6 @@ package io.flutter.plugins.imagepicker; -import static io.flutter.plugins.imagepicker.ImagePickerCache.MAP_KEY_IMAGE_QUALITY; import static io.flutter.plugins.imagepicker.ImagePickerCache.SHARED_PREFERENCES_NAME; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsEqual.equalTo; @@ -16,7 +15,6 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.pm.PackageManager; -import io.flutter.plugin.common.MethodCall; import java.util.HashMap; import java.util.Map; import org.junit.After; @@ -26,12 +24,9 @@ import org.mockito.MockitoAnnotations; public class ImagePickerCacheTest { - private static final int IMAGE_QUALITY = 90; - @Mock Activity mockActivity; @Mock SharedPreferences mockPreference; @Mock SharedPreferences.Editor mockEditor; - @Mock MethodCall mockMethodCall; static Map preferenceStorage; @@ -106,16 +101,15 @@ public void tearDown() throws Exception { } @Test - public void ImageCache_ShouldBeAbleToSetAndGetQuality() { - when(mockMethodCall.argument(MAP_KEY_IMAGE_QUALITY)).thenReturn(IMAGE_QUALITY); + public void imageCache_shouldBeAbleToSetAndGetQuality() { + final int quality = 90; ImagePickerCache cache = new ImagePickerCache(mockActivity); - cache.saveDimensionWithMethodCall(mockMethodCall); + cache.saveDimensionWithOutputOptions(new ImageOutputOptions(null, null, quality)); Map resultMap = cache.getCacheMap(); int imageQuality = (int) resultMap.get(ImagePickerCache.MAP_KEY_IMAGE_QUALITY); - assertThat(imageQuality, equalTo(IMAGE_QUALITY)); + assertThat(imageQuality, equalTo(quality)); - when(mockMethodCall.argument(MAP_KEY_IMAGE_QUALITY)).thenReturn(null); - cache.saveDimensionWithMethodCall(mockMethodCall); + cache.saveDimensionWithOutputOptions(new ImageOutputOptions(null, null, null)); Map resultMapWithDefaultQuality = cache.getCacheMap(); int defaultImageQuality = (int) resultMapWithDefaultQuality.get(ImagePickerCache.MAP_KEY_IMAGE_QUALITY); diff --git a/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java b/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java index f8fb4dbb241..80666e963e2 100644 --- a/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java +++ b/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java @@ -26,7 +26,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; -import io.flutter.plugin.common.MethodCall; +import androidx.annotation.Nullable; import io.flutter.plugin.common.MethodChannel; import java.io.File; import java.util.ArrayList; @@ -48,12 +48,14 @@ public class ImagePickerDelegateTest { private static final Double WIDTH = 10.0; private static final Double HEIGHT = 10.0; - private static final Double MAX_DURATION = 10.0; + private static final int MAX_DURATION = 10; private static final Integer IMAGE_QUALITY = 90; + private static final ImageOutputOptions DEFAULT_IMAGE_OPTIONS = + new ImageOutputOptions(null, null, null); + private static final VideoOptions DEFAULT_VIDEO_OPTIONS = new VideoOptions(null); @Mock Activity mockActivity; @Mock ImageResizer mockImageResizer; - @Mock MethodCall mockMethodCall; @Mock MethodChannel.Result mockResult; @Mock ImagePickerDelegate.PermissionManager mockPermissionManager; @Mock FileUtils mockFileUtils; @@ -92,15 +94,15 @@ public void setUp() { when(mockFileUtils.getPathFromUri(any(Context.class), any(Uri.class))) .thenReturn("pathFromUri"); - when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, null, null)) + when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, null, 100)) .thenReturn("originalPath"); when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, null, IMAGE_QUALITY)) .thenReturn("originalPath"); - when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, HEIGHT, null)) + when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, HEIGHT, 100)) .thenReturn("scaledPath"); - when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, null, null)) + when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, null, 100)) .thenReturn("scaledPath"); - when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, HEIGHT, null)) + when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, HEIGHT, 100)) .thenReturn("scaledPath"); mockFileUriResolver = new MockFileUriResolver(); @@ -122,20 +124,23 @@ public void whenConstructed_setsCorrectFileProviderName() { } @Test - public void chooseImageFromGallery_WhenPendingResultExists_FinishesWithAlreadyActiveError() { - ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); + public void chooseImageFromGallery_whenPendingResultExists_finishesWithAlreadyActiveError() { + ImagePickerDelegate delegate = + createDelegateWithPendingResultAndOptions(DEFAULT_IMAGE_OPTIONS, null); - delegate.chooseImageFromGallery(mockMethodCall, mockResult); + delegate.chooseImageFromGallery(new ImageOutputOptions(null, null, null), false, mockResult); verifyFinishedWithAlreadyActiveError(); verifyNoMoreInteractions(mockResult); } @Test - public void chooseMultiImageFromGallery_WhenPendingResultExists_FinishesWithAlreadyActiveError() { - ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); + public void chooseMultiImageFromGallery_whenPendingResultExists_finishesWithAlreadyActiveError() { + ImagePickerDelegate delegate = + createDelegateWithPendingResultAndOptions(DEFAULT_IMAGE_OPTIONS, null); - delegate.chooseMultiImageFromGallery(mockMethodCall, mockResult); + delegate.chooseMultiImageFromGallery( + new ImageOutputOptions(null, null, null), false, mockResult); verifyFinishedWithAlreadyActiveError(); verifyNoMoreInteractions(mockResult); @@ -144,12 +149,12 @@ public void chooseMultiImageFromGallery_WhenPendingResultExists_FinishesWithAlre @Test @Config(sdk = 30) public void - chooseImageFromGallery_WhenHasExternalStoragePermission_LaunchesChooseFromGalleryIntent() { + chooseImageFromGallery_whenHasExternalStoragePermission_launchesChooseFromGalleryIntent() { when(mockPermissionManager.isPermissionGranted(Manifest.permission.READ_EXTERNAL_STORAGE)) .thenReturn(true); ImagePickerDelegate delegate = createDelegate(); - delegate.chooseImageFromGallery(mockMethodCall, mockResult); + delegate.chooseImageFromGallery(new ImageOutputOptions(null, null, null), false, mockResult); verify(mockActivity) .startActivityForResult( @@ -159,13 +164,12 @@ public void chooseMultiImageFromGallery_WhenPendingResultExists_FinishesWithAlre @Test @Config(minSdk = 33) public void - chooseImageFromGallery_WithPhotoPicker_WhenHasExternalStoragePermission_LaunchesChooseFromGalleryIntent() { + chooseImageFromGallery_WithPhotoPicker_whenHasExternalStoragePermission_launchesChooseFromGalleryIntent() { when(mockPermissionManager.isPermissionGranted(Manifest.permission.READ_EXTERNAL_STORAGE)) .thenReturn(true); - when(mockMethodCall.argument("useAndroidPhotoPicker")).thenReturn(true); ImagePickerDelegate delegate = createDelegate(); - delegate.chooseImageFromGallery(mockMethodCall, mockResult); + delegate.chooseImageFromGallery(new ImageOutputOptions(null, null, null), true, mockResult); verify(mockActivity) .startActivityForResult( @@ -175,13 +179,13 @@ public void chooseMultiImageFromGallery_WhenPendingResultExists_FinishesWithAlre @Test @Config(sdk = 30) public void - chooseMultiImageFromGallery_WhenHasExternalStoragePermission_LaunchesChooseFromGalleryIntent() { + chooseMultiImageFromGallery_whenHasExternalStoragePermission_launchesChooseFromGalleryIntent() { when(mockPermissionManager.isPermissionGranted(Manifest.permission.READ_EXTERNAL_STORAGE)) .thenReturn(true); - when(mockMethodCall.argument("useAndroidPhotoPicker")).thenReturn(true); ImagePickerDelegate delegate = createDelegate(); - delegate.chooseMultiImageFromGallery(mockMethodCall, mockResult); + delegate.chooseMultiImageFromGallery( + new ImageOutputOptions(null, null, null), true, mockResult); verify(mockActivity) .startActivityForResult( @@ -192,13 +196,13 @@ public void chooseMultiImageFromGallery_WhenPendingResultExists_FinishesWithAlre @Test @Config(minSdk = 33) public void - chooseMultiImageFromGallery_WithPhotoPicker_WhenHasExternalStoragePermission_LaunchesChooseFromGalleryIntent() { + chooseMultiImageFromGallery_WithPhotoPicker_whenHasExternalStoragePermission_launchesChooseFromGalleryIntent() { when(mockPermissionManager.isPermissionGranted(Manifest.permission.READ_EXTERNAL_STORAGE)) .thenReturn(true); - when(mockMethodCall.argument("useAndroidPhotoPicker")).thenReturn(true); ImagePickerDelegate delegate = createDelegate(); - delegate.chooseMultiImageFromGallery(mockMethodCall, mockResult); + delegate.chooseMultiImageFromGallery( + new ImageOutputOptions(null, null, null), false, mockResult); verify(mockActivity) .startActivityForResult( @@ -209,13 +213,12 @@ public void chooseMultiImageFromGallery_WhenPendingResultExists_FinishesWithAlre @Test @Config(sdk = 30) public void - chooseVideoFromGallery_WhenHasExternalStoragePermission_LaunchesChooseFromGalleryIntent() { + chooseVideoFromGallery_whenHasExternalStoragePermission_launchesChooseFromGalleryIntent() { when(mockPermissionManager.isPermissionGranted(Manifest.permission.READ_EXTERNAL_STORAGE)) .thenReturn(true); - when(mockMethodCall.argument("useAndroidPhotoPicker")).thenReturn(true); ImagePickerDelegate delegate = createDelegate(); - delegate.chooseVideoFromGallery(mockMethodCall, mockResult); + delegate.chooseVideoFromGallery(new VideoOptions(null), true, mockResult); verify(mockActivity) .startActivityForResult( @@ -225,13 +228,12 @@ public void chooseMultiImageFromGallery_WhenPendingResultExists_FinishesWithAlre @Test @Config(minSdk = 33) public void - chooseVideoFromGallery_WithPhotoPicker_WhenHasExternalStoragePermission_LaunchesChooseFromGalleryIntent() { + chooseVideoFromGallery_WithPhotoPicker_whenHasExternalStoragePermission_launchesChooseFromGalleryIntent() { when(mockPermissionManager.isPermissionGranted(Manifest.permission.READ_EXTERNAL_STORAGE)) .thenReturn(true); - when(mockMethodCall.argument("useAndroidPhotoPicker")).thenReturn(true); ImagePickerDelegate delegate = createDelegate(); - delegate.chooseVideoFromGallery(mockMethodCall, mockResult); + delegate.chooseVideoFromGallery(new VideoOptions(null), true, mockResult); verify(mockActivity) .startActivityForResult( @@ -239,22 +241,23 @@ public void chooseMultiImageFromGallery_WhenPendingResultExists_FinishesWithAlre } @Test - public void takeImageWithCamera_WhenPendingResultExists_FinishesWithAlreadyActiveError() { - ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); + public void takeImageWithCamera_whenPendingResultExists_finishesWithAlreadyActiveError() { + ImagePickerDelegate delegate = + createDelegateWithPendingResultAndOptions(DEFAULT_IMAGE_OPTIONS, null); - delegate.takeImageWithCamera(mockMethodCall, mockResult); + delegate.takeImageWithCamera(new ImageOutputOptions(null, null, null), mockResult); verifyFinishedWithAlreadyActiveError(); verifyNoMoreInteractions(mockResult); } @Test - public void takeImageWithCamera_WhenHasNoCameraPermission_RequestsForPermission() { + public void takeImageWithCamera_whenHasNoCameraPermission_RequestsForPermission() { when(mockPermissionManager.isPermissionGranted(Manifest.permission.CAMERA)).thenReturn(false); when(mockPermissionManager.needRequestCameraPermission()).thenReturn(true); ImagePickerDelegate delegate = createDelegate(); - delegate.takeImageWithCamera(mockMethodCall, mockResult); + delegate.takeImageWithCamera(new ImageOutputOptions(null, null, null), mockResult); verify(mockPermissionManager) .askForPermission( @@ -262,11 +265,11 @@ public void takeImageWithCamera_WhenHasNoCameraPermission_RequestsForPermission( } @Test - public void takeImageWithCamera_WhenCameraPermissionNotPresent_RequestsForPermission() { + public void takeImageWithCamera_whenCameraPermissionNotPresent_RequestsForPermission() { when(mockPermissionManager.needRequestCameraPermission()).thenReturn(false); ImagePickerDelegate delegate = createDelegate(); - delegate.takeImageWithCamera(mockMethodCall, mockResult); + delegate.takeImageWithCamera(new ImageOutputOptions(null, null, null), mockResult); verify(mockActivity) .startActivityForResult( @@ -275,11 +278,11 @@ public void takeImageWithCamera_WhenCameraPermissionNotPresent_RequestsForPermis @Test public void - takeImageWithCamera_WhenHasCameraPermission_AndAnActivityCanHandleCameraIntent_LaunchesTakeWithCameraIntent() { + takeImageWithCamera_whenHasCameraPermission_andAnActivityCanHandleCameraIntent_launchesTakeWithCameraIntent() { when(mockPermissionManager.isPermissionGranted(Manifest.permission.CAMERA)).thenReturn(true); ImagePickerDelegate delegate = createDelegate(); - delegate.takeImageWithCamera(mockMethodCall, mockResult); + delegate.takeImageWithCamera(new ImageOutputOptions(null, null, null), mockResult); verify(mockActivity) .startActivityForResult( @@ -288,13 +291,13 @@ public void takeImageWithCamera_WhenCameraPermissionNotPresent_RequestsForPermis @Test public void - takeImageWithCamera_WhenHasCameraPermission_AndNoActivityToHandleCameraIntent_FinishesWithNoCamerasAvailableError() { + takeImageWithCamera_whenHasCameraPermission_andNoActivityToHandleCameraIntent_finishesWithNoCamerasAvailableError() { when(mockPermissionManager.isPermissionGranted(Manifest.permission.CAMERA)).thenReturn(true); doThrow(ActivityNotFoundException.class) .when(mockActivity) .startActivityForResult(any(Intent.class), anyInt()); ImagePickerDelegate delegate = createDelegate(); - delegate.takeImageWithCamera(mockMethodCall, mockResult); + delegate.takeImageWithCamera(new ImageOutputOptions(null, null, null), mockResult); verify(mockResult) .error("no_available_camera", "No cameras available for taking pictures.", null); @@ -302,11 +305,11 @@ public void takeImageWithCamera_WhenCameraPermissionNotPresent_RequestsForPermis } @Test - public void takeImageWithCamera_WritesImageToCacheDirectory() { + public void takeImageWithCamera_writesImageToCacheDirectory() { when(mockPermissionManager.isPermissionGranted(Manifest.permission.CAMERA)).thenReturn(true); ImagePickerDelegate delegate = createDelegate(); - delegate.takeImageWithCamera(mockMethodCall, mockResult); + delegate.takeImageWithCamera(new ImageOutputOptions(null, null, null), mockResult); mockStaticFile.verify( () -> File.createTempFile(any(), eq(".jpg"), eq(new File("/image_picker_cache"))), @@ -314,8 +317,9 @@ public void takeImageWithCamera_WritesImageToCacheDirectory() { } @Test - public void onRequestPermissionsResult_WhenCameraPermissionDenied_FinishesWithError() { - ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); + public void onRequestPermissionsResult_whenCameraPermissionDenied_finishesWithError() { + ImagePickerDelegate delegate = + createDelegateWithPendingResultAndOptions(DEFAULT_IMAGE_OPTIONS, null); delegate.onRequestPermissionsResult( ImagePickerDelegate.REQUEST_CAMERA_IMAGE_PERMISSION, @@ -328,9 +332,9 @@ public void onRequestPermissionsResult_WhenCameraPermissionDenied_FinishesWithEr @Test public void - onRequestTakeVideoPermissionsResult_WhenCameraPermissionGranted_LaunchesTakeVideoWithCameraIntent() { - - ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); + onRequestTakeVideoPermissionsResult_whenCameraPermissionGranted_launchesTakeVideoWithCameraIntent() { + ImagePickerDelegate delegate = + createDelegateWithPendingResultAndOptions(null, DEFAULT_VIDEO_OPTIONS); delegate.onRequestPermissionsResult( ImagePickerDelegate.REQUEST_CAMERA_VIDEO_PERMISSION, new String[] {Manifest.permission.CAMERA}, @@ -343,9 +347,9 @@ public void onRequestPermissionsResult_WhenCameraPermissionDenied_FinishesWithEr @Test public void - onRequestTakeImagePermissionsResult_WhenCameraPermissionGranted_LaunchesTakeWithCameraIntent() { - - ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); + onRequestTakeImagePermissionsResult_whenCameraPermissionGranted_launchesTakeWithCameraIntent() { + ImagePickerDelegate delegate = + createDelegateWithPendingResultAndOptions(DEFAULT_IMAGE_OPTIONS, null); delegate.onRequestPermissionsResult( ImagePickerDelegate.REQUEST_CAMERA_IMAGE_PERMISSION, new String[] {Manifest.permission.CAMERA}, @@ -357,8 +361,9 @@ public void onRequestPermissionsResult_WhenCameraPermissionDenied_FinishesWithEr } @Test - public void onActivityResult_WhenPickFromGalleryCanceled_FinishesWithNull() { - ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); + public void onActivityResult_whenPickFromGalleryCanceled_finishesWithNull() { + ImagePickerDelegate delegate = + createDelegateWithPendingResultAndOptions(DEFAULT_IMAGE_OPTIONS, null); delegate.onActivityResult( ImagePickerDelegate.REQUEST_CODE_CHOOSE_IMAGE_FROM_GALLERY, Activity.RESULT_CANCELED, null); @@ -368,7 +373,7 @@ public void onActivityResult_WhenPickFromGalleryCanceled_FinishesWithNull() { } @Test - public void onActivityResult_WhenPickFromGalleryCanceled_StoresNothingInCache() { + public void onActivityResult_whenPickFromGalleryCanceled_storesNothingInCache() { ImagePickerDelegate delegate = createDelegate(); delegate.onActivityResult( @@ -379,8 +384,9 @@ public void onActivityResult_WhenPickFromGalleryCanceled_StoresNothingInCache() @Test public void - onActivityResult_WhenImagePickedFromGallery_AndNoResizeNeeded_FinishesWithImagePath() { - ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); + onActivityResult_whenImagePickedFromGallery_andNoResizeNeeded_finishesWithImagePath() { + ImagePickerDelegate delegate = + createDelegateWithPendingResultAndOptions(DEFAULT_IMAGE_OPTIONS, null); delegate.onActivityResult( ImagePickerDelegate.REQUEST_CODE_CHOOSE_IMAGE_FROM_GALLERY, Activity.RESULT_OK, mockIntent); @@ -390,7 +396,7 @@ public void onActivityResult_WhenPickFromGalleryCanceled_StoresNothingInCache() } @Test - public void onActivityResult_WhenImagePickedFromGallery_AndNoResizeNeeded_StoresImageInCache() { + public void onActivityResult_whenImagePickedFromGallery_andNoResizeNeeded_StoresImageInCache() { ImagePickerDelegate delegate = createDelegate(); delegate.onActivityResult( @@ -404,10 +410,9 @@ public void onActivityResult_WhenImagePickedFromGallery_AndNoResizeNeeded_Stores @Test public void - onActivityResult_WhenImagePickedFromGallery_AndResizeNeeded_FinishesWithScaledImagePath() { - when(mockMethodCall.argument("maxWidth")).thenReturn(WIDTH); - - ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); + onActivityResult_whenImagePickedFromGallery_andResizeNeeded_finishesWithScaledImagePath() { + ImagePickerDelegate delegate = + createDelegateWithPendingResultAndOptions(new ImageOutputOptions(WIDTH, null, null), null); delegate.onActivityResult( ImagePickerDelegate.REQUEST_CODE_CHOOSE_IMAGE_FROM_GALLERY, Activity.RESULT_OK, mockIntent); @@ -417,10 +422,9 @@ public void onActivityResult_WhenImagePickedFromGallery_AndNoResizeNeeded_Stores @Test public void - onActivityResult_WhenVideoPickedFromGallery_AndResizeParametersSupplied_FinishesWithFilePath() { - when(mockMethodCall.argument("maxWidth")).thenReturn(WIDTH); - - ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); + onActivityResult_whenVideoPickedFromGallery_andResizeParametersSupplied_finishesWithFilePath() { + ImagePickerDelegate delegate = + createDelegateWithPendingResultAndOptions(new ImageOutputOptions(WIDTH, null, null), null); delegate.onActivityResult( ImagePickerDelegate.REQUEST_CODE_CHOOSE_VIDEO_FROM_GALLERY, Activity.RESULT_OK, mockIntent); @@ -429,8 +433,9 @@ public void onActivityResult_WhenImagePickedFromGallery_AndNoResizeNeeded_Stores } @Test - public void onActivityResult_WhenTakeImageWithCameraCanceled_FinishesWithNull() { - ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); + public void onActivityResult_whenTakeImageWithCameraCanceled_finishesWithNull() { + ImagePickerDelegate delegate = + createDelegateWithPendingResultAndOptions(DEFAULT_IMAGE_OPTIONS, null); delegate.onActivityResult( ImagePickerDelegate.REQUEST_CODE_TAKE_IMAGE_WITH_CAMERA, Activity.RESULT_CANCELED, null); @@ -440,8 +445,9 @@ public void onActivityResult_WhenTakeImageWithCameraCanceled_FinishesWithNull() } @Test - public void onActivityResult_WhenImageTakenWithCamera_AndNoResizeNeeded_FinishesWithImagePath() { - ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); + public void onActivityResult_whenImageTakenWithCamera_andNoResizeNeeded_finishesWithImagePath() { + ImagePickerDelegate delegate = + createDelegateWithPendingResultAndOptions(DEFAULT_IMAGE_OPTIONS, null); when(cache.retrievePendingCameraMediaUriPath()).thenReturn("testString"); delegate.onActivityResult( @@ -453,11 +459,11 @@ public void onActivityResult_WhenImageTakenWithCamera_AndNoResizeNeeded_Finishes @Test public void - onActivityResult_WhenImageTakenWithCamera_AndResizeNeeded_FinishesWithScaledImagePath() { - when(mockMethodCall.argument("maxWidth")).thenReturn(WIDTH); + onActivityResult_whenImageTakenWithCamera_andResizeNeeded_finishesWithScaledImagePath() { when(cache.retrievePendingCameraMediaUriPath()).thenReturn("testString"); - ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); + ImagePickerDelegate delegate = + createDelegateWithPendingResultAndOptions(new ImageOutputOptions(WIDTH, null, null), null); delegate.onActivityResult( ImagePickerDelegate.REQUEST_CODE_TAKE_IMAGE_WITH_CAMERA, Activity.RESULT_OK, mockIntent); @@ -467,11 +473,11 @@ public void onActivityResult_WhenImageTakenWithCamera_AndNoResizeNeeded_Finishes @Test public void - onActivityResult_WhenVideoTakenWithCamera_AndResizeParametersSupplied_FinishesWithFilePath() { - when(mockMethodCall.argument("maxWidth")).thenReturn(WIDTH); + onActivityResult_whenVideoTakenWithCamera_andResizeParametersSupplied_finishesWithFilePath() { when(cache.retrievePendingCameraMediaUriPath()).thenReturn("testString"); - ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); + ImagePickerDelegate delegate = + createDelegateWithPendingResultAndOptions(new ImageOutputOptions(WIDTH, null, null), null); delegate.onActivityResult( ImagePickerDelegate.REQUEST_CODE_TAKE_VIDEO_WITH_CAMERA, Activity.RESULT_OK, mockIntent); @@ -481,11 +487,11 @@ public void onActivityResult_WhenImageTakenWithCamera_AndNoResizeNeeded_Finishes @Test public void - onActivityResult_WhenVideoTakenWithCamera_AndMaxDurationParametersSupplied_FinishesWithFilePath() { - when(mockMethodCall.argument("maxDuration")).thenReturn(MAX_DURATION); + onActivityResult_whenVideoTakenWithCamera_andMaxDurationParametersSupplied_finishesWithFilePath() { when(cache.retrievePendingCameraMediaUriPath()).thenReturn("testString"); - ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); + ImagePickerDelegate delegate = + createDelegateWithPendingResultAndOptions(null, new VideoOptions(MAX_DURATION)); delegate.onActivityResult( ImagePickerDelegate.REQUEST_CODE_TAKE_VIDEO_WITH_CAMERA, Activity.RESULT_OK, mockIntent); @@ -529,19 +535,22 @@ private ImagePickerDelegate createDelegate() { mockImageResizer, null, null, + null, cache, mockPermissionManager, mockFileUriResolver, mockFileUtils); } - private ImagePickerDelegate createDelegateWithPendingResultAndMethodCall() { + private ImagePickerDelegate createDelegateWithPendingResultAndOptions( + @Nullable ImageOutputOptions imageOptions, @Nullable VideoOptions videoOptions) { return new ImagePickerDelegate( mockActivity, new File("/image_picker_cache"), mockImageResizer, + imageOptions, + videoOptions, mockResult, - mockMethodCall, cache, mockPermissionManager, mockFileUriResolver, diff --git a/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/ImagePickerPluginTest.java b/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/ImagePickerPluginTest.java index 328c964c860..8b9135128e7 100644 --- a/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/ImagePickerPluginTest.java +++ b/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/ImagePickerPluginTest.java @@ -21,6 +21,7 @@ import android.app.Activity; import android.app.Application; +import androidx.annotation.Nullable; import androidx.lifecycle.Lifecycle; import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; @@ -75,8 +76,8 @@ public void tearDown() throws Exception { } @Test - public void onMethodCall_WhenActivityIsNull_FinishesWithForegroundActivityRequiredError() { - MethodCall call = buildMethodCall(PICK_IMAGE, SOURCE_GALLERY); + public void onMethodCall_whenActivityIsNull_finishesWithForegroundActivityRequiredError() { + MethodCall call = buildMethodCall(PICK_IMAGE, SOURCE_GALLERY, false); ImagePickerPlugin imagePickerPluginWithNullActivity = new ImagePickerPlugin(mockImagePickerDelegate, null); imagePickerPluginWithNullActivity.onMethodCall(call, mockResult); @@ -86,7 +87,7 @@ public void onMethodCall_WhenActivityIsNull_FinishesWithForegroundActivityRequir } @Test - public void onMethodCall_WhenCalledWithUnknownMethod_ThrowsException() { + public void onMethodCall_whenCalledWithUnknownMethod_throwsException() { IllegalArgumentException e = assertThrows( IllegalArgumentException.class, @@ -97,43 +98,59 @@ public void onMethodCall_WhenCalledWithUnknownMethod_ThrowsException() { } @Test - public void onMethodCall_WhenCalledWithUnknownImageSource_ThrowsException() { + public void onMethodCall_whenCalledWithUnknownImageSource_throwsException() { IllegalArgumentException e = assertThrows( IllegalArgumentException.class, - () -> plugin.onMethodCall(buildMethodCall(PICK_IMAGE, -1), mockResult)); + () -> plugin.onMethodCall(buildMethodCall(PICK_IMAGE, -1, false), mockResult)); assertEquals(e.getMessage(), "Invalid image source: -1"); verifyNoInteractions(mockImagePickerDelegate); verifyNoInteractions(mockResult); } @Test - public void onMethodCall_WhenSourceIsGallery_InvokesChooseImageFromGallery() { - MethodCall call = buildMethodCall(PICK_IMAGE, SOURCE_GALLERY); + public void onMethodCall_whenSourceIsGallery_invokesChooseImageFromGallery() { + MethodCall call = buildMethodCall(PICK_IMAGE, SOURCE_GALLERY, false); plugin.onMethodCall(call, mockResult); - verify(mockImagePickerDelegate).chooseImageFromGallery(eq(call), any()); + verify(mockImagePickerDelegate).chooseImageFromGallery(any(), eq(false), any()); verifyNoInteractions(mockResult); } @Test - public void onMethodCall_InvokesChooseMultiImageFromGallery() { + public void onMethodCall_whenSourceIsGalleryUsingPhotoPicker_invokesChooseImageFromGallery() { + MethodCall call = buildMethodCall(PICK_IMAGE, SOURCE_GALLERY, true); + plugin.onMethodCall(call, mockResult); + verify(mockImagePickerDelegate).chooseImageFromGallery(any(), eq(true), any()); + verifyNoInteractions(mockResult); + } + + @Test + public void onMethodCall_invokesChooseMultiImageFromGallery() { MethodCall call = buildMethodCall(PICK_MULTI_IMAGE); plugin.onMethodCall(call, mockResult); - verify(mockImagePickerDelegate).chooseMultiImageFromGallery(eq(call), any()); + verify(mockImagePickerDelegate).chooseMultiImageFromGallery(any(), eq(false), any()); + verifyNoInteractions(mockResult); + } + + @Test + public void onMethodCall_usingPhotoPicker_invokesChooseMultiImageFromGallery() { + MethodCall call = buildMethodCall(PICK_MULTI_IMAGE, SOURCE_GALLERY, true); + plugin.onMethodCall(call, mockResult); + verify(mockImagePickerDelegate).chooseMultiImageFromGallery(any(), eq(true), any()); verifyNoInteractions(mockResult); } @Test - public void onMethodCall_WhenSourceIsCamera_InvokesTakeImageWithCamera() { - MethodCall call = buildMethodCall(PICK_IMAGE, SOURCE_CAMERA); + public void onMethodCall_whenSourceIsCamera_invokesTakeImageWithCamera() { + MethodCall call = buildMethodCall(PICK_IMAGE, SOURCE_CAMERA, null); plugin.onMethodCall(call, mockResult); - verify(mockImagePickerDelegate).takeImageWithCamera(eq(call), any()); + verify(mockImagePickerDelegate).takeImageWithCamera(any(), any()); verifyNoInteractions(mockResult); } @Test - public void onMethodCall_PickingImage_WhenSourceIsCamera_InvokesTakeImageWithCamera_RearCamera() { - MethodCall call = buildMethodCall(PICK_IMAGE, SOURCE_CAMERA); + public void onMethodCall_PickingImage_whenSourceIsCamera_invokesTakeImageWithCamera_RearCamera() { + MethodCall call = buildMethodCall(PICK_IMAGE, SOURCE_CAMERA, null); HashMap arguments = getArgumentMap(call); arguments.put("cameraDevice", 0); plugin.onMethodCall(call, mockResult); @@ -142,8 +159,8 @@ public void onMethodCall_PickingImage_WhenSourceIsCamera_InvokesTakeImageWithCam @Test public void - onMethodCall_PickingImage_WhenSourceIsCamera_InvokesTakeImageWithCamera_FrontCamera() { - MethodCall call = buildMethodCall(PICK_IMAGE, SOURCE_CAMERA); + onMethodCall_PickingImage_whenSourceIsCamera_invokesTakeImageWithCamera_FrontCamera() { + MethodCall call = buildMethodCall(PICK_IMAGE, SOURCE_CAMERA, null); HashMap arguments = getArgumentMap(call); arguments.put("cameraDevice", 1); plugin.onMethodCall(call, mockResult); @@ -151,8 +168,8 @@ public void onMethodCall_PickingImage_WhenSourceIsCamera_InvokesTakeImageWithCam } @Test - public void onMethodCall_PickingVideo_WhenSourceIsCamera_InvokesTakeImageWithCamera_RearCamera() { - MethodCall call = buildMethodCall(PICK_IMAGE, SOURCE_CAMERA); + public void onMethodCall_PickingVideo_whenSourceIsCamera_invokesTakeImageWithCamera_RearCamera() { + MethodCall call = buildMethodCall(PICK_IMAGE, SOURCE_CAMERA, null); HashMap arguments = getArgumentMap(call); arguments.put("cameraDevice", 0); plugin.onMethodCall(call, mockResult); @@ -161,8 +178,8 @@ public void onMethodCall_PickingVideo_WhenSourceIsCamera_InvokesTakeImageWithCam @Test public void - onMethodCall_PickingVideo_WhenSourceIsCamera_InvokesTakeImageWithCamera_FrontCamera() { - MethodCall call = buildMethodCall(PICK_IMAGE, SOURCE_CAMERA); + onMethodCall_PickingVideo_whenSourceIsCamera_invokesTakeImageWithCamera_FrontCamera() { + MethodCall call = buildMethodCall(PICK_IMAGE, SOURCE_CAMERA, null); HashMap arguments = getArgumentMap(call); arguments.put("cameraDevice", 1); plugin.onMethodCall(call, mockResult); @@ -170,7 +187,7 @@ public void onMethodCall_PickingVideo_WhenSourceIsCamera_InvokesTakeImageWithCam } @Test - public void onResiter_WhenAcitivityIsNull_ShouldNotCrash() { + public void onRegister_whenActivityIsNull_shouldNotCrash() { when(mockRegistrar.activity()).thenReturn(null); ImagePickerPlugin.registerWith((mockRegistrar)); assertTrue( @@ -178,14 +195,14 @@ public void onResiter_WhenAcitivityIsNull_ShouldNotCrash() { } @Test - public void onConstructor_WhenContextTypeIsActivity_ShouldNotCrash() { + public void onConstructor_whenContextTypeIsActivity_shouldNotCrash() { new ImagePickerPlugin(mockImagePickerDelegate, mockActivity); assertTrue( "No exception thrown when ImagePickerPlugin() ran with context instanceof Activity", true); } @Test - public void constructDelegate_ShouldUseInternalCacheDirectory() { + public void constructDelegate_shouldUseInternalCacheDirectory() { File mockDirectory = new File("/mockpath"); when(mockActivity.getCacheDir()).thenReturn(mockDirectory); @@ -199,7 +216,7 @@ public void constructDelegate_ShouldUseInternalCacheDirectory() { } @Test - public void onDetachedFromActivity_ShouldReleaseActivityState() { + public void onDetachedFromActivity_shouldReleaseActivityState() { final BinaryMessenger mockBinaryMessenger = mock(BinaryMessenger.class); when(mockPluginBinding.getBinaryMessenger()).thenReturn(mockBinaryMessenger); @@ -217,9 +234,13 @@ public void onDetachedFromActivity_ShouldReleaseActivityState() { assertNull(plugin.getActivityState()); } - private MethodCall buildMethodCall(String method, final int source) { + private MethodCall buildMethodCall( + String method, final int source, @Nullable Boolean usePhotoPicker) { final Map arguments = new HashMap<>(); arguments.put("source", source); + if (usePhotoPicker != null) { + arguments.put("useAndroidPhotoPicker", usePhotoPicker); + } return new MethodCall(method, arguments); } diff --git a/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/ImageResizerTest.java b/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/ImageResizerTest.java index a3710038379..2287c4abc17 100644 --- a/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/ImageResizerTest.java +++ b/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/ImageResizerTest.java @@ -48,34 +48,34 @@ public void tearDown() throws Exception { } @Test - public void onResizeImageIfNeeded_WhenQualityIsNull_ShoultNotResize_ReturnTheUnscaledFile() { - String outoutFile = resizer.resizeImageIfNeeded(imageFile.getPath(), null, null, null); - assertThat(outoutFile, equalTo(imageFile.getPath())); + public void onResizeImageIfNeeded_whenQualityIsMax_shouldNotResize_returnTheUnscaledFile() { + String outputFile = resizer.resizeImageIfNeeded(imageFile.getPath(), null, null, 100); + assertThat(outputFile, equalTo(imageFile.getPath())); } @Test - public void onResizeImageIfNeeded_WhenQualityIsNotNull_ShoulResize_ReturnResizedFile() { - String outoutFile = resizer.resizeImageIfNeeded(imageFile.getPath(), null, null, 50); - assertThat(outoutFile, equalTo(externalDirectory.getPath() + "/scaled_pngImage.png")); + public void onResizeImageIfNeeded_whenQualityIsNotMax_shouldResize_returnResizedFile() { + String outputFile = resizer.resizeImageIfNeeded(imageFile.getPath(), null, null, 50); + assertThat(outputFile, equalTo(externalDirectory.getPath() + "/scaled_pngImage.png")); } @Test - public void onResizeImageIfNeeded_WhenWidthIsNotNull_ShoulResize_ReturnResizedFile() { - String outoutFile = resizer.resizeImageIfNeeded(imageFile.getPath(), 50.0, null, null); - assertThat(outoutFile, equalTo(externalDirectory.getPath() + "/scaled_pngImage.png")); + public void onResizeImageIfNeeded_whenWidthIsNotNull_shouldResize_returnResizedFile() { + String outputFile = resizer.resizeImageIfNeeded(imageFile.getPath(), 50.0, null, 100); + assertThat(outputFile, equalTo(externalDirectory.getPath() + "/scaled_pngImage.png")); } @Test - public void onResizeImageIfNeeded_WhenHeightIsNotNull_ShoulResize_ReturnResizedFile() { - String outoutFile = resizer.resizeImageIfNeeded(imageFile.getPath(), null, 50.0, null); - assertThat(outoutFile, equalTo(externalDirectory.getPath() + "/scaled_pngImage.png")); + public void onResizeImageIfNeeded_whenHeightIsNotNull_shouldResize_returnResizedFile() { + String outputFile = resizer.resizeImageIfNeeded(imageFile.getPath(), null, 50.0, 100); + assertThat(outputFile, equalTo(externalDirectory.getPath() + "/scaled_pngImage.png")); } @Test - public void onResizeImageIfNeeded_WhenParentDirectoryDoesNotExists_ShouldNotCrash() { + public void onResizeImageIfNeeded_whenParentDirectoryDoesNotExists_shouldNotCrash() { File nonExistentDirectory = new File(externalDirectory, "/nonExistent"); ImageResizer invalidResizer = new ImageResizer(nonExistentDirectory, new ExifDataCopier()); - String outoutFile = invalidResizer.resizeImageIfNeeded(imageFile.getPath(), null, 50.0, null); - assertThat(outoutFile, equalTo(nonExistentDirectory.getPath() + "/scaled_pngImage.png")); + String outputFile = invalidResizer.resizeImageIfNeeded(imageFile.getPath(), null, 50.0, 100); + assertThat(outputFile, equalTo(nonExistentDirectory.getPath() + "/scaled_pngImage.png")); } } diff --git a/packages/image_picker/image_picker_android/pubspec.yaml b/packages/image_picker/image_picker_android/pubspec.yaml index 1c22e9c9366..812026de317 100755 --- a/packages/image_picker/image_picker_android/pubspec.yaml +++ b/packages/image_picker/image_picker_android/pubspec.yaml @@ -3,7 +3,7 @@ description: Android implementation of the image_picker plugin. repository: https://github.com/flutter/packages/tree/main/packages/image_picker/image_picker_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22 -version: 0.8.6 +version: 0.8.6+1 environment: sdk: ">=2.17.0 <3.0.0"