Anzeigen der Kameravorschau
In diesem Artikel wird beschrieben, wie Sie den Kameravorschaudatenstrom in einer XAML-Seite in einer Universelle Windows-Plattform-App (UWP) schnell anzeigen können. Zum Erstellen einer App, die Fotos und Videos mit der Kamera erfasst, müssen Sie Aufgaben wie das Behandeln von Geräte- und Kameraausrichtung oder das Festlegen von Codierungsoptionen für die aufgenommene Datei ausfü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 zu machen. In diesem Artikel wird beschrieben, wie Sie dies mit einem Mindestmaß an Code tun. Beachten Sie, dass Sie den Vorschaudatenstrom immer ordnungsgemäß herunterfahren sollten, wenn Sie damit fertig sind, indem Sie die folgenden Schritte ausführen.
Informationen zum Schreiben einer Kamera-App, die Fotos oder Videos erfasst, finden Sie unter "Einfache Foto-, Video- und Audioaufnahme mit MediaCapture".
Hinzufügen von Capability-Deklarationen zum App-Manifest
Damit Ihre App auf die Kamera eines Geräts zugreifen kann, müssen Sie angeben, dass Ihre App die Gerätefunktionen webcam und microphone verwendet.
Hinzufügen von Funktionen zum App-Manifest
- Öffnen Sie in Microsoft Visual Studio im Projektmappen-Explorer, den Designer für das Anwendungsmanifest, indem Sie auf das Element package.appxmanifest doppelklicken.
- Wählen Sie die Registerkarte Funktionen aus.
- Aktivieren Sie das Kästchen für Webcam und das Kästchen für Mikrofon.
Hinzufügen eines CaptureElements zu Ihrer Seite
Verwenden Sie ein CaptureElement , um den Vorschaudatenstrom auf Ihrer XAML-Seite anzuzeigen.
<CaptureElement Name="PreviewControl" Stretch="Uniform"/>
Verwenden von MediaCapture zum Starten des Vorschaudatenstroms
Das MediaCapture-Objekt ist die Schnittstelle Ihrer App für die Kamera des Geräts. Diese Klasse ist ein Mitglied des Windows.Media.Capture-Namespace. Im Beispiel in diesem Artikel werden auch APIs aus den Namespaces "Windows.ApplicationModel " und "System.Threading.Tasks " verwendet, zusätzlich zu den apIs, die in der Standardprojektvorlage enthalten sind.
Fügen Sie mithilfe von Direktiven die folgenden Namespaces in die .cs Datei Ihrer Seite ein.
//MainPage.xaml.cs
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 Klassenmemempelvariable für das MediaCapture-Objekt und einen booleschen Wert, um nachzuverfolgen, ob die Kamera derzeit eine Vorschau anzeigt.
MediaCapture mediaCapture;
bool isPreviewing;
Deklarieren Sie eine Variable vom Typ DisplayRequest , die verwendet wird, 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 namens "StartPreviewAsync " in diesem Beispiel. Je nach Szenario Ihrer App möchten Sie dies möglicherweise über den OnNavigatedTo-Ereignishandler aufrufen, der aufgerufen wird, wenn die Seite geladen wird, oder warten und die Vorschau als Reaktion auf UI-Ereignisse starten.
Erstellen Sie eine neue Instanz der MediaCapture-Klasse, und rufen Sie InitializeAsync auf, um das Aufnahmegerät zu initialisieren. Diese Methode schlägt möglicherweise fehl, z. B. auf Geräten, auf denen keine Kamera vorhanden ist, sodass Sie sie innerhalb eines Try-Blocks aufrufen sollten. Eine nicht autorisierteAccessException wird ausgelöst, wenn Sie versuchen, die Kamera zu initialisieren, wenn der Benutzer den Kamerazugriff in den Datenschutzeinstellungen des Geräts deaktiviert hat. Diese Ausnahme wird auch während der Entwicklung angezeigt, wenn Sie dem App-Manifest die richtigen Funktionen nicht hinzugefügt haben.
Wichtig bei einigen Gerätefamilien wird dem Benutzer eine Zustimmungsaufforderung angezeigt, bevor der App Zugriff auf die Kamera des Geräts gewährt wird. Aus diesem Grund müssen Sie "MediaCapture.InitializeAsync" nur aus dem Hauptthread der Benutzeroberfläche aufrufen. Der Versuch, die Kamera von einem anderen Thread zu initialisieren, kann zu Initialisierungsfehlern führen.
Hinweis
Windows ermöglicht Benutzern das Gewähren oder Verweigern des Zugriffs auf die Kamera des Geräts in der Windows-Einstellungs-App unter Datenschutz und Sicherheit –> Kamera. Bei der Initialisierung des Aufnahmegeräts sollten Anwendungen prüfen, ob sie Zugriff auf die Kamera haben, und den Fall behandeln, dass der Zugriff vom Benutzer verweigert wird. Weitere Informationen finden Sie unter Behandeln der Datenschutzeinstellung der Windows-Kamera.
Verbinden Sie mediaCapture mit dem CaptureElement, indem Sie die Source-Eigenschaft festlegen. Starten Sie die Vorschau, indem Sie StartPreviewAsync aufrufen. 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 im exklusiven Steuerelement.
Rufen Sie RequestActive auf, um sicherzustellen, dass das Gerät nicht in den Ruhezustand wechselt, während die Vorschau ausgeführt wird. Legen Sie schließlich die DisplayInformation.AutoRotationPreferences-Eigenschaft auf Querformat fest, um zu verhindern, dass die Benutzeroberfläche und das CaptureElement sich drehen, wenn der Benutzer die Geräteausrichtung ändert. Weitere Informationen zum Behandeln von Geräteausrichtungsänderungen finden Sie unter "Behandeln der Geräteausrichtung 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 Aufnahmegerät hat. Ab Windows 10, Version 1703, können Sie einen Handler für das MediaCapture.CaptureDeviceExclusiveControlStatusChanged-Ereignis registrieren, das immer ausgelöst wird, wenn sich der exklusive Steuerelementstatus 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 der neue Status "SharedReadOnlyAvailable" lautet, wissen Sie, dass Sie die Vorschau zurzeit nicht starten können, und Sie möchten die Benutzeroberfläche möglicherweise aktualisieren, um den Benutzer zu benachrichtigen. Wenn der neue Status "ExclusiveControlAvailable" lautet, 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();
});
}
}
Herunterfahren des Vorschaudatenstroms
Wenn Sie mit der Verwendung des Vorschaudatenstroms fertig sind, sollten Sie den Datenstrom immer herunterfahren und die zugehörigen Ressourcen ordnungsgemäß löschen, um sicherzustellen, dass die Kamera für andere Apps auf dem Gerät verfügbar ist. Die erforderlichen Schritte zum Herunterfahren des Vorschaudatenstroms sind:
- Wenn die Kamera derzeit eine Vorschau anzeigt, rufen Sie StopPreviewAsync auf, um den Vorschaudatenstrom zu beenden. Eine Ausnahme wird ausgelöst, wenn Sie StopPreviewAsync aufrufen, während die Vorschau nicht ausgeführt wird.
- Legen Sie die Source-Eigenschaft des 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 das Objekt freizugeben. Verwenden Sie erneut CoreDispatcher.RunAsync , um sicherzustellen, dass dieser Aufruf im UI-Thread ausgeführt wird.
- Legen Sie die MediaCapture-Membervariable auf NULL fest.
- Rufen Sie RequestRelease auf, damit der Bildschirm bei inaktiv deaktiviert werden kann.
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 herunterfahren, wenn der Benutzer von Ihrer Seite navigiert, indem Sie die OnNavigatedFrom-Methode außer Kraft setzen.
protected async override void OnNavigatedFrom(NavigationEventArgs e)
{
await CleanupCameraAsync();
}
Sie sollten den Vorschaudatenstrom auch ordnungsgemäß herunterfahren, wenn Ihre App angehalten wird. Registrieren Sie dazu einen Handler für das Application.Suspending-Ereignis im Konstruktor Ihrer Seite.
public MainPage()
{
this.InitializeComponent();
Application.Current.Suspending += Application_Suspending;
}
Überprüfen Sie zunächst im Anhalteereignishandler, ob die Seite im Frame der Anwendung angezeigt wird, indem Sie den Seitentyp mit der CurrentSourcePageType-Eigenschaft vergleichen. Wenn die Seite derzeit nicht angezeigt wird, sollte das OnNavigatedFrom-Ereignis bereits ausgelöst und der Vorschaudatenstrom heruntergefahren werden. Wenn die Seite derzeit angezeigt wird, rufen Sie ein SuspendingDeferral-Objekt aus den Ereignisargumenten ab, die an den Handler übergeben werden, um sicherzustellen, dass das System Ihre App erst angehalten, wenn der Vorschaudatenstrom heruntergefahren wurde. Rufen Sie nach dem Herunterfahren des Datenstroms die Complete-Methode der Verzögerung auf, damit das System die App weiterhin anhält.
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();
}
}