MAUI Blazor 权限经验分享 (定位,使用相机)

article/2025/11/7 9:20:40

入门文章

Blazor Hybrid / MAUI 简介和实战
https://www.cnblogs.com/densen2014/p/16240966.html

在 Mac 上开发 .NET MAUI
https://www.cnblogs.com/densen2014/p/16057571.html

在 Windows 上开发 .NET MAUI
https://docs.microsoft.com/zh-cn/dotnet/maui/get-started/installation

###之前的工程已经能正常使用blazor的webview下获取定位,使用相机等功能,新版释出后反而权限获取不到了,定位页面出现如下错误

在这里插入图片描述

由于这个问题主要出现在安卓系统,下面只选了安卓的步骤分享

Android

应用所需的权限和功能在 AndroidManifest.xml 中定义。请参阅 官方文档 了解 Android App Manifest。

某些 Android 设备权限需要在运行时显示提示,以便用户可以授予或拒绝该权限。 Android 有一个推荐的 workflow 用于在运行时请求权限,此工作流必须由应用手动实现。 WebView 的 WebChromeClient 负责对权限请求做出反应,因此该项目提供了一个 PermissionManagingBlazorWebChromeClient 将 Webkit 资源映射到 Android 权限并执行推荐的权限请求工作流。

在向 AndroidManifest.xml 添加其他权限后,请务必更新 PermissionManagingBlazorWebChromeClient.cs 以包含该权限的“基本原理字符串”,解释应用程序需要它的原因。可能还需要在 权限请求类型 和 Android Manifest 权限之间定义其他映射。

1. 应用所需的权限Platforms/Android/AndroidManifest.xml

以下是我所有的测试权限列表,各位看官按需自由组合.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"><uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" /><application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application><uses-feature android:name="android.hardware.camera" /><uses-feature android:name="android.hardware.camera.autofocus" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /><uses-feature android:name="android.hardware.location" android:required="false" /><uses-feature android:name="android.hardware.location.gps" android:required="false" /><uses-feature android:name="android.hardware.location.network" android:required="false" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.CALL_PHONE" /><uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.ModifyAudioSettings" /><uses-permission android:name="android.permission.FLASHLIGHT" /><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.USE_FINGERPRINT" /><uses-permission android:name="android.permission.VIBRATE" /><uses-permission android:name="android.permission.WAKE_LOCK" /><uses-permission android:name="android.permission.WRITE_SETTINGS" /><uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT" /><uses-permission android:name="android.permission.CaptureSecureVideoOutput" /><uses-permission android:name="android.permission.CaptureVideoOutput" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.BATTERY_STATS" /><queries><intent><action android:name="android.media.action.IMAGE_CAPTURE" /></intent></queries>
</manifest>

2. 添加文件 Platforms/Android/PermissionManagingBlazorWebChromeClient.cs

