diff --git a/packages/image_picker/image_picker/CHANGELOG.md b/packages/image_picker/image_picker/CHANGELOG.md index 515845e07fc3..703b00bf92a7 100644 --- a/packages/image_picker/image_picker/CHANGELOG.md +++ b/packages/image_picker/image_picker/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.8.0+1 + +* Removed redundant request for camera permissions. + ## 0.8.0 * BREAKING CHANGE: Changed storage location for captured images and videos to internal cache on Android, diff --git a/packages/image_picker/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java b/packages/image_picker/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java index c934b54a1f8e..41df851d1d00 100644 --- a/packages/image_picker/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java +++ b/packages/image_picker/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java @@ -4,7 +4,6 @@ package io.flutter.plugins.imagepicker; -import android.Manifest; import android.app.Activity; import android.content.Intent; import android.content.pm.PackageManager; @@ -15,7 +14,6 @@ import android.os.Build; import android.provider.MediaStore; 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; @@ -42,19 +40,7 @@ enum CameraDevice { * 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 - * checks that {@link Manifest.permission#CAMERA} has been granted. - * - *

The permission check can end up in two different outcomes: - * - *

A) If the permission has already been granted, continue with picking the image from gallery or - * camera. - * - *

B) If the permission hasn't already been granted, ask for the permission from the user. If the - * user grants the permission, proceed with step #3. If the user denies the permission, stop doing - * anything else and finish with a null result. - * - *

3. Launch the gallery or camera for picking the image, depending on whether + *

2. Launch the gallery or camera for picking the image, depending on whether * chooseImageFromGallery() or takeImageWithCamera() was called. * *

