2017-12-11 3 views
0

Ich habe eine Xamarin Forms PCL App, die den Xam.Plugin.Media Helfer benutzt. Ich habe eine Seite, auf der der Benutzer einen Kamerahelfer auf Knopfdruck aufruft, um ein Bild aufzunehmen. Die Bytes vom Kamera-Helper kehren zur Seite zurück und dienen als Quelle für ein Bild. Es gibt eine Schaltfläche zum Speichern auf der Seite, wo ich im Grunde den Messaging-Dienst aufrufen und die Bytes in PCL SQlite speichern. Das Problem ist, ich bekomme über 3 erfolgreiche Ladevorgänge von dieser Seite, und kann ein Bild mit dem Kamerahelfer machen, bevor ich eine Ausnahme bekomme, NACHDEM das Bild mit der Kamera aufgenommen wurde, aber bevor es mit den Bytes zurückkommt. Die Ausnahmebedingungsnachricht lautet 'Zu viele offene Dateien'. Dies ist für iOS. Der gesamte relevante Code ist unten.Xam.Plugin.Media 'Too many open files'

Dank

Kamera Helper:

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; 
    } 
} 

nehmen Foto Seite:

<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> 

Nehmen Sie Foto-Seite-Code Behind:

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"); 
      } 
     } 
    } 
+0

aktualisierte Kamera Helfer zuerst vorgeschlagene Antwort –

Antwort

2

Wenn ich the code richtig bin Lesen, GetStream öffnet sich ein neuer Stream in die Datei jedes Mal. Ich würde versuchen, Ihre CrossMedia.Current.TakePhotoAsync Anruf und den Stream in using Anweisungen nur um sicherzustellen, dass sie ordnungsgemäß entsorgt werden.

public class CameraHelper 
{ 
    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()) { 
       byte[] ImgBytes; 
       ImgBytes = new byte[stream.Length]; 
       stream.Read(ImgBytes, 0, Convert.ToInt32(stream.Length)); 
      } 
     } 
     return ImgBytes; 
    } 
} 
+0

Dank zu reflektieren, das sah vielversprechend aus, aber ich bekomme immer noch den gleichen Fehler –

+0

@PatrickGoode Ist es möglich, Sie das Öffnen von Dateien an anderer Stelle? –

+0

Ich habe überprüft, das ist der einzige Ort. Es sei denn, die Images vom Typ ffimageload werden von Dateien im Hintergrund geladen. Sonst benutze ich nur das Byte-Array, das vom Kamerahelfer kommt und sonst nichts. –