I'm working on an iOS app, which needs to be able to take a picture (to do some stuff with).
I'm using Xamarin with MvvmCross 6.2.0 and have imported the MvxPictureChooser plugin.
I have added NSPhotoLibraryAddUsageDescription to my Info.plist
...
<key>NSPhotoLibraryAddUsageDescription</key>
<string>This app needs to be able to save your expense attachments as images.</string>
<key>UIRequiresFullScreen</key>
<true/>
...
Now, when I try to use the ChoosePictureFromLibrary, all goes well.
If, on the other hand, I try to use TakePicture(int, int, Action, Action), I get an Exception which contains the error: NSInvalidArgumentException Reason: Source type 1 not available
My code looks like this:
private void DoTakePictureCommand()
{
var picChooser = Mvx.IoCProvider.Resolve<IMvxPictureChooserTask>();
try
{
picChooser.TakePicture(_envProvider.Environment.JpegSize, _envProvider.Environment.JpegQuality, (stream) =>
{
using (var ms = new MemoryStream())
{
stream.CopyToAsync(ms);
ReceiptJpegData = ms.ToArray();
_log.Trace("Picture bytes: {0}", ReceiptJpegData.Length);
InvokeOnMainThread(ImageComplete);
}
}, () =>
{
});
}
catch (Exception e)
{
Debug.Write(e);
}
}
The complete error is here:
[0:] Foundation.MonoTouchException: Objective-C exception thrown. Name: NSInvalidArgumentException Reason: Source type 1 not available Native stack trace:
0 CoreFoundation 0x000000011c41429b __exceptionPreprocess + 331 1 libobjc.A.dylib 0x000000011d2e8735 objc_exception_throw + 48 2 UIKitCore 0x0000000126d03553 -[UIImagePickerController sourceType] + 0 3 xxxiOS 0x000000010ed801b9 xamarin_dyn_objc_msgSend + 217 4 ??? 0x0000000141e58257 0x0 + 5400527447
at ObjCRuntime.Runtime.ThrowNSException (System.IntPtr ns_exception) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.0.0.15/src/Xamarin.iOS/ObjCRuntime/Runtime.cs:398
at ObjCRuntime.Runtime.throw_ns_exception (System.IntPtr exc) [0x00000] in /Users/builder/jenkins/workspace/xamarin-macios/xamarin-macios/runtime/Delegates.generated.cs:126
at (wrapper native-to-managed) ObjCRuntime.Runtime.throw_ns_exception(intptr) --- End of stack trace from previous location where exception was thrown --- at (wrapper managed-to-native) ObjCRuntime.Messaging.void_objc_msgSend_Int64(intptr,intptr,long) at UIKit.UIImagePickerController.set_SourceType (UIKit.UIImagePickerControllerSourceType value) [0x00015] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.0.0.15/src/Xamarin.iOS/UIKit/UIImagePickerController.g.cs:587 at MvvmCross.Plugin.PictureChooser.Platforms.Ios.MvxImagePickerTask.TakePicture (System.Int32 maxPixelDimension, System.Int32 percentQuality, System.Action`1[T] pictureAvailable, System.Action assumeCancelled) [0x00014] in <8539a731432e4b45b49dd5ca22de5afd>:0 at xxx.DoTakePictureCommand () [0x0000d] in C:\Users\xxxx\Documents\IdeaProjects\xxxx\xxxx\XXX.Core\ViewModels\AddExpenseViewModel.cs:447 0 CoreFoundation 0x000000011c41429b __exceptionPreprocess + 331 1 libobjc.A.dylib 0x000000011d2e8735 objc_exception_throw + 48 2 UIKitCore
0x0000000126d03553 -[UIImagePickerController sourceType] + 0 3
xxxiOS 0x000000010ed801b9 xamarin_dyn_objc_msgSend + 217 4 ???
0x0000000141e58257 0x0 + 5400527447 2018-09-27 23:15:03.294036+0200 xxxiOS[46563:4418172] 2018-09-27 11:15:03 [TRACE] (MvvmCross.Logging.MvxLog) iOSNavigation 2018-09-27 23:15:03.294886+0200 xxxiOS[46563:4418172] 2018-09-27 11:15:03 [TRACE] (MvvmCross.Logging.MvxLog) PresentationAttribute not found for AddExpenseView. Assuming animated Child presentation CalabashServer | XTC_SKIP_LPSERVER_TOKEN is not in the app environment CalabashServer | Will start LPServer with identifier: c36c12ce937d044d55d0c208f9d4502868233513
UPDATE
I have now tried deploying the code to my iPhone 7 which has been updated to iOS 12, and the app crashes as soon as it attempts to start the camera.
I have also tried hardcoding the int values:
private void DoTakePictureCommand()
{
var picChooser = Mvx.IoCProvider.Resolve<IMvxPictureChooserTask>();
try
{
picChooser.TakePicture(640, 50, (stream) =>
{
using (var ms = new MemoryStream())
{
stream.CopyToAsync(ms);
ReceiptJpegData = ms.ToArray();
_log.Trace("Picture bytes: {0}", ReceiptJpegData.Length);
InvokeOnMainThread(ImageComplete);
}
}, () =>
{
});
}
catch (Exception e)
{
Debug.Write(e);
}
}
But the result is the same.
UPDATE
I created a small sample project which replicates the problem. The app uses both choose picture and take picture - only choose picture works. I have posted it to a public repo on Github: PictureApp
OK, nailed it!
I'll leave a solution here for other app-developer newbies, who run into this issue.
The solution to the problem was actually quite simple: All I had to do, was add
<key>NSCameraUsageDescription</key>
<string></string>
to Info.plist.
It wasn't until I decided to drop MvvmCross.Plugin.PictureChooser and use Xam.Plugin.Media instead, that I got an understandable error message - basically something along the lines of: "you need to add NSCameraUsageDescription to Info.plist since iOS 10"