using Android;
using Android.App;
using Android.Content.PM;
using Android.Graphics;
using Android.OS;
using Android.Views;
using Android.Webkit;
using AndroidX.Activity;
using AndroidX.Activity.Result;
using AndroidX.Activity.Result.Contract;
using AndroidX.Core.Content;
using Java.Interop;
using System;
using System.Collections.Generic;
using View = Android.Views.View;
using WebView = Android.Webkit.WebView;namespace BlazorMaui;internal class PermissionManagingBlazorWebChromeClient : WebChromeClient, IActivityResultCallback
{// This class implements a permission requesting workflow that matches workflow recommended// by the official Android developer documentation.// See: https://developer.android.com/training/permissions/requesting#workflow_for_requesting_permissions// The current implementation supports location, camera, and microphone permissions. To add your own,// update the s_rationalesByPermission dictionary to include your rationale for requiring the permission.// If necessary, you may need to also update s_requiredPermissionsByWebkitResource to define how a specific// Webkit resource maps to an Android permission.// In a real app, you would probably use more convincing rationales tailored toward what your app does.private const string CameraAccessRationale = "This app requires access to your camera. Please grant access to your camera when requested.";private const string LocationAccessRationale = "This app requires access to your location. Please grant access to your precise location when requested.";private const string MicrophoneAccessRationale = "This app requires access to your microphone. Please grant access to your microphone when requested.";private static readonly Dictionary<string, string> s_rationalesByPermission = new(){[Manifest.Permission.Camera] = CameraAccessRationale,[Manifest.Permission.AccessFineLocation] = LocationAccessRationale,[Manifest.Permission.RecordAudio] = MicrophoneAccessRationale,// Add more rationales as you add more supported permissions.};private static readonly Dictionary<string, string[]> s_requiredPermissionsByWebkitResource = new(){[PermissionRequest.ResourceVideoCapture] = new[] { Manifest.Permission.Camera },[PermissionRequest.ResourceAudioCapture] = new[] { Manifest.Permission.ModifyAudioSettings, Manifest.Permission.RecordAudio },// Add more Webkit resource -> Android permission mappings as needed.};private readonly WebChromeClient _blazorWebChromeClient;private readonly ComponentActivity _activity;private readonly ActivityResultLauncher _requestPermissionLauncher;private Action<bool>? _pendingPermissionRequestCallback;public PermissionManagingBlazorWebChromeClient(WebChromeClient blazorWebChromeClient, ComponentActivity activity){_blazorWebChromeClient = blazorWebChromeClient;_activity = activity;_requestPermissionLauncher = _activity.RegisterForActivityResult(new ActivityResultContracts.RequestPermission(), this);}public override void OnCloseWindow(Android.Webkit.WebView? window){_blazorWebChromeClient.OnCloseWindow(window);_requestPermissionLauncher.Unregister();}public override void OnGeolocationPermissionsShowPrompt(string? origin, GeolocationPermissions.ICallback? callback){ArgumentNullException.ThrowIfNull(callback, nameof(callback));RequestPermission(Manifest.Permission.AccessFineLocation, isGranted => callback.Invoke(origin, isGranted, false));}public override void OnPermissionRequest(PermissionRequest? request){ArgumentNullException.ThrowIfNull(request, nameof(request));if (request.GetResources() is not { } requestedResources){request.Deny();return;}RequestAllResources(requestedResources, grantedResources =>{if (grantedResources.Count == 0){request.Deny();}else{request.Grant(grantedResources.ToArray());}});}private void RequestAllResources(Memory<string> requestedResources, Action<List<string>> callback){if (requestedResources.Length == 0){// No resources to request - invoke the callback with an empty list.callback(new());return;}var currentResource = requestedResources.Span[0];var requiredPermissions = s_requiredPermissionsByWebkitResource.GetValueOrDefault(currentResource, Array.Empty<string>());RequestAllPermissions(requiredPermissions, isGranted =>{// Recurse with the remaining resources. If the first resource was granted, use a modified callback// that adds the first resource to the granted resources list.RequestAllResources(requestedResources[1..], !isGranted ? callback : grantedResources =>{grantedResources.Add(currentResource);callback(grantedResources);});});}private void RequestAllPermissions(Memory<string> requiredPermissions, Action<bool> callback){if (requiredPermissions.Length == 0){// No permissions left to request - success!callback(true);return;}RequestPermission(requiredPermissions.Span[0], isGranted =>{if (isGranted){// Recurse with the remaining permissions.RequestAllPermissions(requiredPermissions[1..], callback);}else{// The first required permission was not granted. Fail now and don't attempt to grant// the remaining permissions.callback(false);}});}private void RequestPermission(string permission, Action<bool> callback){// This method implements the workflow described here:// https://developer.android.com/training/permissions/requesting#workflow_for_requesting_permissionsif (ContextCompat.CheckSelfPermission(_activity, permission) == Permission.Granted){callback.Invoke(true);}else if (_activity.ShouldShowRequestPermissionRationale(permission) && s_rationalesByPermission.TryGetValue(permission, out var rationale)){new AlertDialog.Builder(_activity).SetTitle("Enable app permissions")!.SetMessage(rationale)!.SetNegativeButton("No thanks", (_, _) => callback(false))!.SetPositiveButton("Continue", (_, _) => LaunchPermissionRequestActivity(permission, callback))!.Show();}else{LaunchPermissionRequestActivity(permission, callback);}}private void LaunchPermissionRequestActivity(string permission, Action<bool> callback){if (_pendingPermissionRequestCallback is not null){throw new InvalidOperationException("Cannot perform multiple permission requests simultaneously.");}_pendingPermissionRequestCallback = callback;_requestPermissionLauncher.Launch(permission);}void IActivityResultCallback.OnActivityResult(Java.Lang.Object isGranted){var callback = _pendingPermissionRequestCallback;_pendingPermissionRequestCallback = null;callback?.Invoke((bool)isGranted);}#region Unremarkable overrides// See: https://github.com/dotnet/maui/issues/6565public override JniPeerMembers JniPeerMembers => _blazorWebChromeClient.JniPeerMembers;public override Bitmap? DefaultVideoPoster => _blazorWebChromeClient.DefaultVideoPoster;public override Android.Views.View? VideoLoadingProgressView => _blazorWebChromeClient.VideoLoadingProgressView;public override void GetVisitedHistory(IValueCallback? callback)=> _blazorWebChromeClient.GetVisitedHistory(callback);public override bool OnConsoleMessage(ConsoleMessage? consoleMessage)=> _blazorWebChromeClient.OnConsoleMessage(consoleMessage);public override bool OnCreateWindow(WebView? view, bool isDialog, bool isUserGesture, Message? resultMsg)=> _blazorWebChromeClient.OnCreateWindow(view, isDialog, isUserGesture, resultMsg);public override void OnGeolocationPermissionsHidePrompt()=> _blazorWebChromeClient.OnGeolocationPermissionsHidePrompt();public override void OnHideCustomView()=> _blazorWebChromeClient.OnHideCustomView();public override bool OnJsAlert(WebView? view, string? url, string? message, JsResult? result)=> _blazorWebChromeClient.OnJsAlert(view, url, message, result);public override bool OnJsBeforeUnload(WebView? view, string? url, string? message, JsResult? result)=> _blazorWebChromeClient.OnJsBeforeUnload(view, url, message, result);public override bool OnJsConfirm(WebView? view, string? url, string? message, JsResult? result)=> _blazorWebChromeClient.OnJsConfirm(view, url, message, result);public override bool OnJsPrompt(WebView? view, string? url, string? message, string? defaultValue, JsPromptResult? result)=> _blazorWebChromeClient.OnJsPrompt(view, url, message, defaultValue, result);public override void OnPermissionRequestCanceled(PermissionRequest? request)=> _blazorWebChromeClient.OnPermissionRequestCanceled(request);public override void OnProgressChanged(WebView? view, int newProgress)=> _blazorWebChromeClient.OnProgressChanged(view, newProgress);public override void OnReceivedIcon(WebView? view, Bitmap? icon)=> _blazorWebChromeClient.OnReceivedIcon(view, icon);public override void OnReceivedTitle(WebView? view, string? title)=> _blazorWebChromeClient.OnReceivedTitle(view, title);public override void OnReceivedTouchIconUrl(WebView? view, string? url, bool precomposed)=> _blazorWebChromeClient.OnReceivedTouchIconUrl(view, url, precomposed);public override void OnRequestFocus(WebView? view)=> _blazorWebChromeClient.OnRequestFocus(view);public override void OnShowCustomView(View? view, ICustomViewCallback? callback)=> _blazorWebChromeClient.OnShowCustomView(view, callback);public override bool OnShowFileChooser(WebView? webView, IValueCallback? filePathCallback, FileChooserParams? fileChooserParams)=> _blazorWebChromeClient.OnShowFileChooser(webView, filePathCallback, fileChooserParams);#endregion
}

