我有一个Xamarin表单PCL应用程序,使用Xam.Plugin.Media助手。2我有一个页面,用户可以在按下按钮时调用一个摄像头助手来拍照。3摄像头助手的字节返回到页面,并作为图像的源。4页面上有一个保存按钮,我基本上可以调用消息服务并将字节保存到PCL SQlite存储器。问题是我得到了大约3个成功加载此页面,并可以采取一张照片与相机助手之前,我得到一个异常后,图像是用相机,但之前,它返回的字节。异常消息是'太多打开的文件'。这是iOS。所有相关的代码如下。谢谢
摄像头助手:
public class CameraHelper
{
private MediaFile file;
public async Task<byte[]> TakePicture()
{
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
throw new Exception("No camera available");
}
using (MediaFile file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
Name = $"photo{DateTime.Now.ToString("yyyyMMddHHmmss")}.jpg",
PhotoSize = PhotoSize.Small,
CompressionQuality = 80,
AllowCropping = true,
}))
{
if (file == null)
{
return null;
}
using (System.IO.Stream stream = file.GetStream())
{
ImgBytes = new byte[stream.Length];
await stream.ReadAsync(ImgBytes, 0, Convert.ToInt32(stream.Length));
file.Dispose();
}
}
return ImgBytes;
}
}
拍照页面:
<ContentPage.Content>
<StackLayout VerticalOptions="FillAndExpand" Padding="12,10,12,15">
<Label x:Name="photoTypeLabel" Text="Take *photo type* Photo" VerticalOptions="Start" />
<StackLayout Padding="0,30,0,70">
<ffimageloading:CachedImage x:Name="Image" Grid.Row="0" FadeAnimationEnabled="true" Aspect="AspectFill"
HeightRequest="200" WidthRequest="125" >
<ffimageloading:CachedImage.GestureRecognizers>
<TapGestureRecognizer Tapped="OnImageTapped" />
</ffimageloading:CachedImage.GestureRecognizers>
</ffimageloading:CachedImage>
</StackLayout>
<Label Grid.Row="0" Grid.Column="1"
Text="{ x:Static local:GrialShapesFont.PhotoCamera }"
Style="{StaticResource FontIcon}"
HorizontalTextAlignment="Center"
Opacity="1"
FontSize="60"
TextColor="#FF000000"
VerticalOptions="Center"
HorizontalOptions="Center">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="OnCameraTapped" />
</Label.GestureRecognizers>
</Label>
<Button Style="{StaticResource PrimaryActionButtonStyle}" VerticalOptions="End" Text="Save" WidthRequest="{ artina:OnOrientationDouble
LandscapePhone=200,
LandscapeTablet=400 }" HorizontalOptions="{ artina:OnOrientationLayoutOptions
PortraitPhone=Fill,
LandscapePhone=Center,
PortraitTablet=Fill,
LandscapeTablet=Center }" Clicked="saveButtonClicked" />
<Button Style="{StaticResource PrimaryActionButtonStyle}" VerticalOptions="End" Text="Cancel" WidthRequest="{ artina:OnOrientationDouble
LandscapePhone=200,
LandscapeTablet=400 }" HorizontalOptions="{ artina:OnOrientationLayoutOptions
PortraitPhone=Fill,
LandscapePhone=Center,
PortraitTablet=Fill,
LandscapeTablet=Center }" Clicked="cancelButtonClicked" />
</StackLayout>
</ContentPage.Content>
背后拍照页面代码:
private async void OnCameraTapped(object sender, EventArgs args)
{
CameraHelper cameraHelper = new CameraHelper();
try
{
ImgBytes = await cameraHelper.TakePicture();
Image.Source = ImageSource.FromStream(() =>
{
return new MemoryStream(ImgBytes);
});
}
catch (Exception ex)
{
if (ex.Message == "No camera available")
{
await DisplayAlert("Error", "No camera available", "Ok");
}
else
{
await DisplayAlert("Error", "Unable to take picture.", "Ok");
}
}
}
2条答案
按热度按时间kmbjn2e31#
如果我没有阅读错代码,
GetStream
每次都会打开一个新的流,我会尝试将CrossMedia.Current.TakePhotoAsync
调用和流 Package 在using
语句中,以确保它们得到正确的处理。ndasle7k2#
我建议你看到Xamarin Essential相机视图。你可以实现自己的自定义相机屏幕。
https://learn.microsoft.com/pt-br/xamarin/community-toolkit/views/cameraview?source=recommendations
然后你可以保存在本地存储的图像,只是保存在本地数据库的路径,或者如果你想可以保存在Base64字符串,但我不推荐。