Anzeigen der Kameravorschau

Dieser Artikel beschreibt, wie Sie in einer UWP (Universelle Windows-Plattform)-App innerhalb einer XAML-Seite schnell den Datenstrom der Kameravorschau anzeigen. Zum Erstellen einer App, die Fotos und Videos mit der Kamera erfasst, müssen Sie Aufgaben wie das Behandeln der Geräte- und Kameraausrichtung oder das Festlegen von Codierungsoptionen für die erfasste Datei durchführen. Für einige App-Szenarien möchten Sie vielleicht einfach nur den Vorschaudatenstrom von der Kamera anzeigen, ohne sich Gedanken über diese anderen Überlegungen machen zu müssen. Dieser Artikel zeigt, wie dies mit einem Minimum an Code möglich ist. Hinweis: Sie sollten den Vorschaudatenstrom immer ordnungsgemäß beenden, wenn Sie damit fertig sind; führen Sie dazu die folgenden Schritte aus.

Informationen zum Schreiben einer Kamera-App, die Fotos oder Videos aufnimmt, finden Sie unter Allgemeine Foto-, Video- und Audioaufnahme mit „MediaCapture“.

Hinzufügen von Funktionsdeklarationen zum App-Manifest

Damit Ihre App auf die Kamera eines Geräts zugreifen kann, müssen Sie die Verwendung der webcam- und microphone-Gerätefunktionen durch Ihre App deklarieren.

Hinzufügen von Funktionen zum App-Manifest

  1. Öffnen Sie in Microsoft Visual Studio im Projektmappen-Explorer den Designer für das Anwendungsmanifest, indem Sie auf das Element package.appxmanifest doppelklicken.
  2. Wählen Sie die Registerkarte Funktionen aus.
  3. Aktivieren Sie das Kontrollkästchen für Webcam und das Kontrollkästchen für Mikrofon.

Hinzufügen eines CaptureElement zu einer Seite

Mithilfe eines CaptureElement können Sie den Vorschaudatenstrom innerhalb der XAML-Seite anzeigen.

<CaptureElement Name="PreviewControl" Stretch="Uniform"/>

Verwenden von MediaCapture zum Starten des Vorschaudatenstroms

Das MediaCapture-Objekt ist die Schnittstelle Ihrer App mit der Kamera des Geräts. Diese Klasse ist ein Mitglied des Windows.Media.Capture-Namespace. Im Beispiel in diesem Artikel werden neben den in der Standard-Projektvorlage enthaltenen APIs auch APIs aus den Namespaces Windows.ApplicationModel und System.Threading.Tasks verwendet.

Fügen Sie using-Direktiven hinzu, um die folgenden Namespaces in die CS-Datei Ihrer Seite einzubeziehen.

using Windows.UI.Core;
using Windows.UI.Xaml.Navigation;
using Windows.Media.Capture;
using Windows.ApplicationModel;
using System.Threading.Tasks;
using Windows.System.Display;
using Windows.Graphics.Display;

Deklarieren Sie eine Klassenmembervariable für das MediaCapture-Objekt. Fügen Sie einen booleschen Member hinzu, um nachzuverfolgen, ob die Vorschau der Kamera gerade aktiv ist.

MediaCapture mediaCapture;
bool isPreviewing;

Deklarieren Sie eine Variable vom Typ DisplayRequest, um sicherzustellen, dass die Anzeige während der Ausführung der Vorschau nicht deaktiviert wird.

DisplayRequest displayRequest = new DisplayRequest();

Erstellen Sie eine Hilfsmethode zum Starten der Kameravorschau, die in diesem Beispiel StartPreviewAsync genannt wird. Abhängig vom Szenario Ihrer App können Sie dies über den OnNavigatedTo-Ereignishandler aufrufen, der aufgerufen wird, wenn die Seite geladen wird, oder warten Und starten Sie die Vorschau als Reaktion auf UI-Ereignisse.

