. net多平台App UI(。NET MAUI)是一个跨平台的框架,用于使用c#和XAML创建本地移动和桌面应用程序。使用。net MAUI,你可以从一个共享代码库开发出可以在Android和iOS上运行的应用程序。
. net MAUI是开源的,是Xamarin的进化。形式,extended from mobile to desktop scenarios, with UI controls rebuilt from the ground up for performance and extensibility. If you've previously used Xamarin.Forms to build cross-platform user interfaces, you'll notice many similarities with .NET MAUI. However, there are also some differences. Using .NET MAUI, you can create multi-platform apps using a single project, but you can add platform-specific source code and resources if necessary. One of the key aims of .NET MAUI is to enable you to implement as much of your app logic and UI layout as possible in a single code-base.
在这里你可以阅读更多关于MAUI及其工作原理的信息。
1.要创建。net MAUI应用程序,你至少需要Visual Studio 2022 17.3预览或更高版本:
要么安装Visual Studio,要么修改你的安装,然后用默认的可选安装选项安装。net多平台应用UI开发工作负载:
2.启动Visual Studio,并在开始窗口中单击创建一个新项目创建一个新项目。在创建一个新项目窗口中,选择毛伊岛在所有项目类型下拉菜单,选择.NET MAUI应用程序模板,并单击下一个按钮:
3.在配置您的新项目窗口,为项目命名,为其选择合适的位置,然后单击下一个按钮:
4.在额外的信息窗口中,单击创建按钮:
等待项目创建完成,并恢复其依赖项。
5.目前我们的SDK只支持Android和iOS平台。这就是为什么您需要从项目中删除其他平台(maccatalyst和windows)。的TargetFrameworks中删除它们cmbSDKMauiSample.csproj以及平台中的项目文件:
我们将SDK作为nuget包发布https://www.nuget.org.请安装Cognex.cmbSDK.Maui这个项目的Nuget包。
如果一切正常,cognexx . cmbsdk . maui应该列在两个平台的包中:
为了使用移动设备的内置摄像头,您需要声明摄像头权限。
android在AndroidManifest.xml文件中设置,iOS在Info中设置。Plist(你需要用文本编辑器打开这个文件):
当所有这些都作为最后一步完成时,我们需要为这个程序注册本地处理程序。开放MauiProgram.cs文件和配置毛伊处理器:
要在没有MX移动终端的移动设备上使用cmbSDK进行条形码扫描,需要安装许可密钥。如果许可证密钥缺失,将出现星号而不是扫描结果。
有关如何获取许可证密钥(包括30天试用许可证)的信息,请与您的康耐视销售代表联系。
如果你获得了跨平台许可证(两个平台都有一个许可证),当你创建摄像头扫描仪时,直接从代码中实现激活:
如果(param_deviceClass = = ScannerDevice.PhoneCamera ) { //*************************************************************************************** // 创建一个照相扫描器/ / / /注意:如果我们使用内置摄像头扫描/ /手机或平板电脑,然后SDK需要许可证密钥。参考// SDK关于获取许可密钥的文档以及//将密钥传递给SDK的方法(在本例中,我们依赖于// info中的一个条目)。plist和androidmanifest.xml——也有ScannerCameraMode方法,它可以作为参数传递)。//*************************************************************************************** scannerControl。GetPhoneCameraDevice (param_cameraMode ScannerPreviewOption。默认值,true, "SDK_KEY");}
否则,如果你有不同的键(键仅用于iOS和键仅用于Android),将这些键添加到AndroidManifest.xml或Info中。plist文件。
对于Android,在应用程序的AndroidManifest.xml文件的application标签下添加以下一行:
<应用>…
对于iOS,在项目特定的信息中添加它作为一个键值。plist文件:
MX_MOBILE_LICENSE 您的license密钥 . key>MX_MOBILE_LICENSE
1.当你构建UI时,考虑到如果你想显示部分屏幕,你需要为scannerControl设置大小通过设置父布局大小。永远记住扫描仪控制填充父大小。ScannerControl表示阅读器设备,当你创建相机扫描仪时,在构造函数中发送假作为全屏的输入参数。
如果您想使用全屏预览设置0为父布局的大小scannerControl在构造函数send中真正的作为全屏的输入参数(就像在我们的示例应用程序)。
2.设置以下事件处理程序来监视scannerControl的连接状态,并接收有关已读代码的信息:
//当一个MX-1xxx设备变得可用(USB电缆被插入,或MX设备被打开),//或当一个MX-1xxx之前可用已经变得不可用(USB电缆被拔出,由于不活动或电池耗尽而关闭)时调用。if (availability == ScannerAvailability.Available) {ConnectToScannerDevice();} else if (availability == ScannerAvailability.Unavailable) {DisplayAlert("设备不可用",null, "OK");}} //连接方法已经完成,在这里你可以看到建立连接是否有错误// (args:scanerexceptions exception, string errorMessage) public void OnConnectionCompleted(对象sender,对象[]args){//如果我们有有效的连接错误参数将为空,//否则这里是错误,通知我们的问题,我们连接到扫描仪If ((ScannerExceptions)args[0] != ScannerExceptions. noexception){//如果必要,要求相机权限(仅android,对于iOS我们处理来自SDK的权限)if ((ScannerExceptions)args[0] == ScannerExceptions. camerapermissionexception) RequestCameraPermission();else {Debug.WriteLine(args[1].ToString());UpdateUIByConnectionState (ScannerConnectionStatus.Disconnected);}}} //当与扫描器的连接被改变时调用。OnConnectionStateChanged(对象sender, ScannerConnectionStatus状态){ClearResult(); if (status == ScannerConnectionStatus.Connected) { // We just connected, so now configure the device how we want it ConfigureScannerDevice(); } isScanning = false; UpdateUIByConnectionState(status); } // This is called after scanning has completed, either by detecting a barcode, canceling the scan by using the on-screen button or a hardware trigger button, or if the scanning timed-out public void OnReadResultReceived(object sender, List results) { ClearResult(); if (results?.Count > 0) { lblResultText.Text = results[0].ResultCode; lblResultType.Text = results[0].ResultSymbology; } isScanning = false; btnScan.Text = "START SCANNING"; }
3.创建扫描设备。我们将在下一节中解释这一点。
使用以下工厂方法初始化MX阅读器的扫描设备对象:
//*************************************************************************************** // 创建一个MX-1xxx扫描仪(注意,没有许可证密钥 ) //*************************************************************************************** scannerControl.GetMXDevice ();
MX移动终端的可用性可能会在设备打开或关闭,或者连接或断开USB线时发生变化。您可以使用下面的方法处理这些更改AvailabilityChanged事件处理程序:
OnAvailabilityChanged(对象发送者,扫描可用性可用性)
建议使用MX移动终端扫描条形码。但是,cmbSDK还支持使用移动设备的内置摄像头。这包括支持可选的外部瞄准器或照明,以及自定义直播预览的外观。
若要使用移动设备的内置摄像头扫描条形码,请初始化扫描设备对象使用scannerControl。GetPhoneCameraDevice方法。相机读取器初始化时有几个选项。需要配置以下参数:
的ScannerCameraMode参数的类型为ScannerCameraMode枚举,它接受下表中列出的值之一。
这些模式为扫描仪提供了以下默认设置:
根据所选择的模式,设置额外的照明选项和行为,也列在表格中。
价值 | 描述 | 照明 | 直播预览 |
---|---|---|---|
NoAimer | 初始化阅读器以在移动设备屏幕上使用实时流预览,以便用户可以将条形码定位在摄像机的视野内以进行检测和解码。如果移动设备没有瞄准配件,请使用此模式。 | 照明是可用的,一个按钮来控制它是可见的直播流预览。 | 显示 |
如果命令被发送给阅读器进行瞄准器控制,则它们将被忽略。 | |||
PassiveAimer | 初始化读取器以使用被动瞄准器。在这种模式下,设备屏幕上没有直播预览,因为瞄准模式是投影的。 | 照明是不可用的,并且直播预览没有照明按钮。 | 不显示 |
如果命令被发送到阅读器进行照明控制,它们将被忽略,因为在这种模式下,假设移动设备的内置LED被用于瞄准器。 | |||
ActiveAimer (仅适用于iOS) |
时,直播预览将不会显示StartScanning ()方法默认调用。 | 照明是可用的,如果一个预览选项相机预览启用,照明控制按钮也是可用的。 | 不显示 |
接受照明或瞄准器控制命令。 | |||
FrontCamera | 初始化阅读器以使用移动设备的前置摄像头(如果可用)。使用这种配置时要小心,因为大多数前置摄像头都没有自动对焦和照明,提供的图像分辨率也明显较低。照明在此模式下不可用。 | 使用前置摄像头。 | 显示 |
照明是不可用的,实时流预览没有照明按钮。 | |||
如果命令被发送到阅读器用于瞄准器或照明控制,它们将被忽略。 |
扫描仪PreviewOption参数的类型为ScannerPreviewOptionenum,用于更改阅读器的默认值或覆盖从所选扫描器派生的默认值CameraMode.您可以指定以下选项:
价值 | 描述 |
---|---|
违约 | 接受CameraMode设置的所有默认值。 |
NoZoomButton | 隐藏实时流预览上的缩放按钮,防止用户调整移动设备相机的缩放。 |
NoIlluminationButton | 隐藏直播预览上的照明按钮,防止用户切换照明。 |
HardwareTrigger | 启用模拟硬件触发器(音量降低按钮),以便在移动设备上开始扫描。这个按钮只在按下时才开始扫描,不需要像专用扫描仪的触发器那样按住它,第二次按下它也不会停止扫描过程。 |
停顿了一下 | 如果使用实时流预览,则在startScanning ()方法调用,但是直到用户按下屏幕上的按钮开始扫描过程时,阅读器才开始解码。 |
AlwaysShow | 即使选择了瞄准模式(例如CameraMode == PASSIVE_AIMER),也会强制显示实时流预览。 |
PessimisticCaching | 使用更高分辨率的设备摄像头,在支持它的设备上将默认的1280x720分辨率更改为1920x1080,在不支持它的设备上更改为默认分辨率。这可以帮助扫描小条形码,但增加解码时间,因为每帧有更多的数据需要处理。 |
HighResolution (仅适用于iOS) |
使用较高分辨率的设备摄像头帮助扫描小条码,但解码时间较慢。该选项在支持该选项的设备上将分辨率设置为1920x1080,在不支持该选项的设备上将分辨率设置为默认值。默认分辨率为1280x720。 |
HighFrameRate | 使用设备的相机在60 FPS,而不是默认的30 FPS,以提供一个更流畅的相机预览。 |
ShowCloseButton | 在局部视图中显示关闭按钮。 |
KeepPreviewInPausedState | 读取或超时后保持预览暂停状态。 |
如果全屏参数已设置真正的时,使用全屏预览,否则使用部分屏预览。
的RegistrationKey(可选)参数用于使用您拥有的许可密钥授权您的SDK
例子:
创建一个没有瞄准器和全屏直播预览的阅读器:
scannerControl.GetPhoneCameraDevice (ScannerCameraMode。NoAimer ScannerPreviewOption。违约,真实);
创建一个没有瞄准器,没有缩放按钮,并使用模拟触发器的阅读器:
scannerControl.GetPhoneCameraDevice (ScannerCameraMode。NoAimer ScannerPreviewOption。NoZoomButton|ScannerPreviewOption.HardwareTrigger,真正的);
对于Android 6.0及以上版本,您需要向用户请求访问移动设备内置摄像头的权限。
如果由于权限问题而无法打开摄像机,则OnConnectionCompleted(发送者,args)回调包含ScannerException在参数args中。您可以检查这种异常类型并请求权限。
公共空间OnConnectionCompleted(对象发送方,object [] args){/ /如果我们有有效的连接错误参数将null, / /否则这是错误,告知我们的问题,我们有同时连接扫描仪,如果((ScannerExceptions) args [0] ! = ScannerExceptions.NoException){/ /要求相机允许在必要时(android, iOS我们处理许可SDK)如果(args (ScannerExceptions) [0] = = ScannerExceptions.CameraPermissionException) RequestCameraPermission ();...
如果相机权限被授予,您可以再次尝试在扫描设备上连接:
private async void RequestCameraPermission() {var result = await Permissions.RequestAsync();//查看权限请求结果。如果用户允许,连接到扫描仪If (result == permissionstatus . granting) {scannerControl.Connect();} else {if (Permissions.ShouldShowRationale()) {if (await DisplayAlert(null, "You need allow access to the Camera", "OK", "Cancel")) RequestCameraPermission();}}}
连接前,设置OnAvailabilityChanged,ConnectionStateChanged而且ConnectionCompleted事件处理程序。
public void OnAvailabilityChanged(对象发送者,ScannerAvailability可用性)public void OnConnectionStateChanged(对象发送者,ScannerConnectionStatus状态)public void OnConnectionCompleted(对象发送者,对象[]args)
方法初始化后调用connect方法ScannerDevice.
//在可以配置或使用扫描仪之前,需要建立一个连接private void ConnectToScannerDevice() {scannerControl.Connect();}
我们之前设置的事件处理程序将使用new调用ScannerDevice状态信息。
MX系列移动终端提供了复杂的设备配置和管理,包括保存在设备上的配置。MX设备是康耐视预先配置的,大多数符号和功能都可以使用。
如果您想要自定义配置,请通过DataMan安装工具或Cognex快速安装重新配置。这两种工具都可以轻松地将保存的配置分发到多个设备,以便进行简单的配置管理。
移动应用程序能够配置MX设备,让您选择:
cmbSDK使用一组默认选项用于移动设备的内置摄像头读取条形码。然而,有两个重要的区别需要记住:
CmbSDK不启用任何象征学默认情况下,通过移动设备的内置摄像头读取条形码。必须启用应用程序需要扫描的所有条形码符号,以实现最佳扫描性能。
控件的以下方法可以启用单个符号ScannerControl类:
SetSymbologyEnabled(符号符号,bool启用)
此方法中用于符号参数的所有符号都可以在符号学枚举。
例子
//显式启用我们需要的符号。Datamatrix,真正的);scannerControl.SetSymbologyEnabled(象征。C128,真正的);
你也可以使用相同的方法禁用符号:
//显式禁用我们知道不需要的符号。Codabar、假);
你可以实现symbolologyenabled事件处理程序来检查符号改变的结果:
// SymbologyEnabled监听器(args: symbologysymbolology, bool isEnabled, string error) public void OnSymbologyEnabled(对象发送器,对象[]args) {if ((string)args[2] != null)调试。WriteLine("Failed to enable/disable " + args[0].ToString());else Debug.WriteLine(((symbolology)args[0]).ToString() + (bool)args[1] ?" Enabled ": " disabled"));}
如果您的扫描设备配备了照明灯,您可以使用这个DMCC控制它们:
scannerControl。SendCommand(“光。INTERNAL-ENABLE”);
你可以在扫描预览激活时控制灯光,或者如果你在启动扫描仪之前发送这个DMCC,你将设置灯光的初始值。
如果使用移动设备的内置摄像头作为读取设备,您可以配置缩放级别及其使用方式。有三个缩放级别:
的设置相机。缩放百分比[100-max] [100-max]命令用于配置两个级别的缩放百分比。100不能放大,MAX(最高可达1000)会尽可能放大设备所能放大的范围。第一个参数用于设置1级缩放,第二个参数用于设置2级缩放。
控件可以检查当前的缩放设置让相机。ZOOM-PERCENT命令,该命令返回两个值:一级缩放和二级缩放。
例子
scannerControl。SendCommand(“设置相机。缩放比例250 500”);
获取/设置相机。变焦0 - 2另一个设置缩放级别或返回实际设置的命令。SET命令的取值包括:
您可以在扫描之前或甚至在扫描期间调用此命令,然后缩放上升到配置的级别。如果扫描完成,该值将重置为正常行为(0)。
例子
scannerControl。SendCommand(“设置相机。放大2”);
当使用移动设备的摄像头时,cmbSDK允许您在预览容器中或全屏查看摄像头预览。此预览还包含一个可定制的覆盖。cmbSDK相机覆盖功能按钮缩放,闪烁和关闭扫描仪,以及一个进度条指示扫描超时。
使用cmbSDK v2.0中最初使用的遗留摄像头覆盖。x和ManateeWorks SDK,在初始化ScannerDevice之前使用这个:
private void CreateScannerDevice() {if (param_deviceClass == ScannerDevice.PhoneCamera) {scannerControl.SetOverlay(ScannerOverlay.LEGACY);scannerControl.GetPhoneCameraDevice (ScannerCameraMode。NoAimer ScannerPreviewOption。违约,真实);}
当使用cmbSDK覆盖时:
cmbSDK和遗留的覆盖都允许您更改缩放和闪光按钮上使用的图像,如果您的图像具有与cmbSDK使用的名称相同的名称。您可以在参考资料/中找到cmbSDK中使用的图像和名称必威随行版官网drawable-mdpi而且drawable-hdpiAndroid和Resources/的目录必威随行版官网MWBScannerImages.xcassetsiOS。
cmbSDK和遗留的覆盖层都允许您更改检测到条形码时显示的矩形的颜色和宽度。这些更改需要在ConfigureScannerDevice()方法中完成(在我们有到扫描仪设备的有效连接之后)。
例子:
private void ConfigureScannerDevice(){扫描控制。System.Drawing.Color SetLegacyOverlayLocationLine(255。黄色,6.0f,真);...
康耐视扫描设备实现DataMan控制命令(DMCC),用于配置和控制设备。设备的每个功能都可以使用这种基于文本的语言进行控制。API提供了一种向设备发送DMC命令的方法。存在用于设置和查询配置属性的命令。DMC命令适用于所有平台和框架。
的附录包括完整的DMCC参考相机阅读器。
下面的例子展示了不同的DMCC发送到设备进行更高级的配置。
例子
//修改扫描方向为全向扫描控制。SendCommand("SET DECODER.1D-SYMBOLORIENTATION 0");//更改直播预览的扫描超时时间为10秒scannerControl. //SendCommand(“设置解码器。MAX-SCAN-TIMEOUT 10”);
你也可以设置responserecreceived事件处理程序来接收send命令的响应:
//发送DMCC命令(args: string payload, string error, string DMCC) public void onresponserecreceived (object sender, object[] args) {if ((string)args[1] != null)WriteLine(“执行DMCC失败”);其他调试。WriteLine("响应" +(字符串)args[2] + ": " +(字符串)args[0]);}
CmbSDK包括一个将设备重置为默认设置的方法。对于MX移动终端,默认配置为已保存的配置。对于内置摄像头,默认设置为附录,其中没有启用任何符号。
重置设备发送这个DMCC:
scannerControl.SendCommand(“CONFIG.DEFAULT”);
在使用MX移动终端时,我们可以区分三种状态:
有了正确配置的阅读器,就可以扫描条形码了。方法可以简单地实现这一点StartScanning ()方法。scannerControl.接下来会发生什么是基于类型ScannerDevice以及它是如何配置的。一般来说:
当满足下列条件之一时,扫描停止:
当条形码被成功解码时,您将在ReadResultReceived中收到ScannedResult列表事件:
//在扫描完成后调用,通过检测条形码,通过使用屏幕按钮或硬件触发按钮取消扫描,或者如果扫描超时公共void OnReadResultReceived(对象发送者,List结果)
要简单地显示ScannedResult扫描条形码后:
public void OnReadResultReceived(对象发送者,列表结果){if(结果?。计数> 0){lblResultText。Text = results[0].ResultCode;lblResultType。Text = results[0]. resultsymology;}}
可能会出现由于电池电量不足或手动断开电缆而导致设备断开的情况。这些情况可以在ConnectionStateChanged事件处理程序。
从非活动状态返回应用程序后,阅读器设备保持初始化,但没有连接。不需要重新初始化SDK,但需要重新连接。
//---------------------------------------------------------------------------- // 当一个页面消失,到扫描装置的连接需要/ /关闭;因此,当我们恢复(再次出现此页)时,我们//必须恢复连接(假设我们有一个)。//---------------------------------------------------------------------------- 如果(scannerControl。IsScannerControlReady && await permission . checkstatusasync () == permissionstatus . granting) {ConnectToScannerDevice();}