Menampilkan pratinjau kamera

Artikel ini menjelaskan cara cepat menampilkan aliran pratinjau kamera dalam halaman XAML di aplikasi Platform Windows Universal (UWP). Membuat aplikasi yang mengambil foto dan video menggunakan kamera mengharuskan Anda melakukan tugas seperti menangani perangkat dan orientasi kamera atau mengatur opsi pengodean untuk file yang diambil. Untuk beberapa skenario aplikasi, Anda mungkin hanya ingin menampilkan streaming pratinjau dari kamera tanpa khawatir tentang pertimbangan lain ini. Artikel ini memperlihatkan kepada Anda cara melakukannya dengan kode minimum. Perhatikan bahwa Anda harus selalu mematikan aliran pratinjau dengan benar ketika Anda selesai dengan mengikuti langkah-langkah di bawah ini.

Untuk informasi tentang menulis aplikasi kamera yang mengambil foto atau video, lihat Pengambilan foto, video, dan audio dasar dengan MediaCapture.

Menambahkan deklarasi kemampuan ke manifes aplikasi

Agar aplikasi Anda dapat mengakses kamera perangkat, Anda harus menyatakan bahwa aplikasi Anda menggunakan kemampuan webcam dan perangkat mikrofon .

Menambahkan kemampuan ke manifes aplikasi

  1. Di Microsoft Visual Studio, di Penjelajah Solusi, buka perancang untuk manifes aplikasi dengan mengklik dua kali item package.appxmanifest .
  2. Pilih tab Kemampuan.
  3. Centang kotak untuk Webcam dan kotak untuk Mikrofon.

Menambahkan CaptureElement ke halaman Anda

Gunakan CaptureElement untuk menampilkan aliran pratinjau dalam halaman XAML Anda.

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

Menggunakan MediaCapture untuk memulai aliran pratinjau

Objek MediaCapture adalah antarmuka aplikasi Anda ke kamera perangkat. Kelas ini adalah anggota namespace Windows.Media.Capture. Contoh dalam artikel ini juga menggunakan API dari namespace Windows.ApplicationModel dan System.Threading.Tasks , selain yang disertakan oleh templat proyek default.

Tambahkan menggunakan direktif untuk menyertakan namespace berikut dalam file .cs halaman Anda.

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;

Nyatakan variabel anggota kelas untuk objek MediaCapture dan boolean untuk melacak apakah kamera saat ini sedang dipratinjau.

MediaCapture mediaCapture;
bool isPreviewing;

Deklarasikan variabel jenis DisplayRequest yang akan digunakan untuk memastikan tampilan tidak dimatikan saat pratinjau berjalan.

DisplayRequest displayRequest = new DisplayRequest();

Buat metode pembantu untuk memulai pratinjau kamera, yang disebut StartPreviewAsync dalam contoh ini. Bergantung pada skenario aplikasi, Anda mungkin ingin memanggil ini dari penanganan aktivitas OnNavigatedTo yang dipanggil saat halaman dimuat atau menunggu dan meluncurkan pratinjau sebagai respons terhadap peristiwa UI.

Buat instans baru kelas MediaCapture dan panggil InitializeAsync untuk menginisialisasi perangkat pengambilan. Metode ini mungkin gagal, pada perangkat yang tidak memiliki kamera misalnya, jadi Anda harus memanggilnya dari dalam blok coba . UnauthorizedAccessException akan dilemparkan ketika Anda mencoba menginisialisasi kamera jika pengguna telah menonaktifkan akses kamera di pengaturan privasi perangkat. Anda juga akan melihat pengecualian ini selama pengembangan jika Anda telah diabaikan untuk menambahkan kemampuan yang tepat ke manifes aplikasi Anda.

Penting Pada beberapa keluarga perangkat, permintaan persetujuan pengguna ditampilkan kepada pengguna sebelum aplikasi Anda diberikan akses ke kamera perangkat. Untuk alasan ini, Anda hanya boleh memanggil MediaCapture.InitializeAsync dari utas UI utama. Mencoba menginisialisasi kamera dari utas lain dapat mengakibatkan kegagalan inisialisasi.

