【MAUI Blazor踩坑日记】2.关于Windows上的相机问题

发布时间 2023-04-23 19:51:27作者: Yu-Core

前言

MAUI中Windows上,调用MediaPicker.Default.CapturePhotoAsync()并不能启动相机拍照。关于这个问题可以查看 https://github.com/dotnet/maui/issues/7660https://github.com/dotnet/maui/pull/13220
好消息是已经修复了,坏消息是.net8修复了,而且还没发布.
所以目前怎么办, https://github.com/dotnet/maui/issues/7660 中已经给出了临时的解决方案。

正文

  1. 把下面代码复制到 Platforms/Windows 文件夹下
using Windows.Foundation.Collections;
using Windows.Media.Capture;
using Windows.Storage;
using Windows.System;
using WinRT.Interop;

public static class WindowsMediaPicker
{
    public static Task<FileResult?> CapturePhotoAsync()
        => CaptureAsync(false);

    public static Task<FileResult?> CaptureVideoAsync()
        => CaptureAsync(true);

    private static async Task<FileResult?> CaptureAsync(bool isVideo)
    {
        var captureUi = new CustomCameraCaptureUI();

        StorageFile? file = await captureUi.CaptureFileAsync(isVideo ? CameraCaptureUIMode.Video : CameraCaptureUIMode.Photo);

        if (file != null)
        {
            return new FileResult(file.Path, file.ContentType);
        }

        return null;
    }

    private class CustomCameraCaptureUI
    {
        private readonly LauncherOptions _launcherOptions;

        public CustomCameraCaptureUI()
        {
            var window = WindowStateManager.Default.GetActiveWindow();
            var handle = WindowNative.GetWindowHandle(window);

            _launcherOptions = new LauncherOptions();
            InitializeWithWindow.Initialize(_launcherOptions, handle);

            _launcherOptions.TreatAsUntrusted = false;
            _launcherOptions.DisplayApplicationPicker = false;
            _launcherOptions.TargetApplicationPackageFamilyName = "Microsoft.WindowsCamera_8wekyb3d8bbwe";
        }

        public async Task<StorageFile?> CaptureFileAsync(CameraCaptureUIMode mode)
        {
            var extension = mode == CameraCaptureUIMode.Photo ? ".jpg" : ".mp4";

            var currentAppData = ApplicationData.Current;
            var tempLocation = currentAppData.LocalCacheFolder;
            var tempFileName = $"capture{extension}";
            var tempFile = await tempLocation.CreateFileAsync(tempFileName, CreationCollisionOption.GenerateUniqueName);
            var token = Windows.ApplicationModel.DataTransfer.SharedStorageAccessManager.AddFile(tempFile);

            var set = new ValueSet();
            if (mode == CameraCaptureUIMode.Photo)
            {
                set.Add("MediaType", "photo");
                set.Add("PhotoFileToken", token);
            }
            else
            {
                set.Add("MediaType", "video");
                set.Add("VideoFileToken", token);
            }

            var uri = new Uri("microsoft.windows.camera.picker:");
            var result = await Windows.System.Launcher.LaunchUriForResultsAsync(uri, _launcherOptions, set);
            if (result.Status == LaunchUriStatus.Success && result.Result != null)
            {
                return tempFile;
            }

            return null;
        }
    }
}
  1. 如何使用
#if WINDOWS
            FileResult? photo = await WindowsMediaPicker.CapturePhotoAsync();
#else
            FileResult photo = await MediaPicker.Default.CapturePhotoAsync();
#endif