广告位联系
返回顶部
分享到

Maui Blazor使用摄像头实现介绍

相关技巧 来源:互联网 作者:佚名 发布时间:2024-02-14 13:03:19 人浏览
摘要

由于Maui Blazor中界面是由WebView渲染,所以再使用Android的摄像头时无法去获取,因为原生的摄像头需要绑定界面组件 所以我找到了其他的实现方式,通过WebView使用js调用设备摄像头 支持多平台

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

1. 添加js方法

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

/**

 * 设置元素的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文件内容

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

<?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文件内容

1

2

3

4

5

6

7

8

9

10

11

[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文件内容

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

#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体现

1

2

3

4

5

6

#if ANDROID

        builder.ConfigureMauiHandlers(handlers =>

        {

            handlers.AddHandler<IBlazorWebView, MauiBlazorWebViewHandler>();

        });

#endif

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

然后编写界面

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

@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);

    }

}

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


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。

您可能感兴趣的文章 :

原文链接 :
相关文章
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计