[image_picker] Image picker fix camera device (#3898)
diff --git a/packages/image_picker/image_picker/CHANGELOG.md b/packages/image_picker/image_picker/CHANGELOG.md
index 0e49912..33178de 100644
--- a/packages/image_picker/image_picker/CHANGELOG.md
+++ b/packages/image_picker/image_picker/CHANGELOG.md
@@ -1,9 +1,13 @@
+## 0.8.1+4
+
+* Fixes an issue where `preferredCameraDevice` option is not working for `getVideo` method.
+* Refactor unit tests that were device-only before.
+
## 0.8.1+3
* Fix image picker causing a crash when the cache directory is deleted.
## 0.8.1+2
-
* Update the example app to support the multi-image feature.
## 0.8.1+1
diff --git a/packages/image_picker/image_picker/example/ios/Podfile b/packages/image_picker/image_picker/example/ios/Podfile
index 75efae4..8979c25 100644
--- a/packages/image_picker/image_picker/example/ios/Podfile
+++ b/packages/image_picker/image_picker/example/ios/Podfile
@@ -31,7 +31,10 @@
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
+ platform :ios, '9.0'
inherit! :search_paths
+ # Pods for testing
+ pod 'OCMock', '~> 3.8.1'
end
target 'RunnerUITests' do
inherit! :search_paths
diff --git a/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/project.pbxproj b/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/project.pbxproj
index 547c2be..fc1609f 100644
--- a/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/project.pbxproj
@@ -877,7 +877,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
- DEVELOPMENT_TEAM = NHAKRD9N7D;
+ DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = RunnerUITestiOS14/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
diff --git a/packages/image_picker/image_picker/example/ios/RunnerTests/ImagePickerPluginTests.m b/packages/image_picker/image_picker/example/ios/RunnerTests/ImagePickerPluginTests.m
index f667526..cc901f0 100644
--- a/packages/image_picker/image_picker/example/ios/RunnerTests/ImagePickerPluginTests.m
+++ b/packages/image_picker/image_picker/example/ios/RunnerTests/ImagePickerPluginTests.m
@@ -6,6 +6,7 @@
@import image_picker;
@import XCTest;
+#import <OCMock/OCMock.h>
@interface MockViewController : UIViewController
@property(nonatomic, retain) UIViewController *mockPresented;
@@ -27,15 +28,33 @@
@end
@interface ImagePickerPluginTests : XCTestCase
+@property(readonly, nonatomic) id mockUIImagePicker;
+@property(readonly, nonatomic) id mockAVCaptureDevice;
@end
@implementation ImagePickerPluginTests
-#pragma mark - Test camera devices, no op on simulators
+- (void)setUp {
+ _mockUIImagePicker = OCMClassMock([UIImagePickerController class]);
+ _mockAVCaptureDevice = OCMClassMock([AVCaptureDevice class]);
+}
+
- (void)testPluginPickImageDeviceBack {
- if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
- return;
- }
+ // UIImagePickerControllerSourceTypeCamera is supported
+ OCMStub(ClassMethod(
+ [_mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]))
+ .andReturn(YES);
+
+ // UIImagePickerControllerCameraDeviceRear is supported
+ OCMStub(ClassMethod(
+ [_mockUIImagePicker isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear]))
+ .andReturn(YES);
+
+ // AVAuthorizationStatusAuthorized is supported
+ OCMStub([_mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo])
+ .andReturn(AVAuthorizationStatusAuthorized);
+
+ // Run test
FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
FlutterMethodCall *call =
[FlutterMethodCall methodCallWithMethodName:@"pickImage"
@@ -43,14 +62,27 @@
[plugin handleMethodCall:call
result:^(id _Nullable r){
}];
+
XCTAssertEqual([plugin getImagePickerController].cameraDevice,
UIImagePickerControllerCameraDeviceRear);
}
- (void)testPluginPickImageDeviceFront {
- if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
- return;
- }
+ // UIImagePickerControllerSourceTypeCamera is supported
+ OCMStub(ClassMethod(
+ [_mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]))
+ .andReturn(YES);
+
+ // UIImagePickerControllerCameraDeviceFront is supported
+ OCMStub(ClassMethod([_mockUIImagePicker
+ isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront]))
+ .andReturn(YES);
+
+ // AVAuthorizationStatusAuthorized is supported
+ OCMStub([_mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo])
+ .andReturn(AVAuthorizationStatusAuthorized);
+
+ // Run test
FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
FlutterMethodCall *call =
[FlutterMethodCall methodCallWithMethodName:@"pickImage"
@@ -58,14 +90,27 @@
[plugin handleMethodCall:call
result:^(id _Nullable r){
}];
+
XCTAssertEqual([plugin getImagePickerController].cameraDevice,
UIImagePickerControllerCameraDeviceFront);
}
- (void)testPluginPickVideoDeviceBack {
- if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
- return;
- }
+ // UIImagePickerControllerSourceTypeCamera is supported
+ OCMStub(ClassMethod(
+ [_mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]))
+ .andReturn(YES);
+
+ // UIImagePickerControllerCameraDeviceRear is supported
+ OCMStub(ClassMethod(
+ [_mockUIImagePicker isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear]))
+ .andReturn(YES);
+
+ // AVAuthorizationStatusAuthorized is supported
+ OCMStub([_mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo])
+ .andReturn(AVAuthorizationStatusAuthorized);
+
+ // Run test
FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
FlutterMethodCall *call =
[FlutterMethodCall methodCallWithMethodName:@"pickVideo"
@@ -73,10 +118,41 @@
[plugin handleMethodCall:call
result:^(id _Nullable r){
}];
+
XCTAssertEqual([plugin getImagePickerController].cameraDevice,
UIImagePickerControllerCameraDeviceRear);
}
+- (void)testPluginPickVideoDeviceFront {
+ // UIImagePickerControllerSourceTypeCamera is supported
+ OCMStub(ClassMethod(
+ [_mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]))
+ .andReturn(YES);
+
+ // UIImagePickerControllerCameraDeviceFront is supported
+ OCMStub(ClassMethod([_mockUIImagePicker
+ isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront]))
+ .andReturn(YES);
+
+ // AVAuthorizationStatusAuthorized is supported
+ OCMStub([_mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo])
+ .andReturn(AVAuthorizationStatusAuthorized);
+
+ // Run test
+ FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
+ FlutterMethodCall *call =
+ [FlutterMethodCall methodCallWithMethodName:@"pickVideo"
+ arguments:@{@"source" : @(0), @"cameraDevice" : @(1)}];
+ [plugin handleMethodCall:call
+ result:^(id _Nullable r){
+ }];
+
+ XCTAssertEqual([plugin getImagePickerController].cameraDevice,
+ UIImagePickerControllerCameraDeviceFront);
+}
+
+#pragma mark - Test camera devices, no op on simulators
+
- (void)testPluginPickImageDeviceCancelClickMultipleTimes {
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
return;
@@ -91,26 +167,13 @@
plugin.result = ^(id result) {
};
+ // To ensure the flow does not crash by multiple cancel call
[plugin imagePickerControllerDidCancel:[plugin getImagePickerController]];
[plugin imagePickerControllerDidCancel:[plugin getImagePickerController]];
}
-- (void)testPluginPickVideoDeviceFront {
- if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
- return;
- }
- FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
- FlutterMethodCall *call =
- [FlutterMethodCall methodCallWithMethodName:@"pickVideo"
- arguments:@{@"source" : @(0), @"cameraDevice" : @(1)}];
- [plugin handleMethodCall:call
- result:^(id _Nullable r){
- }];
- XCTAssertEqual([plugin getImagePickerController].cameraDevice,
- UIImagePickerControllerCameraDeviceFront);
-}
-
#pragma mark - Test video duration
+
- (void)testPickingVideoWithDuration {
FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
FlutterMethodCall *call = [FlutterMethodCall
diff --git a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m
index 7c91606..4084ae6 100644
--- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m
+++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m
@@ -37,7 +37,6 @@
@implementation FLTImagePickerPlugin {
UIImagePickerController *_imagePickerController;
- UIImagePickerControllerCameraDevice _device;
}
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
@@ -70,6 +69,21 @@
return topController;
}
+/**
+ * Returns the UIImagePickerControllerCameraDevice to use given [arguments].
+ *
+ * If the cameraDevice value that is fetched from arguments is 1 then returns
+ * UIImagePickerControllerCameraDeviceFront. If the cameraDevice value that is fetched
+ * from arguments is 0 then returns UIImagePickerControllerCameraDeviceRear.
+ *
+ * @param arguments that should be used to get cameraDevice value.
+ */
+- (UIImagePickerControllerCameraDevice)getCameraDeviceFromArguments:(NSDictionary *)arguments {
+ NSInteger cameraDevice = [[arguments objectForKey:@"cameraDevice"] intValue];
+ return (cameraDevice == 1) ? UIImagePickerControllerCameraDeviceFront
+ : UIImagePickerControllerCameraDeviceRear;
+}
+
- (void)pickImageWithPHPicker:(int)maxImagesAllowed API_AVAILABLE(ios(14)) {
PHPickerConfiguration *config =
[[PHPickerConfiguration alloc] initWithPhotoLibrary:PHPhotoLibrary.sharedPhotoLibrary];
@@ -95,13 +109,9 @@
self.maxImagesAllowed = 1;
switch (imageSource) {
- case SOURCE_CAMERA: {
- NSInteger cameraDevice = [[_arguments objectForKey:@"cameraDevice"] intValue];
- _device = (cameraDevice == 1) ? UIImagePickerControllerCameraDeviceFront
- : UIImagePickerControllerCameraDeviceRear;
+ case SOURCE_CAMERA:
[self checkCameraAuthorization];
break;
- }
case SOURCE_GALLERY:
[self checkPhotoAuthorization];
break;
@@ -188,11 +198,12 @@
return;
}
}
+ UIImagePickerControllerCameraDevice device = [self getCameraDeviceFromArguments:_arguments];
// Camera is not available on simulators
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] &&
- [UIImagePickerController isCameraDeviceAvailable:_device]) {
+ [UIImagePickerController isCameraDeviceAvailable:device]) {
_imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
- _imagePickerController.cameraDevice = _device;
+ _imagePickerController.cameraDevice = device;
[[self viewControllerWithWindow:nil] presentViewController:_imagePickerController
animated:YES
completion:nil];
@@ -406,8 +417,8 @@
* The difference with initWithCapacity is that initWithCapacity still gives an empty array making
* it impossible to add objects on an index larger than the size.
*
- * @param @size The length of the required array
- * @return @NSMutableArray An array of a specified size
+ * @param size The length of the required array
+ * @return NSMutableArray An array of a specified size
*/
- (NSMutableArray *)createNSMutableArrayWithSize:(NSUInteger)size {
NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithCapacity:size];
@@ -528,14 +539,14 @@
* Applies NSMutableArray on the FLutterResult.
*
* NSString must be returned by FlutterResult if the single image
- * mode is active. It is checked by @c maxImagesAllowed and
- * returns the first object of the @c pathlist.
+ * mode is active. It is checked by maxImagesAllowed and
+ * returns the first object of the pathlist.
*
* NSMutableArray must be returned by FlutterResult if the multi-image
- * mode is active. After the @c pathlist count is checked then it returns
- * the @c pathlist.
+ * mode is active. After the pathlist count is checked then it returns
+ * the pathlist.
*
- * @param @pathList that should be applied to FlutterResult.
+ * @param pathList that should be applied to FlutterResult.
*/
- (void)handleSavedPathList:(NSArray *)pathList {
if (!self.result) {
diff --git a/packages/image_picker/image_picker/pubspec.yaml b/packages/image_picker/image_picker/pubspec.yaml
index bcda757..c9866db 100755
--- a/packages/image_picker/image_picker/pubspec.yaml
+++ b/packages/image_picker/image_picker/pubspec.yaml
@@ -3,7 +3,7 @@
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.1+3
+version: 0.8.1+4
environment:
sdk: ">=2.12.0 <3.0.0"