Erstellen Sie eine neue Instanz der MediaCapture-Klasse, und rufen Sie InitializeAsync auf, um das Aufnahmegerät zu initialisieren. Diese Methode schlägt u. U. fehl, beispielsweise auf Geräten ohne Kamera, daher sollte der Aufruf aus einem try-Block erfolgen. Beim Versuch, die Kamera zu initialisieren, wird eine UnauthorizedAccessException ausgelöst, wenn der Benutzer in den Datenschutzeinstellungen des Geräts den Kamerazugriff deaktiviert hat. Diese Ausnahme tritt auch während der Entwicklung auf, wenn Sie Ihrem App-Manifest nicht die richtigen Funktionen hinzugefügt haben.

Wichtig Bei einigen Gerätefamilien wird dem Benutzer eine Aufforderung zur Zustimmung des Benutzers angezeigt, bevor Ihrer App der Zugriff auf die Kamera des Geräts gewährt wird. Aus diesem Grund müssen Sie nur MediaCapture.InitializeAsync aus dem Hauptthread der Benutzeroberfläche aufrufen. Der Versuch, die Kamera von einem anderen Thread aus zu initialisieren, kann zum einem Initialisierungsfehler führen.

Verbinden Sie das MediaCapture-Objekt mit der CaptureElement-Klasse, indem Sie die Source-Eigenschaft festlegen. Starten Sie die Vorschau durch Aufrufen von StartPreviewAsync. Diese Methode löst eine FileLoadException aus, wenn eine andere App die exklusive Kontrolle über das Aufnahmegerät hat. Im nächsten Abschnitt finden Sie Informationen zum Überwachen von Änderungen in der exklusiven Steuerung.

Rufen Sie RequestActive auf, um sicherzustellen, dass das Gerät während der Ausführung der Vorschau nicht in den Standbymodus wechselt. Legen Sie abschließend die DisplayInformation.AutoRotationPreferences-Eigenschaft auf Landscape fest, um zu verhindern, dass die sich Benutzeroberfläche und das CaptureElement drehen, wenn der Benutzer die Ausrichtung des Geräts ändert. Weitere Informationen zum Behandeln von Änderungen an der Geräteausrichtung finden Sie unter Handhaben der Geräte- und Bildschirmausrichtung mit „MediaCapture“.

       private async Task StartPreviewAsync()
       {
           try
           {

               mediaCapture = new MediaCapture();
               await mediaCapture.InitializeAsync();

               displayRequest.RequestActive();
               DisplayInformation.AutoRotationPreferences = DisplayOrientations.Landscape;
           }
           catch (UnauthorizedAccessException)
           {
               // This will be thrown if the user denied access to the camera in privacy settings
               ShowMessageToUser("The app was denied access to the camera");
               return;
           }

           try
           {
               PreviewControl.Source = mediaCapture;
               await mediaCapture.StartPreviewAsync();
               isPreviewing = true;
           }
           catch (System.IO.FileLoadException)
           {
               mediaCapture.CaptureDeviceExclusiveControlStatusChanged += _mediaCapture_CaptureDeviceExclusiveControlStatusChanged;
           }

       }

Behandeln von Änderungen im exklusiven Steuerelement

Wie im vorherigen Abschnitt erwähnt, löst StartPreviewAsync eine FileLoadException aus, wenn eine andere App die exklusive Kontrolle über das Erfassungsgerät hat. Ab Windows 10 Version 1703 können Sie einen Handler für das MediaCapture.CaptureDeviceExclusiveControlStatusChanged-Ereignis registrieren, das immer dann ausgelöst wird, wenn sich das exklusive Steuerelement status des Geräts ändert. Überprüfen Sie im Handler für dieses Ereignis die MediaCaptureDeviceExclusiveControlStatusChangedEventArgs.Status-Eigenschaft, um zu sehen, was der aktuelle status ist. Wenn die neue status SharedReadOnlyAvailable lautet, wissen Sie, dass Sie die Vorschau derzeit nicht starten können, und Sie möchten möglicherweise Ihre Benutzeroberfläche aktualisieren, um den Benutzer zu benachrichtigen. Wenn der neue status ExclusiveControlAvailable ist, können Sie versuchen, die Kameravorschau erneut zu starten.

