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

如何在半迁移的Xamarin.Android转.NET MAUI项目中集成ZXing.Net.MAUI实现扫码

Xamarin.Android迁移.NET MAUI后扫码功能问题

项目背景

原项目是Xamarin.Android实现的WebView轻量包装,核心UI由HTML、JavaScript和CSS编写,需调用蓝牙、相机等Android原生功能,仅包含两个页面:

  • InitializationActivity:用于用户输入网站URL
  • MainActivity:加载WebView展示目标网页

迁移至.NET 8.0-Android后,应用整体运行正常,但扫码功能失效。原项目依赖的ZXing.Net.Mobile库与.NET MAUI不兼容,因此切换为ZXing.Net.MAUI库适配。

当前问题

已实现从MainActivity导航到MAUI扫码页面,但存在两个核心问题:

  1. 扫码页面无法显示相机画面
  2. 无法将扫码结果回传给MainActivity,进而传递给WebView中的JavaScript

相关代码

ZXingScannerActivity.cs

[Activity(Label = "ZXingScanActivity")]
public class ZXingScanActivity : Activity
{
    public static string m_Tag = "ZXingScanActivity";
    public static readonly Lazy<MauiApp> MauiApp = new(() =>
    {
        var mauiApp = MauiProgram.CreateMauiApp(builder =>
        {
            builder
                .UseMauiEmbedding()
                .UseBarcodeReader();
        });
        return mauiApp;
    });
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        var mauiApp = MauiApp.Value;
        var mauiContext = new MauiContext(mauiApp.Services, this);
        var mauiView = new ZXingScannerPage();
        var scannerView = mauiView.ToPlatformEmbedded(mauiContext);
        SetContentView(scannerView);
    }
}

MainActivity.cs

public async Task<string> OpenZXingScanner()
{
    RunOnUiThread(() =>
    {
        var intent = new Intent(this, typeof(ZXingScanActivity));
        StartActivity(intent);
    });
    return string.Empty;
}

ZXingScannerPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:zxing="clr-namespace:ZXing.Net.Maui.Controls;assembly=ZXing.Net.MAUI.Controls"
             x:Class="TWP.Pages.ZXingScannerPage">

    <zxing:CameraBarcodeReaderView x:Name="barcodeReader" BarcodesDetected="BarcodesDetected" />
</ContentPage>

ZXingScannerPage.xaml.cs

namespace TWP.Pages
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class ZXingScannerPage : ContentPage
    {
        public ZXingScannerPage()
        {
            InitializeComponent();
            barcodeReader.Options = new BarcodeReaderOptions
            {
                Formats = BarcodeFormats.All,
                AutoRotate = true,
                Multiple = false
            };
            barcodeReader.CameraLocation = CameraLocation.Front;
        }

        public void BarcodesDetected(object sender, BarcodeDetectionEventArgs e)
        {
            var first = e.Results?.FirstOrDefault();
            if (first is null)
                return;

            Dispatcher.DispatchAsync(async () =>
            {
                await DisplayAlert("Barcode Detected", first.Value, "OK");
                await Navigation.PopAsync();
            });
        }
    }
}

AndroidManifest.xml

<uses-permission android:name="android.permission.CAMERA" />

解决方案

1. 修复相机无法显示的问题

补充动态权限申请

Android 6.0+需动态申请相机权限,在MainActivity的扫码启动方法中添加权限检查:

public async Task<string> OpenZXingScanner()
{
    // 检查并请求相机权限
    if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.Camera) != Permission.Granted)
    {
        ActivityCompat.RequestPermissions(this, new[] { Manifest.Permission.Camera }, 100);
        return string.Empty;
    }

    RunOnUiThread(() =>
    {
        var intent = new Intent(this, typeof(ZXingScanActivity));
        StartActivityForResult(intent, 101); // 改用StartActivityForResult接收返回值
    });
    return string.Empty;
}

调整MAUI嵌入初始化逻辑

简化ZXingScannerActivity中的MAUI初始化代码,避免懒加载可能导致的上下文问题:

protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);
    var mauiApp = MauiProgram.CreateMauiApp();
    var mauiContext = new MauiContext(mauiApp.Services, this);
    var scannerPage = new ZXingScannerPage();
    var nativeView = scannerPage.ToPlatform(mauiContext);
    SetContentView(nativeView);
}

启用扫码控件的扫描状态

在ZXingScannerPage构造函数中启用扫描,并切换为后置摄像头(通常扫码场景使用):

public ZXingScannerPage()
{
    InitializeComponent();
    barcodeReader.Options = new BarcodeReaderOptions
    {
        Formats = BarcodeFormats.All,
        AutoRotate = true,
        Multiple = false
    };
    barcodeReader.CameraLocation = CameraLocation.Back;
    barcodeReader.IsScanning = true; // 启用扫描
}

2. 实现扫码结果回传并传递给WebView

在MainActivity接收返回结果

重写OnActivityResult方法,接收扫码页返回的结果并传递给WebView:

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
    base.OnActivityResult(requestCode, resultCode, data);
    if (requestCode == 101 && resultCode == Result.Ok)
    {
        var scanResult = data.GetStringExtra("ScanResult");
        // 调用WebView中的JavaScript方法传递结果
        webView.EvaluateJavascript($"window.onScanResult('{scanResult}')", null);
    }
}

在扫码页返回结果

修改ZXingScannerPage的BarcodesDetected方法,停止扫描并将结果返回给MainActivity:

public void BarcodesDetected(object sender, BarcodeDetectionEventArgs e)
{
    var first = e.Results?.FirstOrDefault();
    if (first is null)
        return;

    barcodeReader.IsScanning = false; // 停止扫描

    // 获取当前Activity并返回结果
    var currentActivity = Platform.CurrentActivity;
    var resultIntent = new Intent();
    resultIntent.PutExtra("ScanResult", first.Value);
    currentActivity.SetResult(Result.Ok, resultIntent);
    currentActivity.Finish();
}

内容的提问来源于stack exchange,提问作者Nantha Kishor Anandhan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 04:24:58