Maui Blazor 使用摄像头实现代码

作者:dotnet-simple 时间:2023-12-06 11:44:37 

由于Maui Blazor中界面是由WebView渲染,所以再使用Android的摄像头时无法去获取,因为原生的摄像头需要绑定界面组件
所以我找到了其他的实现方式,通过WebView使用js调用设备摄像头 支持多平台兼容目前测试了Android 和PC 由于没有ioc和mac无法测试 大概率是兼容可能需要动态申请权限

1. 添加js方法

我们再wwwroot中创建一个helper.js的文件并且添加以下俩个js函数
index.html中添加<script src="helper.js"></script>引入js

/**
* 设置元素的src
* @param {any} canvasId canvasId的dom id
* @param {any} videoId video的dom id
* @param {any} srcId img的dom id
* @param {any} widht 设置截图宽度
* @param {any} height 设置截图高度
*/
function setImgSrc(dest,videoId, srcId, widht, height) {
   let video = document.getElementById(videoId);
   let canvas = document.getElementById(canvasId);
   console.log(video.clientHeight, video.clientWidth);

canvas.getContext('2d').drawImage(video, 0, 0, widht, height);

canvas.toBlob(function (blob) {
       var src = document.getElementById(srcId);
       src.setAttribute("height", height)
       src.setAttribute("width", widht);
       src.setAttribute("src", URL.createObjectURL(blob))
   }, "image/jpeg", 0.95);
}
/**
* 初始化摄像头
* @param {any} src
*/
function startVideo(src) {
   if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
       navigator.mediaDevices.getUserMedia({ video: true }).then(function (stream) {
           let video = document.getElementById(src);
           if ("srcObject" in video) {
               video.srcObject = stream;
           } else {
               video.src = window.URL.createObjectURL(stream);
           }
           video.onloadedmetadata = function (e) {
               video.play();
           };
           //mirror image
           video.style.webkitTransform = "scaleX(-1)";
           video.style.transform = "scaleX(-1)";
       });
   }
}

然后各个平台的兼容

android:

Platforms/Android/AndroidManifest.xml文件内容

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:allowBackup="true" android:supportsRtl="true"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<!--相机权限-->
<uses-permission android:name="android.permission.CAMERA" android:required="false"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!--相机功能-->
<uses-feature android:name="android.hardware.camera" />
<!--音频录制权限-->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!--位置权限-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<!-- Needed only if your app targets Android 5.0 (API level 21) or higher. -->
<uses-feature android:name="android.hardware.location.gps" />

<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="http"/>
</intent>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https"/>
</intent>
</queries>
</manifest>

Platforms/Android/MainActivity.cs文件内容

