在我的previous article中,我演示了如何将C ++库包装到Nuget软件包中。本周,我将将包装扩展到包括Android和iOS绑定库,从而在 Windows , Linux , macos 中启用多平台开发, android 和 ios 。一个多合一的Nuget软件包的优点是,您可以使用Unified .NET API为台式机和移动平台创建条形码和QR代码扫描应用程序,从而消除了对平台特定代码的需求。
。下载barcodeqrcodesdk
https://www.nuget.org/packages/BarcodeQRCodeSDK
多合一的Nuget软件包是什么样的?
-
BarcodeQRCodeSDK.targets
文件包含视觉C ++项目的构建指令。 -
net6.0
文件夹包含Windows,Linux和MacOS的.NET绑定库。runtimes
文件夹包含C ++库(*.dll
,*.so
和*.dylib
),由.NET绑定库调用。 -
net6.0-android31.0
文件夹包含.NET绑定库和Android的*.aar
文件。 -
net6.0-ios16.1
文件夹包含.net绑定库和iOS的.xcframework
软件包。
如何为Android和iOS绑定库创建统一的.NET API
要将新的Android和iOS绑定库项目添加到Visual Studio中的BarcodeQRCodeSDK
解决方案中,只需单击解决方案上的右键,然后选择“ add”。有关构建Android和iOS库的详细步骤,请参考https://www.dynamsoft.com/codepool/dotnet-android-ios-nuget-package.html。
Bar Codeqrcodesdk解决方案现在包括三个子项目。您需要在Windows上构建iOS绑定库之前运行Pair to Mac
。在尝试在MACOS上构建解决方案的同时,将项目导入Mac的Visual Studio时会遇到以下错误。解决方法是在MacOS上独立构建iOS绑定项目。
由于我们的目标是创建一个多合一的Nuget软件包,因此最好确保Android和iOS绑定库的输出名称与.NET绑定库一致。为此,我们可以将AssemblyName
属性添加到Android和iOS绑定库的*.csproj
文件中。
<AssemblyName>BarcodeQRCodeSDK</AssemblyName>
此时,两个绑定库都可以使用。但是,API尚未统一。为了实现这一目标,您需要在Android和iOS绑定库项目中创建一个BarcodeQRCodeReader.cs
文件以实现其他功能。参考.NET绑定库项目中现有的BarcodeQRCodeReader.cs
文件,您可以为Android和iOS绑定库编写以下代码。
-
导入因名称空间。
android
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using Android.Hardware.Lights; using Com.Dynamsoft.Dbr; using Java.Nio; using Java.Nio.FileNio.Attributes;
ios
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using com.Dynamsoft.Dbr; using System.Runtime.InteropServices; using Foundation;
-
创建一个
BarcodeQRCodeReader
类,一个Result
类和ImagePixelFormat
枚举:android
namespace Dynamsoft { public class BarcodeQRCodeReader { private BarcodeReader? reader; public class Result { public string? Text { get; set; } public int[]? Points { get; set; } public string? Format1 { get; set; } public string? Format2 { get; set; } } public enum ImagePixelFormat { IPF_BINARY, IPF_BINARYINVERTED, IPF_GRAYSCALED, IPF_NV21, IPF_RGB_565, IPF_RGB_555, IPF_RGB_888, IPF_ARGB_8888, IPF_RGB_161616, IPF_ARGB_16161616, IPF_ABGR_8888, IPF_ABGR_16161616, IPF_BGR_888 } } }
ios
namespace Dynamsoft { public class BarcodeQRCodeReader { private DynamsoftBarcodeReader? reader; public class Result { public string? Text { get; set; } public int[]? Points { get; set; } public string? Format1 { get; set; } public string? Format2 { get; set; } } public enum ImagePixelFormat { IPF_BINARY, IPF_BINARYINVERTED, IPF_GRAYSCALED, IPF_NV21, IPF_RGB_565, IPF_RGB_555, IPF_RGB_888, IPF_ARGB_8888, IPF_RGB_161616, IPF_ARGB_16161616, IPF_ABGR_8888, IPF_ABGR_16161616, IPF_BGR_888 } } }
-
实施
InitLicense()
,Create()
,GetVersionInfo()
,DecodeFile()
,DecodeBuffer()
,DecodeBase64()
和SetParameters
方法:android
public class DBRLicenseVerificationListener : Java.Lang.Object, IDBRLicenseVerificationListener { public void DBRLicenseVerificationCallback(bool isSuccess, Java.Lang.Exception error) { if (!isSuccess) { System.Console.WriteLine(error.Message); } } } public static void InitLicense(string license) { BarcodeReader.InitLicense(license, new DBRLicenseVerificationListener()); } private BarcodeQRCodeReader() { reader = new BarcodeReader(); } public static BarcodeQRCodeReader Create() { return new BarcodeQRCodeReader(); } ~BarcodeQRCodeReader() { Destroy(); } public void Destroy() { reader = null; } public static string? GetVersionInfo() { return BarcodeReader.Version; } private Result[]? OutputResults(TextResult[]? results) { Result[]? output = null; if (results != null && results.Length > 0) { output = new Result[results.Length]; for (int i = 0; i < results.Length; ++i) { TextResult tmp = results[i]; Result r = new Result(); output[i] = r; r.Text = tmp.BarcodeText; r.Format1 = tmp.BarcodeFormatString; r.Format2 = tmp.BarcodeFormatString; if (tmp.LocalizationResult != null && tmp.LocalizationResult.ResultPoints != null) { IList<Point> points = tmp.LocalizationResult.ResultPoints; r.Points = new int[8] { points[0].X, points[0].Y, points[1].X, points[1].Y, points[2].X, points[2].Y, points[3].X, points[3].Y }; } else r.Points = null; } } return output; } public Result[]? DecodeFile(string filename) { if (reader == null) { return null; } TextResult[]? results = reader.DecodeFile(filename); return OutputResults(results); } public Result[]? DecodeBuffer(byte[] buffer, int width, int height, int stride, ImagePixelFormat format) { if (reader == null) { return null; } TextResult[]? results = reader.DecodeBuffer(buffer, width, height, stride, (int)format); return OutputResults(results); } public Result[]? DecodeBase64(string base64string) { if (reader == null) { return null; } TextResult[]? results = reader.DecodeBase64String(base64string); return OutputResults(results); } public void SetParameters(string parameters) { if (reader == null) { return; } reader.InitRuntimeSettingsWithString(parameters, EnumConflictMode.CmOverwrite); }
ios
public class Listener : DBRLicenseVerificationListener { public void DBRLicenseVerificationCallback(bool isSuccess, NSError error) { if (error != null) { System.Console.WriteLine(error.UserInfo); } } } public static void InitLicense(string license) { DynamsoftBarcodeReader.InitLicense(license, new Listener()); } private BarcodeQRCodeReader() { reader = new DynamsoftBarcodeReader(); } public static BarcodeQRCodeReader Create() { return new BarcodeQRCodeReader(); } ~BarcodeQRCodeReader() { Destroy(); } public void Destroy() { reader = null; } public static string? GetVersionInfo() { return DynamsoftBarcodeReader.Version; } private Result[]? OutputResults(iTextResult[]? results) { Result[]? output = null; if (results != null && results.Length > 0) { output = new Result[results.Length]; for (int i = 0; i < results.Length; ++i) { iTextResult tmp = results[i]; Result r = new Result(); output[i] = r; r.Text = tmp.BarcodeText; r.Format1 = tmp.BarcodeFormatString; r.Format2 = tmp.BarcodeFormatString; if (tmp.LocalizationResult != null && tmp.LocalizationResult.ResultPoints != null) { NSObject[] points = tmp.LocalizationResult.ResultPoints; r.Points = new int[8] { (int)((NSValue)points[0]).CGPointValue.X, (int)((NSValue)points[0]).CGPointValue.Y, (int)((NSValue)points[1]).CGPointValue.X, (int)((NSValue)points[1]).CGPointValue.Y, (int)((NSValue)points[2]).CGPointValue.X, (int)((NSValue)points[2]).CGPointValue.Y, (int)((NSValue)points[3]).CGPointValue.X, (int)((NSValue)points[3]).CGPointValue.Y }; } else r.Points = null; } } return output; } public Result[]? DecodeFile(string filename) { if (reader == null) { return null; } NSError error; iTextResult[]? results = reader.DecodeFileWithName(filename, out error); return OutputResults(results); } public Result[]? DecodeBuffer(byte[] myBytes, int width, int height, int stride, ImagePixelFormat format) { if (reader == null) { return null; } NSError error; IntPtr buffer = Marshal.AllocHGlobal(myBytes.Length); Marshal.Copy(myBytes, 0, buffer, myBytes.Length); NSData data = NSData.FromBytes(buffer, (nuint)myBytes.Length); iTextResult[]? results = reader.DecodeBuffer(data, width, height, stride, (EnumImagePixelFormat)format, out error); Marshal.FreeHGlobal(buffer); return OutputResults(results); } public Result[]? DecodeBase64(string base64string) { if (reader == null) { return null; } NSError error; iTextResult[]? results = reader.DecodeBase64(base64string, out error); return OutputResults(results); } public void SetParameters(string parameters) { if (reader == null) { return; } NSError error; reader.InitRuntimeSettingsWithString(parameters, EnumConflictMode.Overwrite, out error); }
构建Android绑定库不会提出任何问题。但是,当尝试使用MacOS上的Visual Studio构建iOS绑定库时,可能会出现红色小脚架。
不要惊慌。您可以安全地忽略这些红色的尖叫声并成功地构建项目。
如何配置 *.nuspec文件以包含Android和iOS绑定库
如果您已经成功构建了Android和iOS绑定库,则下一步是配置*.nuspec
文件以将它们包含在Nuget软件包中。
<!-- Android -->
<file src="android\bin\Release\net6.0-android\**\*.*" target="lib\net6.0-android31.0" />
<!-- iOS -->
<file src="ios/manifest" target="lib/net6.0-ios16.1/BarcodeQRCodeSDK.resources" />
<file src="ios\bin\Release\net6.0-ios\BarcodeQRCodeSDK.dll" target="lib\net6.0-ios16.1" />
<file src="ios\bin\Release\net6.0-ios\BarcodeQRCodeSDK.resources\**\*.*" target="lib\net6.0-ios16.1\BarcodeQRCodeSDK.resources" />
<file src="ios/bin/Release/net6.0-ios/BarcodeQRCodeSDK.resources/DynamsoftBarcodeReader.xcframework/ios-arm64/DynamsoftBarcodeReader.framework/DynamsoftBarcodeReader" target="lib/net6.0-ios16.1/BarcodeQRCodeSDK.resources/DynamsoftBarcodeReader.xcframework/ios-arm64/DynamsoftBarcodeReader.framework" />
<file src="ios/bin/Release/net6.0-ios/BarcodeQRCodeSDK.resources/DynamsoftBarcodeReader.xcframework/ios-arm64_x86_64-simulator/DynamsoftBarcodeReader.framework/DynamsoftBarcodeReader" target="lib/net6.0-ios16.1/BarcodeQRCodeSDK.resources/DynamsoftBarcodeReader.xcframework/ios-arm64_x86_64-simulator/DynamsoftBarcodeReader.framework" />
请注意,虽然Wildcard **\*.*
包括指定文件夹中的所有文件和子文件夹,但它将无法说明DynamsoftBarcodeReader
汇编文件。因此,您必须手动添加此文件。
如何使用多合一的Nuget软件包更新MAUI条形码QR代码扫描仪
要尝试使用多合一的Nuget软件包,您可以下载https://github.com/yushulx/maui-barcode-qrcode-scanner项目。该项目是使用DynamSoft条形码读取器的Android和iOS绑定库开发的。
这是使用多合一的Nuget软件包更新项目的步骤:
-
用
BarcodeQRCodeSDK
替换Barcode.NET.Mobile
。 -
修改特定于平台的代码如下:
- using BarcodeQrScanner.Services; + using Dynamsoft; - BarcodeQRCodeService _barcodeQRCodeService; + BarcodeQRCodeReader _reader; - data = _barcodeQRCodeService.DecodeFile(path); + BarcodeQRCodeReader.Result[] results = _reader.DecodeFile(imagepath); - TextResult[] results = barcodeReader.DecodeBuffer(image.GetYuvData(), previewWidth, previewHeight, stridelist[0], EnumImagePixelFormat.IpfNv21); + BarcodeQRCodeReader.Result[] results = barcodeReader.DecodeBuffer(image.GetYuvData(), previewWidth, previewHeight, stridelist[0], BarcodeQRCodeReader.ImagePixelFormat.IPF_NV21); - results = reader.DecodeBuffer(buffer, width, height, bpr, EnumImagePixelFormat.Argb8888, out errorr); + byte[] bytearray = new byte[buffer.Length]; + System.Runtime.InteropServices.Marshal.Copy(buffer.Bytes, bytearray, 0, Convert.ToInt32(buffer.Length)); + results = reader.DecodeBuffer(bytearray, (int)width, (int)height, (int)bpr, BarcodeQRCodeReader.ImagePixelFormat.IPF_ARGB_8888);
-
在Android和iOS上运行MAUI条形码QR代码扫描仪。
修改后的MAUI条形码QR代码扫描仪项目可在https://github.com/yushulx/dotnet-barcode-qr-code-sdk/tree/main/example/maui上找到。