You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Xamarin.Forms中基于ZXing实现跨平台读取本地条码二维码图片

跨平台实现本地图片二维码读取方案

前置依赖安装

首先确保你已经在项目中安装了对应的NuGet包:

  • 共享项目:安装 ZXing.Net
  • Android 平台项目:安装 ZXing.Net.Bindings.XamarinAndroid
  • iOS 平台项目:安装 ZXing.Net.Bindings.XamarinIOS
  • UWP 平台项目:安装 ZXing.Net.Bindings.Windows.Universal

实现跨平台服务

因为不同平台的图片处理API不同,我们用Xamarin.Forms自带的DependencyService来封装各平台的解码逻辑。

1. 共享项目定义公共接口

在共享项目中新增接口:

public interface IBarcodeDecoderService
{
    Task<ZXing.Result> DecodeImageAsync(string filePath, ZXing.BarcodeFormat? targetFormat = null, KeyValuePair<ZXing.DecodeHintType, object>[] extraHints = null);
}

注意:代码中的命名空间请替换为你项目实际使用的命名空间。

2. 各平台实现接口

Android 端实现

在Android项目中新增服务类,记得添加依赖注册特性:

[assembly: Dependency(typeof(YourNamespace.Droid.BarcodeDecoderService))]
namespace YourNamespace.Droid
{
    public class BarcodeDecoderService : IBarcodeDecoderService
    {
        public async Task<ZXing.Result> DecodeImageAsync(string filePath, ZXing.BarcodeFormat? targetFormat = null, KeyValuePair<ZXing.DecodeHintType, object>[] extraHints = null)
        {
            // 加载本地图片为Bitmap
            var bitmap = await BitmapFactory.DecodeFileAsync(filePath);
            // 转成ZXing可用的LuminanceSource
            var source = new ZXing.Mobile.RGBLuminanceSource(bitmap, bitmap.Width, bitmap.Height);
            var binaryBitmap = new ZXing.BinaryBitmap(new ZXing.Common.HybridBinarizer(source));
            
            // 初始化解码器
            var reader = new ZXing.MultiFormatReader();
            var hints = new Dictionary<ZXing.DecodeHintType, object>();
            if (targetFormat.HasValue)
            {
                hints.Add(ZXing.DecodeHintType.POSSIBLE_FORMATS, new List<ZXing.BarcodeFormat> { targetFormat.Value });
            }
            // 添加高优先级识别提示,提高识别成功率
            hints.Add(ZXing.DecodeHintType.TRY_HARDER, true);
            if (extraHints != null)
            {
                foreach (var hint in extraHints)
                {
                    hints[hint.Key] = hint.Value;
                }
            }
            reader.Hints = hints;
            return reader.decode(binaryBitmap);
        }
    }
}

iOS 端实现

在iOS项目中新增服务类:

[assembly: Dependency(typeof(YourNamespace.iOS.BarcodeDecoderService))]
namespace YourNamespace.iOS
{
    public class BarcodeDecoderService : IBarcodeDecoderService
    {
        public async Task<ZXing.Result> DecodeImageAsync(string filePath, ZXing.BarcodeFormat? targetFormat = null, KeyValuePair<ZXing.DecodeHintType, object>[] extraHints = null)
        {
            var uiImage = UIImage.FromFile(filePath);
            var source = new ZXing.Mobile.RGBLuminanceSource(uiImage.CGImage);
            var binaryBitmap = new ZXing.BinaryBitmap(new ZXing.Common.HybridBinarizer(source));
            
            // 解码器初始化逻辑和Android端一致
            var reader = new ZXing.MultiFormatReader();
            var hints = new Dictionary<ZXing.DecodeHintType, object>();
            if (targetFormat.HasValue)
            {
                hints.Add(ZXing.DecodeHintType.POSSIBLE_FORMATS, new List<ZXing.BarcodeFormat> { targetFormat.Value });
            }
            hints.Add(ZXing.DecodeHintType.TRY_HARDER, true);
            if (extraHints != null)
            {
                foreach (var hint in extraHints)
                {
                    hints[hint.Key] = hint.Value;
                }
            }
            reader.Hints = hints;
            return reader.decode(binaryBitmap);
        }
    }
}

UWP 端实现

在UWP项目中新增服务类:

[assembly: Dependency(typeof(YourNamespace.UWP.BarcodeDecoderService))]
namespace YourNamespace.UWP
{
    public class BarcodeDecoderService : IBarcodeDecoderService
    {
        public async Task<ZXing.Result> DecodeImageAsync(string filePath, ZXing.BarcodeFormat? targetFormat = null, KeyValuePair<ZXing.DecodeHintType, object>[] extraHints = null)
        {
            var file = await StorageFile.GetFileFromPathAsync(filePath);
            using (var stream = await file.OpenAsync(FileAccessMode.Read))
            {
                var bitmap = new WriteableBitmap(1, 1);
                await bitmap.SetSourceAsync(stream);
                var source = new ZXing.PresentationCore.WriteableBitmapLuminanceSource(bitmap);
                var binaryBitmap = new ZXing.BinaryBitmap(new ZXing.Common.HybridBinarizer(source));
                
                // 解码器初始化逻辑和Android端一致
                var reader = new ZXing.MultiFormatReader();
                var hints = new Dictionary<ZXing.DecodeHintType, object>();
                if (targetFormat.HasValue)
                {
                    hints.Add(ZXing.DecodeHintType.POSSIBLE_FORMATS, new List<ZXing.BarcodeFormat> { targetFormat.Value });
                }
                hints.Add(ZXing.DecodeHintType.TRY_HARDER, true);
                if (extraHints != null)
                {
                    foreach (var hint in extraHints)
                    {
                        hints[hint.Key] = hint.Value;
                    }
                }
                reader.Hints = hints;
                return reader.decode(binaryBitmap);
            }
        }
    }
}

原有业务代码修改

你原来的调用代码可以直接替换为调用依赖服务的逻辑:

string file = "";
var filePickerOptions = new PickOptions
{
    PickerTitle = "Select Barcode Image",
    FileTypes = FilePickerFileType.Images
};
var result = await FilePicker.PickAsync(filePickerOptions);
if (result != null)
{
    file = result.FullPath;
    // 调用跨平台解码服务
    var decoder = DependencyService.Get<IBarcodeDecoderService>();
    var res = await decoder.DecodeImageAsync(file, BarcodeFormat.QR_CODE);
    if (res != null)
    {
        Console.WriteLine(res.Text);
    }
    else
    {
        Console.WriteLine("未识别到二维码内容");
    }
}

注意事项

  • Android端需要提前申请READ_EXTERNAL_STORAGE权限,Android 13及以上需要申请READ_MEDIA_IMAGES权限
  • iOS端需要在Info.plist中添加NSPhotoLibraryUsageDescription权限说明
  • UWP端需要在Package.appxmanifest中开启图片库访问权限
  • 针对清晰度低、角度倾斜的二维码,可以额外添加DecodeHintType.PURE_BARCODE等hint提高识别率

内容的提问来源于stack exchange,提问作者Kikanye

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 18:36:03