private async void _mediaCapture_CaptureDeviceExclusiveControlStatusChanged(MediaCapture sender, MediaCaptureDeviceExclusiveControlStatusChangedEventArgs args)
{
    if (args.Status == MediaCaptureDeviceExclusiveControlStatus.SharedReadOnlyAvailable)
    {
        ShowMessageToUser("The camera preview can't be displayed because another app has exclusive access");
    }
    else if (args.Status == MediaCaptureDeviceExclusiveControlStatus.ExclusiveControlAvailable && !isPreviewing)
    {
        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
        {
            await StartPreviewAsync();
        });
    }
}

Beenden des Vorschaudatenstroms

Wenn Sie den Vorschaudatenstrom nicht mehr benötigen, sollten Sie ihn stets beenden und die dazugehörigen Ressourcen ordnungsgemäß löschen, um sicherzustellen, dass die Kamera für andere Apps auf dem Gerät verfügbar ist. Folgende Schritte sind zum Beenden des Vorschaudatenstroms erforderlich:

  • Wenn die Vorschau der Kamera gerade aktiv ist, rufen Sie StopPreviewAsync auf, um den Vorschaudatenstrom zu beenden. Wenn Sie StopPreviewAsync aufrufen, während die Vorschau nicht ausgeführt, wird eine Ausnahme ausgelöst.
  • Legen Sie die Source-Eigenschaft von CaptureElement auf NULL fest. Verwenden Sie CoreDispatcher.RunAsync, um sicherzustellen, dass dieser Aufruf im UI-Thread ausgeführt wird.
  • Rufen Sie die Dispose-Methode des MediaCapture-Objekts auf, um es freizugeben. Stellen Sie erneut mit CoreDispatcher.RunAsync sicher, dass dieser Aufruf im UI-Thread ausgeführt wird.
  • Legen Sie die MediaCapture-Membervariable auf NULL fest.
  • Rufen Sie RequestRelease auf, wenn der Bildschirm bei Inaktivität ausgeschaltet werden soll.
private async Task CleanupCameraAsync()
{
    if (mediaCapture != null)
    {
        if (isPreviewing)
        {
            await mediaCapture.StopPreviewAsync();
        }

        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            PreviewControl.Source = null;
            if (displayRequest != null)
            {
                displayRequest.RequestRelease();
            }

            mediaCapture.Dispose();
            mediaCapture = null;
        });
    }
    
}

Sie sollten den Vorschaudatenstrom durch Außerkraftsetzen der OnNavigatedFrom-Methode beenden, wenn der Benutzer Ihre Seite verlässt.

protected async override void OnNavigatedFrom(NavigationEventArgs e)
{
    await CleanupCameraAsync();
}

Sie sollten den Vorschaudatenstrom auch ordnungsgemäß beenden, wenn die App angehalten wird. Registrieren Sie dazu im Konstruktor der Seite einen Handler für das Application.Suspending-Ereignis.

public MainPage()
{
    this.InitializeComponent();

    Application.Current.Suspending += Application_Suspending;
}

Stellen Sie im Suspending-Ereignishandler zunächst sicher, dass die Seite im Frame der Anwendung angezeigt wird, indem Sie den Seitentyp mit der CurrentSourcePageType-Eigenschaft vergleichen. Wird die Seite derzeit nicht angezeigt, sollten das OnNavigatedFrom-Ereignis bereits ausgelöst und der Vorschaudatenstrom geschlossen worden sein. Wird die Seite angezeigt, rufen Sie ein SuspendingDeferral-Objekt aus den an den Handler übergebenen Ereignisargumenten ab, um sicherzustellen, dass das System Ihre App nicht anhält, bis der Vorschaudatenstrom beendet wurde. Rufen Sie nach dem Beenden des Datenstroms die Complete-Methode der Verzögerung auf, damit das System die App weiterhin anhalten kann.

private async void Application_Suspending(object sender, SuspendingEventArgs e)
{
    // Handle global application events only if this page is active
    if (Frame.CurrentSourcePageType == typeof(MainPage))
    {
        var deferral = e.SuspendingOperation.GetDeferral();
        await CleanupCameraAsync();
        deferral.Complete();
    }
}