需要一个用 MonoDroid 和 MVVMCross 拍照的例子 [英] Need an example of take a Picture with MonoDroid and MVVMCross
问题描述
谁能告诉我一个拍照并使用MVVMCross
存储它的例子吗?
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:
Monodroid 用相机拍照(不实现 MVVMCross)
Monodroid Take a picture with Camera (Doesn't Implement MVVMCross)
视频录制(这是视频,我无法让它工作:S)
Video Recording (It's Video and i can't make it work :S)
官方食谱示例(有效但没有实现 MVVMCross)
The Oficialy Recipe Example (It Works but does not implement MVVMCross)
谢谢!!!
已解决!谢谢!
未来参考:(使用主分支)
感谢 Stuart,我刚刚更改了代码以适应我的现实
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; }
}
}
推荐答案
我一般使用内置的IMvxPictureChooserTask
来实现一个服务(如果使用vNext,这是在一个Plugin中):
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 });
}
}
}
我一般在启动时将此服务注册为单例,然后从 ViewModel ICommand 处理程序中调用它.
I generally register this service as a singleton during startup, and then call it from a ViewModel ICommand handler.
使用此服务的一个应用是 Blooor 示例 - 请参阅 BaseEditProductViewModel.cs - 这不是样本我有任何关系,但我相信它带来了拍照和 ZXing - 两者都使用外部服务.
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.
一个警告:在 MonoDroid 上,您可以看到一些奇怪/意外的 Activity/ViewModel 生命周期行为 - 基本上您可以看到您从中获取照片的 Activity 在拍照期间从内存中卸载/擦除.如果您的应用发生这种情况,那么您可能需要开始查看以下问题:保存 Android 活动使用保存实例状态的状态 - 这在 MvvmCross 中不会自动处理(目前).
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).
我相信 Blooor 样本可能会遇到这个问题 - 但用户是否会在正常的应用程序使用中看到它是值得商榷的.
I believe the Blooor sample might suffer from this issue - but whether a user would ever see it in normal app use is debatable.
作为 IMvxPictureChooserTask
服务的替代方案,您还可以考虑使用 Xamarin.Mobile 中的一些跨平台 API - 请参阅 MvvmCross vnext : monodroid 在插件中使用 VideoView 作为可能的起始位置 - 或者仅适用于 Android,您可以轻松实现你自己的.
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.
这篇关于需要一个用 MonoDroid 和 MVVMCross 拍照的例子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!