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; }
}
}
Community
  • 1
  • 1
ptorrezao
  • 87
  • 2
  • 7

1 Answers1

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.

Community
  • 1
  • 1
Stuart
  • 66,722
  • 7
  • 114
  • 165
  • That VideoRecorder sample - https://gist.github.com/3945799 - is based around Xamarin.Mobile - and it might be a great place to start with in-app photo taking. – Stuart Nov 20 '12 at 15:16
  • Currently i'm using the master brunch. I will upgrade to the vnext and hopefully put it working! Thanks @Stuart – ptorrezao Nov 20 '12 at 15:28
  • 1
    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 :) – Stuart Nov 20 '12 at 17:54
  • 1
    Thanks for the question. Please do feel free to blog about anything you learn - helps to add to the documentation! – Stuart Nov 21 '12 at 15:07