This can end up in three different outcomes: @@ -69,15 +55,11 @@ enum CameraDevice { * *

C) User cancels picking an image. Finish with null result. */ -public class ImagePickerDelegate - implements PluginRegistry.ActivityResultListener, - PluginRegistry.RequestPermissionsResultListener { +public class ImagePickerDelegate implements PluginRegistry.ActivityResultListener { @VisibleForTesting static final int REQUEST_CODE_CHOOSE_IMAGE_FROM_GALLERY = 2342; @VisibleForTesting static final int REQUEST_CODE_TAKE_IMAGE_WITH_CAMERA = 2343; - @VisibleForTesting static final int REQUEST_CAMERA_IMAGE_PERMISSION = 2345; @VisibleForTesting static final int REQUEST_CODE_CHOOSE_VIDEO_FROM_GALLERY = 2352; @VisibleForTesting static final int REQUEST_CODE_TAKE_VIDEO_WITH_CAMERA = 2353; - @VisibleForTesting static final int REQUEST_CAMERA_VIDEO_PERMISSION = 2355; @VisibleForTesting final String fileProviderName; @@ -85,20 +67,11 @@ public class ImagePickerDelegate @VisibleForTesting final File externalFilesDirectory; private final ImageResizer imageResizer; private final ImagePickerCache cache; - private final PermissionManager permissionManager; private final IntentResolver intentResolver; private final FileUriResolver fileUriResolver; private final FileUtils fileUtils; private CameraDevice cameraDevice; - interface PermissionManager { - boolean isPermissionGranted(String permissionName); - - void askForPermission(String permissionName, int requestCode); - - boolean needRequestCameraPermission(); - } - interface IntentResolver { boolean resolveActivity(Intent intent); } @@ -129,23 +102,6 @@ public ImagePickerDelegate( null, null, cache, - new PermissionManager() { - @Override - public boolean isPermissionGranted(String permissionName) { - return ActivityCompat.checkSelfPermission(activity, permissionName) - == PackageManager.PERMISSION_GRANTED; - } - - @Override - public void askForPermission(String permissionName, int requestCode) { - ActivityCompat.requestPermissions(activity, new String[] {permissionName}, requestCode); - } - - @Override - public boolean needRequestCameraPermission() { - return ImagePickerUtils.needRequestCameraPermission(activity); - } - }, new IntentResolver() { @Override public boolean resolveActivity(Intent intent) { @@ -187,7 +143,6 @@ public void onScanCompleted(String path, Uri uri) { final MethodChannel.Result result, final MethodCall methodCall, final ImagePickerCache cache, - final PermissionManager permissionManager, final IntentResolver intentResolver, final FileUriResolver fileUriResolver, final FileUtils fileUtils) { @@ -197,7 +152,6 @@ public void onScanCompleted(String path, Uri uri) { this.fileProviderName = activity.getPackageName() + ".flutter.image_provider"; this.pendingResult = result; this.methodCall = methodCall; - this.permissionManager = permissionManager; this.intentResolver = intentResolver; this.fileUriResolver = fileUriResolver; this.fileUtils = fileUtils; @@ -269,13 +223,6 @@ public void takeVideoWithCamera(MethodCall methodCall, MethodChannel.Result resu return; } - if (needRequestCameraPermission() - && !permissionManager.isPermissionGranted(Manifest.permission.CAMERA)) { - permissionManager.askForPermission( - Manifest.permission.CAMERA, REQUEST_CAMERA_VIDEO_PERMISSION); - return; - } - launchTakeVideoWithCameraIntent(); } @@ -328,22 +275,9 @@ public void takeImageWithCamera(MethodCall methodCall, MethodChannel.Result resu return; } - if (needRequestCameraPermission() - && !permissionManager.isPermissionGranted(Manifest.permission.CAMERA)) { - permissionManager.askForPermission( - Manifest.permission.CAMERA, REQUEST_CAMERA_IMAGE_PERMISSION); - return; - } launchTakeImageWithCameraIntent(); } - private boolean needRequestCameraPermission() { - if (permissionManager == null) { - return false; - } - return permissionManager.needRequestCameraPermission(); - } - private void launchTakeImageWithCameraIntent() { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (cameraDevice == CameraDevice.FRONT) { @@ -401,39 +335,6 @@ private void grantUriPermissions(Intent intent, Uri imageUri) { } } - @Override - public boolean onRequestPermissionsResult( - int requestCode, String[] permissions, int[] grantResults) { - boolean permissionGranted = - grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED; - - switch (requestCode) { - case REQUEST_CAMERA_IMAGE_PERMISSION: - if (permissionGranted) { - launchTakeImageWithCameraIntent(); - } - break; - case REQUEST_CAMERA_VIDEO_PERMISSION: - if (permissionGranted) { - launchTakeVideoWithCameraIntent(); - } - break; - default: - return false; - } - - if (!permissionGranted) { - switch (requestCode) { - case REQUEST_CAMERA_IMAGE_PERMISSION: - case REQUEST_CAMERA_VIDEO_PERMISSION: - finishWithError("camera_access_denied", "The user did not allow camera access."); - break; - } - } - - return true; - } - @Override public boolean onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { diff --git a/packages/image_picker/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerPlugin.java b/packages/image_picker/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerPlugin.java index bffc903b531e..b4e7e8a06ce3 100644 --- a/packages/image_picker/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerPlugin.java +++ b/packages/image_picker/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerPlugin.java @@ -192,11 +192,9 @@ private void setup( // V1 embedding setup for activity listeners. application.registerActivityLifecycleCallbacks(observer); registrar.addActivityResultListener(delegate); - registrar.addRequestPermissionsResultListener(delegate); } else { // V2 embedding setup for activity listeners. activityBinding.addActivityResultListener(delegate); - activityBinding.addRequestPermissionsResultListener(delegate); lifecycle = FlutterLifecycleAdapter.getActivityLifecycle(activityBinding); lifecycle.addObserver(observer); } @@ -204,7 +202,6 @@ private void setup( private void tearDown() { activityBinding.removeActivityResultListener(delegate); - activityBinding.removeRequestPermissionsResultListener(delegate); activityBinding = null; lifecycle.removeObserver(observer); lifecycle = null; diff --git a/packages/image_picker/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java b/packages/image_picker/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java index da53b10b50f5..5b66814de761 100644 --- a/packages/image_picker/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java +++ b/packages/image_picker/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java @@ -14,7 +14,6 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -import android.Manifest; import android.app.Activity; import android.content.Context; import android.content.Intent; @@ -40,7 +39,6 @@ public class ImagePickerDelegateTest { @Mock ImageResizer mockImageResizer; @Mock MethodCall mockMethodCall; @Mock MethodChannel.Result mockResult; - @Mock ImagePickerDelegate.PermissionManager mockPermissionManager; @Mock ImagePickerDelegate.IntentResolver mockIntentResolver; @Mock FileUtils mockFileUtils; @Mock Intent mockIntent; @@ -104,11 +102,7 @@ public void chooseImageFromGallery_WhenPendingResultExists_FinishesWithAlreadyAc } @Test - public void - chooseImageFromGallery_WhenHasExternalStoragePermission_LaunchesChooseFromGalleryIntent() { - when(mockPermissionManager.isPermissionGranted(Manifest.permission.READ_EXTERNAL_STORAGE)) - .thenReturn(true); - + public void chooseImageFromGallery_LaunchesChooseFromGalleryIntent() { ImagePickerDelegate delegate = createDelegate(); delegate.chooseImageFromGallery(mockMethodCall, mockResult); @@ -127,50 +121,31 @@ public void takeImageWithCamera_WhenPendingResultExists_FinishesWithAlreadyActiv verifyNoMoreInteractions(mockResult); } - @Test - 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); - - verify(mockPermissionManager) - .askForPermission( - Manifest.permission.CAMERA, ImagePickerDelegate.REQUEST_CAMERA_IMAGE_PERMISSION); - } - - @Test - public void takeImageWithCamera_WhenCameraPermissionNotPresent_RequestsForPermission() { - when(mockPermissionManager.needRequestCameraPermission()).thenReturn(false); - when(mockIntentResolver.resolveActivity(any(Intent.class))).thenReturn(true); - - ImagePickerDelegate delegate = createDelegate(); - delegate.takeImageWithCamera(mockMethodCall, mockResult); - - verify(mockActivity) - .startActivityForResult( - any(Intent.class), eq(ImagePickerDelegate.REQUEST_CODE_TAKE_IMAGE_WITH_CAMERA)); - } - @Test public void - takeImageWithCamera_WhenHasCameraPermission_AndAnActivityCanHandleCameraIntent_LaunchesTakeWithCameraIntent() { - when(mockPermissionManager.isPermissionGranted(Manifest.permission.CAMERA)).thenReturn(true); + takeImageWithCamera_WhenAnActivityCanHandleCameraIntent_LaunchesTakeWithCameraIntent() { when(mockIntentResolver.resolveActivity(any(Intent.class))).thenReturn(true); - ImagePickerDelegate delegate = createDelegate(); - delegate.takeImageWithCamera(mockMethodCall, mockResult); + MockedStatic mockStaticFile = Mockito.mockStatic(File.class); + mockStaticFile + .when(() -> File.createTempFile(any(), any(), any())) + .thenReturn(new File("/tmpfile")); - verify(mockActivity) - .startActivityForResult( - any(Intent.class), eq(ImagePickerDelegate.REQUEST_CODE_TAKE_IMAGE_WITH_CAMERA)); + try { + ImagePickerDelegate delegate = createDelegate(); + delegate.takeImageWithCamera(mockMethodCall, mockResult); + + verify(mockActivity) + .startActivityForResult( + any(Intent.class), eq(ImagePickerDelegate.REQUEST_CODE_TAKE_IMAGE_WITH_CAMERA)); + } finally { + mockStaticFile.close(); + } } @Test public void - takeImageWithCamera_WhenHasCameraPermission_AndNoActivityToHandleCameraIntent_FinishesWithNoCamerasAvailableError() { - when(mockPermissionManager.isPermissionGranted(Manifest.permission.CAMERA)).thenReturn(true); + takeImageWithCamera_WhenNoActivityToHandleCameraIntent_FinishesWithNoCamerasAvailableError() { when(mockIntentResolver.resolveActivity(any(Intent.class))).thenReturn(false); ImagePickerDelegate delegate = createDelegate(); @@ -183,7 +158,6 @@ public void takeImageWithCamera_WhenCameraPermissionNotPresent_RequestsForPermis @Test public void takeImageWithCamera_WritesImageToCacheDirectory() { - when(mockPermissionManager.isPermissionGranted(Manifest.permission.CAMERA)).thenReturn(true); when(mockIntentResolver.resolveActivity(any(Intent.class))).thenReturn(true); MockedStatic mockStaticFile = Mockito.mockStatic(File.class); @@ -191,57 +165,16 @@ public void takeImageWithCamera_WritesImageToCacheDirectory() { .when(() -> File.createTempFile(any(), any(), any())) .thenReturn(new File("/tmpfile")); - ImagePickerDelegate delegate = createDelegate(); - delegate.takeImageWithCamera(mockMethodCall, mockResult); + try { + ImagePickerDelegate delegate = createDelegate(); + delegate.takeImageWithCamera(mockMethodCall, mockResult); - mockStaticFile.verify( - () -> File.createTempFile(any(), eq(".jpg"), eq(new File("/image_picker_cache"))), - times(1)); - } - - @Test - public void onRequestPermissionsResult_WhenCameraPermissionDenied_FinishesWithError() { - ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); - - delegate.onRequestPermissionsResult( - ImagePickerDelegate.REQUEST_CAMERA_IMAGE_PERMISSION, - new String[] {Manifest.permission.CAMERA}, - new int[] {PackageManager.PERMISSION_DENIED}); - - verify(mockResult).error("camera_access_denied", "The user did not allow camera access.", null); - verifyNoMoreInteractions(mockResult); - } - - @Test - public void - onRequestTakeVideoPermissionsResult_WhenCameraPermissionGranted_LaunchesTakeVideoWithCameraIntent() { - when(mockIntentResolver.resolveActivity(any(Intent.class))).thenReturn(true); - - ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); - delegate.onRequestPermissionsResult( - ImagePickerDelegate.REQUEST_CAMERA_VIDEO_PERMISSION, - new String[] {Manifest.permission.CAMERA}, - new int[] {PackageManager.PERMISSION_GRANTED}); - - verify(mockActivity) - .startActivityForResult( - any(Intent.class), eq(ImagePickerDelegate.REQUEST_CODE_TAKE_VIDEO_WITH_CAMERA)); - } - - @Test - public void - onRequestTakeImagePermissionsResult_WhenCameraPermissionGranted_LaunchesTakeWithCameraIntent() { - when(mockIntentResolver.resolveActivity(any(Intent.class))).thenReturn(true); - - ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); - delegate.onRequestPermissionsResult( - ImagePickerDelegate.REQUEST_CAMERA_IMAGE_PERMISSION, - new String[] {Manifest.permission.CAMERA}, - new int[] {PackageManager.PERMISSION_GRANTED}); - - verify(mockActivity) - .startActivityForResult( - any(Intent.class), eq(ImagePickerDelegate.REQUEST_CODE_TAKE_IMAGE_WITH_CAMERA)); + mockStaticFile.verify( + () -> File.createTempFile(any(), eq(".jpg"), eq(new File("/image_picker_cache"))), + times(1)); + } finally { + mockStaticFile.close(); + } } @Test @@ -362,7 +295,6 @@ private ImagePickerDelegate createDelegate() { null, null, cache, - mockPermissionManager, mockIntentResolver, mockFileUriResolver, mockFileUtils); @@ -371,12 +303,11 @@ private ImagePickerDelegate createDelegate() { private ImagePickerDelegate createDelegateWithPendingResultAndMethodCall() { return new ImagePickerDelegate( mockActivity, - null, + new File("/image_picker_cache"), mockImageResizer, mockResult, mockMethodCall, cache, - mockPermissionManager, mockIntentResolver, mockFileUriResolver, mockFileUtils); diff --git a/packages/image_picker/image_picker/pubspec.yaml b/packages/image_picker/image_picker/pubspec.yaml index 95ea8086d52c..c24fdd01fb1c 100755 --- a/packages/image_picker/image_picker/pubspec.yaml +++ b/packages/image_picker/image_picker/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for selecting images from the Android and iOS image library, and taking new pictures with the camera. repository: https://github.com/flutter/plugins/tree/master/packages/image_picker/image_picker issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22 -version: 0.8.0 +version: 0.8.0+1 environment: sdk: ">=2.12.0 <3.0.0"