3. 文件 MainPage.xaml

添加 x:Name="_blazorWebView"

    <BlazorWebView x:Name="_blazorWebView" HostPage="wwwroot/index.html"><BlazorWebView.RootComponents><RootComponent Selector="#app" ComponentType="{x:Type shared:App}" /></BlazorWebView.RootComponents></BlazorWebView> 

4. 文件 MainPage.xaml.cs

添加
_blazorWebView.BlazorWebViewInitialized += BlazorWebViewInitialized; _blazorWebView.BlazorWebViewInitializing += BlazorWebViewInitializing;

完整代码:

using LibraryShared;
using Microsoft.AspNetCore.Components.WebView;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using System;
using static Microsoft.Maui.ApplicationModel.Permissions;
#if ANDROID
using AndroidX.Activity;
#endifnamespace BlazorMaui
{public partial class MainPage : ContentPage{public MainPage(){InitializeComponent();_blazorWebView.BlazorWebViewInitialized += BlazorWebViewInitialized;_blazorWebView.BlazorWebViewInitializing += BlazorWebViewInitializing;}private void BlazorWebViewInitialized(object? sender, BlazorWebViewInitializedEventArgs e){
#if ANDROIDif (e.WebView.Context?.GetActivity() is not ComponentActivity activity){throw new InvalidOperationException($"The permission-managing WebChromeClient requires that the current activity be a '{nameof(ComponentActivity)}'.");}e.WebView.Settings.JavaScriptEnabled = true;e.WebView.Settings.AllowFileAccess = true;e.WebView.Settings.MediaPlaybackRequiresUserGesture = false;e.WebView.Settings.SetGeolocationEnabled(true);e.WebView.Settings.SetGeolocationDatabasePath(e.WebView.Context?.FilesDir?.Path);e.WebView.SetWebChromeClient(new PermissionManagingBlazorWebChromeClient(e.WebView.WebChromeClient!, activity));
#endif}private void BlazorWebViewInitializing(object? sender, BlazorWebViewInitializingEventArgs e){
#if IOS || MACCATALYST                   e.Configuration.AllowsInlineMediaPlayback = true;e.Configuration.MediaTypesRequiringUserActionForPlayback = WebKit.WKAudiovisualMediaTypes.None;
#endif}}
}

4. 其他更改

由于工程是一个共享库给多端用,先定义了一个接口用于注入服务到页面调用演示功能

    public interface ITools{Task<string> CheckPermissionsCamera();Task<string> TakePhoto();Task<string> CheckPermissionsLocation();Task<string> GetCachedLocation();Task<string> GetCurrentLocation();Task<string> CheckMock();double DistanceBetweenTwoLocations();void ShowSettingsUI();string GetAppInfo();}

调用MAUI的API功能 BlazorMaui/Services/TestService.cs

#if WINDOWS
using Windows.Storage;
#endif
#if ANDROID
using Android.Webkit;
#endif
using BlazorShared.Services;
using System.Security.Permissions;namespace LibraryShared
{public class TestService : ITools{public string GetAppInfo() {//读取应用信息string name = AppInfo.Current.Name;string package = AppInfo.Current.PackageName;string version = AppInfo.Current.VersionString;string build = AppInfo.Current.BuildString;return $"{name},{version}.{build}";}public void ShowSettingsUI(){//显示应用设置AppInfo.Current.ShowSettingsUI();}public async Task<string> CheckPermissionsCamera(){//检查权限的当前状态PermissionStatus status = await Permissions.CheckStatusAsync<Permissions.Camera>();//请求权限if (status != PermissionStatus.Granted){status = await Permissions.RequestAsync<Permissions.Camera>();}return status.ToString();}public async Task<string> CheckPermissionsLocation(){//检查权限的当前状态PermissionStatus status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();//请求权限if (status != PermissionStatus.Granted){status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();}return status.ToString();}/// <summary>/// 拍照/// CapturePhotoAsync调用该方法以打开相机,让用户拍照。 如果用户拍照,该方法的返回值将是非 null 值。/// 以下代码示例使用媒体选取器拍摄照片并将其保存到缓存目录:/// </summary>public async Task<string> TakePhoto(){await CheckPermissionsCamera();if (MediaPicker.Default.IsCaptureSupported){FileResult photo = await MediaPicker.Default.CapturePhotoAsync();if (photo != null){// save the file into local storagestring localFilePath = Path.Combine(FileSystem.CacheDirectory, photo.FileName);using Stream sourceStream = await photo.OpenReadAsync();using FileStream localFileStream = File.OpenWrite(localFilePath);await sourceStream.CopyToAsync(localFileStream);return localFilePath;}return "photo null";}return null;}/// <summary>/// 获取最后一个已知位置, 设备可能已缓存设备的最新位置。/// 使用此方法 GetLastKnownLocationAsync 访问缓存的位置(如果可用)。/// 这通常比执行完整位置查询更快,但可能不太准确。/// 如果不存在缓存位置,此方法将 null返回 。/// </summary>/// <returns></returns>public async Task<string> GetCachedLocation(){await CheckPermissionsLocation();string result = null;try{Location location = await Geolocation.Default.GetLastKnownLocationAsync();if (location != null){result = $"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude: {location.Altitude}";Console.WriteLine(result);return result;}}catch (FeatureNotSupportedException fnsEx){// Handle not supported on device exceptionresult = $"not supported on device, {fnsEx.Message}";}catch (FeatureNotEnabledException fneEx){// Handle not enabled on device exceptionresult = $"not enabled on device, {fneEx.Message}";}catch (PermissionException pEx){// Handle permission exceptionresult = $"permission, {pEx.Message}";}catch (Exception ex){// Unable to get locationresult = $"Unable to get location, {ex.Message}";}return result ?? "None";}private CancellationTokenSource _cancelTokenSource;private bool _isCheckingLocation;/// <summary>/// 获取当前位置/// 虽然检查设备 的最后已知位置 可能更快,但它可能不准确。/// 使用该方法 GetLocationAsync 查询设备的当前位置。/// 可以配置查询的准确性和超时。/// 最好是使用 GeolocationRequest 和 CancellationToken 参数的方法重载,/// 因为可能需要一些时间才能获取设备的位置。/// </summary>/// <returns></returns>public async Task<string> GetCurrentLocation(){await CheckPermissionsLocation();string result = null;try{_isCheckingLocation = true;GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(10));_cancelTokenSource = new CancellationTokenSource();#if IOS//从 iOS 14 开始,用户可能会限制应用检测完全准确的位置。//该 Location.ReducedAccuracy 属性指示位置是否使用降低的准确性。//若要请求完全准确性,请将 GeolocationRequest.RequestFullAccuracy 属性设置为 truerequest.RequestFullAccuracy = true;
#endifLocation location = await Geolocation.Default.GetLocationAsync(request, _cancelTokenSource.Token);if (location != null){result = $"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude: {location.Altitude}";Console.WriteLine(result);return result;}}catch (FeatureNotSupportedException fnsEx){// Handle not supported on device exceptionresult = $"not supported on device, {fnsEx.Message}";}catch (FeatureNotEnabledException fneEx){// Handle not enabled on device exceptionresult = $"not enabled on device, {fneEx.Message}";}catch (PermissionException pEx){// Handle permission exceptionresult = $"permission, {pEx.Message}";}catch (Exception ex){// Unable to get locationresult = $"Unable to get location, {ex.Message}";}finally{_isCheckingLocation = false;}return result ?? "None";}}
}

MauiProgram.cs文件注入

builder.Services.AddSingleton<ITools, TestService>();

razor

        <Button Text="定位权限" OnClick="检查定位权限" /><span>@定位权限</span><br/><br/><Button Text="摄像机权限" OnClick="检查摄像机权限" /><span>@摄像机权限</span><br /><br /><Button Text="定位" OnClick="获取定位" /><span>@Locations</span><br /><br /><Button Text="TakePhoto" OnClick="TakePhoto" /><span>@PhotoFilename</span><br /><br /><Button Text="ShowSettings" OnClick="ShowSettingsUI" /><span>@version</span><br /><br />@code{[Inject] protected ITools Tools { get; set; }private string Locations;private string PhotoFilename;private string version;private string 定位权限;private string 摄像机权限;async Task 获取定位() => Locations = await Tools.GetCurrentLocation();async Task TakePhoto() => PhotoFilename = await Tools.TakePhoto();async Task 检查定位权限() => 定位权限 = await Tools.CheckPermissionsLocation();async Task 检查摄像机权限() => 摄像机权限 = await Tools.CheckPermissionsCamera();void ShowSettingsUI() =>   Tools.ShowSettingsUI();
}

###最终效果
在这里插入图片描述

在这里插入图片描述

项目地址

https://github.com/densen2014/BlazorMaui

https://gitee.com/densen2014/BlazorMaui

参考资料

Permissions
https://docs.microsoft.com/en-us/dotnet/maui/platform-integration/appmodel/permissions?tabs=android

Geolocation
https://docs.microsoft.com/en-us/dotnet/maui/platform-integration/device/geolocation?tabs=windows

MauiBlazorPermissionsExample
https://github.com/MackinnonBuck/MauiBlazorPermissionsExample

关联项目

FreeSql QQ群:4336577、8578575、52508226

BA & Blazor QQ群:795206915、675147445

知识共享许可协议

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名AlexChow(包含链接: https://github.com/densen2014 ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系 。

AlexChow

今日头条 | 博客园 | 知乎 | Gitee | GitHub


http://chatgpt.dhexx.cn/article/TCkZAJmb.shtml

相关文章

UniApp 实战指南

uni-app 是一个使用 Vue.js 开发所有前端应用的框架&#xff0c;开发者编写一套代码&#xff0c;可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等多个平台。 打包原生 APP 申请 AppKey 登录 DCloud 管理应用 点击…

Android Studio 插件大全(转)

转自&#xff1a;http://blog.csdn.net/alpha58/article/details/62881144 现在Android的开发者基本上都使用android Studio进行开发(如果你还在使用eclipse那也行&#xff0c;毕竟你乐意怎么样都行)。使用好Android Studio插件能大量的减少我们的工作量。 1.GsonFormat 快速…

定位技术课程设计-微信小程序校园导游系统

定位技术课程设计课程设计教学目的课程设计要求课程设计题目原题目拓展内容需求分析原理分析微信小程序API定位原理WIFI指纹定位原理路径规划算法调研详细设计总述主页面介绍学校简介页面介绍导引页面概述导引地图景点列表景点详细介绍页面搜索界面导航页面概述导航逻辑驾车导航…

前端知识——盒子类型,浮动属性,定位属性,JavaScript基础语法

文章目录 CSS—盒子类型marginpadding 浮动属性CSS—溢出属性overflow的设置项 CSS—定位属性定位状态定位操作 CSS—z-indexJavaScript简介主要功能运行模式变量与注释数据类型数据类型之数值类型(Number)数据类型之字符串类型(String) CSS—盒子类型 所有的标签其实都有一个…

python转js解释器_python 代码转换 js

广告关闭 腾讯云11.11云上盛惠 &#xff0c;精选热门产品助力上云&#xff0c;云服务器首年88元起&#xff0c;买的越多返的越多&#xff0c;最高返5000元&#xff01; 推荐使用腾讯云 api 配套的7种常见的编程语言 sdk&#xff0c;已经封装了签名和请求过程&#xff0c;均已…

android 图像识别定位,Android OpenCV 图像识别

最近打算写一个android 平台opencv 的小程序,着手查找了一下资料.网络上的资料参差不齐,有一些都比较老旧,我参考了前面的方法找到了一个简单的搭建方法,分享给大家. 0,环境的搭建: java 虚拟机环境搭建,网络资料很多不再赘述. 下面说明如果搭建 android opencv 环境: 下载Open…

安卓逆向及JavaScript实战

沐阳~ 各种案例&#xff0c;瑞树啥的&#xff0c;等等&#xff0c;案例多。 安卓逆向如下&#xff1a; 主&#xff1a; 沐阳~ 课程如下&#xff1a; 1.(ndk)1.初始NDK.mp4 1.(ndk)2.NDK性能提升及数据类型.mp4 1.(ndk)3.JAVA反射结合NDK.mp4 1.(ndk)4.JVM和JNI.mp4 1.(ndk)4.…

js逆向、安卓逆向教程

JS基础 提示信息 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn 1.零基础js逆向专题 MD5通杀 长度32位置 搜索关键词&#xff1a; 16进制 0x67452301 10进制 1732584193 RSA 搜索关键词&#xff1a; setpublickey AES cryptojs.aes DES cryptojs.des.encrypt …

学习强国---Android逆向及JS逆向

沐阳~ 各种案例&#xff0c;瑞树啥的&#xff0c;等等&#xff0c;案例多。有意私我&#xff0c;优惠大大 安卓逆向如下&#xff1a; 主&#xff1a; 沐阳~ 课程如下&#xff1a; 1.(ndk)1.初始NDK.mp4 1.(ndk)2.NDK性能提升及数据类型.mp4 1.(ndk)3.JAVA反射结合NDK.mp4 1.(…

js加密参数定位

当我们抓取网页端数据时&#xff0c;经常被加密参数、加密数据所困扰&#xff0c;如何快速定位这些加解密函数&#xff0c;尤为重要。本片文章是我逆向js时一些技巧的总结&#xff0c;如有遗漏&#xff0c;欢迎补充。 所需环境&#xff1a;Chrome浏览器 1. 搜索 1.1 全局搜索…

【APP 逆向百例】Frida 初体验,root 检测与加密字符串定位

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;不提供完整代码&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 本文章未…

巴斯勒相机acA1300-60gm

Basler acA1300-60gm GigE 相机配有 e2v EV76C560 CMOS 感光芯片&#xff0c;每秒 60 帧图像&#xff0c;130 万像素分辨率。

如何选择合适的工业相机

如何选择合适的工业相机 目录 如何选择合适的工业相机简洁具体**多相机检测****工业相机的白平衡知识**工业相机的参数工业数字相机常见问题解决方案参考文献 简洁 工业相机有许多项参数&#xff0c;选择合适的工业相机既要考虑工业相机的参数&#xff0c;也要考虑到项目的精度…

巴斯勒BASLER GIGE相机程序调试报错后需要拔网线

巴斯勒BASLER GIGE相机程序调试报错后需要拔网线的个人解决方案 根据SDK的用户手册提示&#xff0c;在相机连接后&#xff0c;直接执行以下程序。 camera.Parameters[PLTransportLayer.HeartbeatTimeout].TrySetValue(1000,IntegerValueCorrection.Nearest); // 1000 ms time…

机器视觉_工业相机及相关配件选型

文章目录 工业相机一、 概述二、 相机参数1. 传感器芯片1.1. CCD&CMOS1.2. CCD1.3. CMOS1.4. 靶面1.5. 传感器芯片选型 2. 黑白or彩色3. 帧数⭐4. 接口类型4.1. POE供电 三、相关硬件⭐1. 镜头1.1. 焦距⭐1.2. 视野⭐1.3. 物距1.4. 景深⭐1.5. 调焦1.6. 镜头的一些理论小知…

Ubuntu环境下配置巴斯勒相机及相机测试

Ubuntu环境下配置巴斯勒相机及相机测试 Ubuntu配置巴斯勒相机及相机测试软硬件要求Ubuntu虚拟系统安装安装c编译器安装Sublime Text 3及配置C运行环境配置巴斯勒相机SDK及代码测试 Ubuntu配置巴斯勒相机及相机测试 软硬件要求 软件 我们对Markdown编辑器进行了一些功能拓展与…

Python之OpenCV 005 工业相机Basler之图像采集

工业机器视觉系统2D应用用到Basler&#xff08;德国&#xff09;&#xff0c;Baumer&#xff08;瑞士&#xff09;&#xff0c;ImageSource&#xff08;台湾&#xff09;&#xff0c;大恒和海康等等牌子工业相机。 Basler&#xff08;巴斯勒&#xff09;是比较常用的&#xff…

机器视觉 · 工业相机

文章目录 工业相机 面阵相机工业相机 线阵相机工业相机 光场相机工业相机 棱镜相机工业相机 多光谱/高光谱工业相机 偏振相机工业相机 传感器 CCD工业相机 传感器 ICCD工业相机 传感器 EMCCD工业相机 传感器 CMOS工业相机 传感器 sCMOS工业相机 传感器 红外探…

BASLER巴斯勒线扫相机使用流程

(Q有答疑)康耐视智能相机Insight-OCR读取案例 1、相机连接—线缆连接 将相机电源线、网线与相机连接,网线另一端连接电脑 无编码器触发时,只需连接网线、电源线即可 2、修改电脑IP 3、修改相机IP 4、相机连接—软件连接 连接相机有两种方式: 1、双击该相机型号进行连接;…

basler工业相机使用经验小记

1&#xff0c;windows10的系统&#xff0c;要用&#xff15;以上的&#xff53;&#xff44;&#xff4b;不然打不开相机。 &#xff12;&#xff0c;如果用&#xff4f;&#xff50;&#xff45;&#xff4e;&#xff43;&#xff56;或&#xff56;&#xff53;程序打开忘记…