5

Can anyone point me to an example of take a Photo and store it using MVVMCross?

I have been searching but only have found this:

Thanks!!!

Resolved! Thanks!
To Future References: (Using Master Branch)
Credits to Stuart, I just changed the code to work with my reality

using Cirrious.MvvmCross.ExtensionMethods; using Cirrious.MvvmCross.Interfaces.Platform.Tasks; using Cirrious.MvvmCross.Interfaces.ServiceProvider; using SIGEP.DummyService; using SIGEP.Mobile.Core.Interfaces; namespace SIGEP.Mobile.Core.Models { public class PhotoService : IMvxServiceConsumer<IMvxPictureChooserTask> { private const int MaxPixelDimension = 1024; private const int DefaultJpegQuality = 92; public void GetNewPhoto() { this.GetService<IMvxPictureChooserTask>().TakePicture( MaxPixelDimension, DefaultJpegQuality, HandlePhotoAvailable, () => { /* cancel is ignored */ }); } public event EventHandler<PhotoStreamEventArgs> PhotoStreamAvailable; private void HandlePhotoAvailable(Stream pictureStream) { var handler = PhotoStreamAvailable; if (handler != null) { handler(this, new PhotoStreamEventArgs() { PictureStream = pictureStream, OnSucessGettingPhotoFileName = OnSucessGettingPhotoFileName }); } } public static void TakePhoto(Action<string> successFileName, Action<Exception> error) { var service = new PhotoService(); service.OnSucessGettingPhotoFileName = successFileName; service.OnError = error; service.GetNewPhoto(); service.PhotoStreamAvailable += new EventHandler<PhotoStreamEventArgs>(service_PhotoStreamAvailable); } static void service_PhotoStreamAvailable(object sender, PhotoStreamEventArgs e) { //grava pra ficheiro!!! var directory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); var filename = Path.Combine(directory, "photo.jpeg"); string saveTo = filename; FileStream writeStream = new FileStream(saveTo, FileMode.Create, FileAccess.Write); ReadWriteStream(e.PictureStream, writeStream); e.OnSucessGettingPhotoFileName(filename); } private static void ReadWriteStream(Stream readStream, Stream writeStream) { int Length = 256; Byte[] buffer = new Byte[Length]; int bytesRead = readStream.Read(buffer, 0, Length); // write the required bytes while (bytesRead > 0) { writeStream.Write(buffer, 0, bytesRead); bytesRead = readStream.Read(buffer, 0, Length); } readStream.Close(); writeStream.Close(); } public Action<string> OnSucessGettingPhotoFileName { get; set; } public Action<Exception> OnError { get; set; } } [Serializable] [ComVisible(true)] public class PhotoStreamEventArgs : EventArgs { public Stream PictureStream { get; set; } public Action<string> OnSucessGettingPhotoFileName { get; set; } } } 

1 Answer 1

3

I generally implement a service using the built-in IMvxPictureChooserTask (this is in a Plugin if using vNext):

using Cirrious.MvvmCross.ExtensionMethods; using Cirrious.MvvmCross.Interfaces.Platform.Tasks; using Cirrious.MvvmCross.Interfaces.ServiceProvider; public class PhotoService : IMvxServiceConsumer<IMvxPictureChooserTask> , IPhotoService { private const int MaxPixelDimension = 1024; private const int DefaultJpegQuality = 92; public void GetNewPhoto() { Trace.Info("Get a new photo started."); this.GetService<IMvxPictureChooserTask>().TakePicture( MaxPixelDimension, DefaultJpegQuality, HandlePhotoAvailable, () => { /* cancel is ignored */ }); } public event EventHandler<PhotoStreamEventArgs> PhotoStreamAvailable; private void HandlePhotoAvailable(Stream pictureStream) { Trace.Info("Picture available"); var handler = PhotoStreamAvailable; if (handler != null) { handler(this, new PhotoStreamEventArgs() { PictureStream = pictureStream }); } } } 

I generally register this service as a singleton during startup, and then call it from a ViewModel ICommand handler.


One app which uses this service is the Blooor sample - see BaseEditProductViewModel.cs - this isn't a sample I had anything to do with, but I believe it brings in both Picture taking and ZXing - both using external services.


One warning: On MonoDroid, you can see some strange/unexpected Activity/ViewModel lifecycle behaviour - basically you can see that the Activity you take the photo from is unloaded/wiped from memory during the photo taking. If this happens to your app then you'll probably need to start looking at questions like: Saving Android Activity state using Save Instance State - this isn't automatically handled in MvvmCross (yet).

I believe the Blooor sample might suffer from this issue - but whether a user would ever see it in normal app use is debatable.


As an alternative to the IMvxPictureChooserTask service, you can also look at using some of the cross-platform APIs from Xamarin.Mobile - see MvvmCross vnext : monodroid use a VideoView inside a plugin for a possible starting place - or for Android only you can easily implement your own.

Sign up to request clarification or add additional context in comments.

4 Comments

That VideoRecorder sample - gist.github.com/3945799 - is based around Xamarin.Mobile - and it might be a great place to start with in-app photo taking.
Currently i'm using the master brunch. I will upgrade to the vnext and hopefully put it working! Thanks @Stuart
That code I posted should work in the master branch - if you are already working in master, then I think you will find it easier to get it working in master rather than switching to PCLs in vNext :)
Thanks for the question. Please do feel free to blog about anything you learn - helps to add to the documentation!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.