[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
public class MainActivity : MauiAppCompatActivity
{
   protected override void OnCreate(Bundle savedInstanceState)
   {
       base.OnCreate(savedInstanceState);
       Platform.Init(this, savedInstanceState);
       // 申请所需权限 也可以再使用的时候去申请
       ActivityCompat.RequestPermissions(this, new[] { Manifest.Permission.Camera, Manifest.Permission.RecordAudio, Manifest.Permission.ModifyAudioSettings }, 0);
   }
}

MauiWebChromeClient.cs文件内容

#if ANDROID
using Android.Webkit;
using Microsoft.AspNetCore.Components.WebView.Maui;

namespace MainSample;

public class MauiWebChromeClient : WebChromeClient
{
   public override void OnPermissionRequest(PermissionRequest request)
   {
       request.Grant(request.GetResources());
   }
}

public class MauiBlazorWebViewHandler : BlazorWebViewHandler
{
   protected override void ConnectHandler(Android.Webkit.WebView platformView)
   {
       platformView.SetWebChromeClient(new MauiWebChromeClient());
       base.ConnectHandler(platformView);
   }
}

#endif

MauiProgram.cs中添加以下代码;如果没有下面代码会出现没有摄像头权限
具体在这个 issue体现

#if ANDROID
       builder.ConfigureMauiHandlers(handlers =>
       {
           handlers.AddHandler<IBlazorWebView, MauiBlazorWebViewHandler>();
       });
#endif

以上是android的适配代码 pc不需要设置额外代码 ios和mac不清楚

然后编写界面

@page "/" @*界面路由*@

@inject IJSRuntime JSRuntime @*注入jsRuntime*@

@if(OpenCameraStatus) @*在摄像头没有被打开的情况不显示video*@
{
   <video id="@VideoId" width="@widht" height="@height" />
   <canvas class="d-none" id="@CanvasId" width="@widht" height="@height" />
}
<button @onclick="" style="margin:8px">打开摄像头</button>
@*因为摄像头必须是用户手动触发如果界面是滑动进入无法直接调用方法打开摄像头所以添加按钮触发*@
<button style="margin:8px">截图</button> @*对视频流截取一张图*@

<img id="@ImgId" />

@code{
   private string CanvasId;
   private string ImgId;
   private string VideoId;
   private bool OpenCameraStatus;
   private int widht = 320;
   private int height = 500;

private async Task OpenCamera()
   {
       if (!OpenCameraStatus)
       {
           // 由于打开摄像头的条件必须是用户手动触发如果滑动切换到界面是无法触发的
           await JSRuntime.InvokeVoidAsync("startVideo", "videoFeed");
           OpenCameraStatus = true;
           StateHasChanged();
       }
   }

protected override async Task OnInitializedAsync()
   {
       // 初始化id
       ImgId = Guid.NewGuid().ToString("N");
       CanvasId = Guid.NewGuid().ToString("N");
       VideoId = Guid.NewGuid().ToString("N");
       await base.OnInitializedAsync();
   }

private async Task Screenshot()
   {
       await JSRuntime.InvokeAsync<String>("setImgSrc", CanvasId,VideoId, ImgId, widht, height);
   }
}

然后可以运行程序就可以看到我们的效果了

示例代码:gitee github

来源:https://www.cnblogs.com/hejiale010426/p/17045707.html

标签:Maui,Blazor,摄像头
0
投稿

猜你喜欢

  • python 字符串转列表 list 出现\\ufeff的解决方法

    2023-11-24 18:47:06
  • 用nodejs搭建websocket服务器

    2024-05-08 09:36:56
  • MySQL数据库索引原理及优化策略

    2024-01-20 00:35:42
  • 对DataFrame数据中的重复行,利用groupby累加合并的方法详解

    2023-09-06 03:01:19
  • Python绘制词云图之可视化神器pyecharts的方法

    2022-12-08 14:38:44
  • Python之进行URL编码案例讲解

    2023-03-31 03:46:58
  • pygame实现非图片按钮效果

    2021-08-30 23:21:14
  • 利用Python生成Excel炫酷图表

    2023-03-09 21:52:00
  • Python 移动光标位置的方法

    2023-09-07 03:15:25
  • python实现马耳可夫链算法实例分析

    2022-08-13 00:27:08
  • Mysql5.7中使用group concat函数数据被截断的问题完美解决方法

    2024-01-18 02:00:39
  • python中if及if-else如何使用

    2022-12-06 08:14:15
  • vue中el-table合并列的具体实现

    2024-05-02 16:35:03
  • python中封包建立过程实例

    2021-11-13 14:29:08
  • vue实现拖拽交换位置

    2024-04-30 08:45:51
  • python基础之共有操作

    2021-01-29 23:42:18
  • python抢购软件/插件/脚本附完整源码

    2021-04-25 22:03:17
  • 微信支付PHP SDK之微信公众号支付代码详解

    2024-05-10 14:21:21
  • Python Django框架设计模式详解

    2021-01-16 12:52:40
  • 详解MySQL的用户密码过期功能

    2024-01-21 01:29:40
  • asp之家 网络编程 m.aspxhome.com