我一直在寻找,但只发现了这个:
> Monodroid Take a picture with Camera(不实施MVVMCross)
> Video Recording(这是视频,我不能使它工作:S)
> The Oficialy Recipe Example(虽然有效,但未实施MVVMCross)
谢谢!!!
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,Length); // write the required bytes while (bytesRead > 0) { writeStream.Write(buffer,bytesRead); bytesRead = readStream.Read(buffer,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; } } }
解决方法
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,() => { /* 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 }); } } }
我通常在启动期间将此服务注册为单例,然后从viewmodel ICommand处理程序调用它.
一个使用这项服务的应用程序是Blooor样本 – 见BaseEditProductViewModel.cs – 这不是我有任何关系的样本,但我相信它带来了Picture take和ZXing – 两者都使用外部服务.
一个警告:在MonoDroid上,您可以看到一些奇怪/意外的Activity / viewmodel生命周期行为 – 基本上您可以看到拍摄照片的活动是在拍照期间从内存中卸载/擦除的.如果您的应用程序发生这种情况,那么您可能需要开始查看类似的问题:Saving Android Activity state using Save Instance State – 这不会在MvvmCross中自动处理(尚未).
我相信Blooor样本可能会遇到这个问题 – 但用户是否会在正常的应用程序中看到它是值得商榷的.
作为IMvxPictureChooserTask服务的替代方案,您还可以查看使用Xamarin.Mobile中的一些跨平台API – 请参阅MvvmCross vnext : monodroid use a VideoView inside a plugin以获取可能的起始位置 – 或者仅限Android,您可以轻松实现自己的.