Sambungkan MediaCapture ke CaptureElement dengan mengatur properti Sumber . Mulai pratinjau dengan memanggil StartPreviewAsync. Metode ini akan melempar FileLoadException jika aplikasi lain memiliki kontrol eksklusif terhadap perangkat penangkapan. Lihat bagian berikutnya untuk informasi yang mendengarkan perubahan kontrol eksklusif.

Panggil RequestActive untuk memastikan perangkat tidak tidur saat pratinjau sedang berjalan. Terakhir, atur properti DisplayInformation.AutoRotationPreferences ke Lanskap untuk mencegah UI dan CaptureElement berputar saat pengguna mengubah orientasi perangkat. Untuk informasi selengkapnya tentang menangani perubahan orientasi perangkat, lihat Menangani orientasi perangkat dengan 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;
           }

       }

Menangani perubahan dalam kontrol eksklusif

Seperti yang dinyatakan di bagian sebelumnya, StartPreviewAsync akan melempar FileLoadException jika aplikasi lain memiliki kontrol eksklusif terhadap perangkat pengambilan. Dimulai dengan Windows 10, versi 1703, Anda dapat mendaftarkan handler untuk peristiwa MediaCapture.CaptureDeviceExclusiveControlStatusChanged, yang dinaikkan setiap kali status kontrol eksklusif perangkat berubah. Di handler untuk kejadian ini, periksa properti MediaCaptureDeviceExclusiveControlStatusChangedEventArgs.Status untuk melihat status saat ini. Jika status baru adalah SharedReadOnlyAvailable, maka Anda tahu bahwa Saat ini Anda tidak dapat memulai pratinjau dan Anda mungkin ingin memperbarui UI Anda untuk memberi tahu pengguna. Jika status baru adalah ExclusiveControlAvailable, maka Anda dapat mencoba memulai pratinjau kamera lagi.

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

Mematikan aliran pratinjau

Setelah selesai menggunakan aliran pratinjau, Anda harus selalu mematikan aliran dan membuang sumber daya terkait dengan benar untuk memastikan bahwa kamera tersedia untuk aplikasi lain di perangkat. Langkah-langkah yang diperlukan untuk mematikan aliran pratinjau adalah:

  • Jika kamera sedang dipratinjau, panggil StopPreviewAsync untuk menghentikan aliran pratinjau. Pengecualian akan dilemparkan jika Anda memanggil StopPreviewAsync saat pratinjau tidak berjalan.
  • Atur properti SumbercaptureElement ke null. Gunakan CoreDispatcher.RunAsync untuk memastikan panggilan ini dijalankan pada utas UI.
  • Panggil metode Buang objek MediaCapture untuk merilis objek. Sekali lagi, gunakan CoreDispatcher.RunAsync untuk memastikan panggilan ini dijalankan pada utas UI.
  • Atur variabel anggota MediaCapture ke null.
  • Panggil RequestRelease untuk memungkinkan layar dimatikan saat tidak aktif.
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;
        });
    }
    
}

Anda harus mematikan aliran pratinjau saat pengguna menavigasi jauh dari halaman Anda dengan menimpa metode OnNavigatedFrom .

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

Anda juga harus mematikan streaming pratinjau dengan benar saat aplikasi ditangguhkan. Untuk melakukan ini, daftarkan handler untuk peristiwa Application.Suspending di konstruktor halaman Anda.

public MainPage()
{
    this.InitializeComponent();

    Application.Current.Suspending += Application_Suspending;
}

Di penanganan aktivitas Penangguhan , pertama-tama periksa untuk memastikan bahwa halaman sedang ditampilkan Bingkai aplikasi dengan membandingkan jenis halaman dengan properti CurrentSourcePageType . Jika halaman saat ini tidak ditampilkan, maka peristiwa OnNavigatedFrom seharusnya sudah dinaikkan dan aliran pratinjau dimatikan. Jika halaman saat ini sedang ditampilkan, dapatkan objek SuspendingDeferral dari arg peristiwa yang diteruskan ke handler untuk memastikan sistem tidak menangguhkan aplikasi Anda sampai aliran pratinjau telah dimatikan. Setelah mematikan streaming, panggil metode Lengkap penangguhan untuk membiarkan sistem terus menangguhkan aplikasi Anda.

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