如何在半迁移的Xamarin.Android转.NET MAUI项目中集成ZXing.Net.MAUI实现扫码
Xamarin.Android迁移.NET MAUI后扫码功能问题
项目背景
原项目是Xamarin.Android实现的WebView轻量包装,核心UI由HTML、JavaScript和CSS编写,需调用蓝牙、相机等Android原生功能,仅包含两个页面:
InitializationActivity:用于用户输入网站URLMainActivity:加载WebView展示目标网页
迁移至.NET 8.0-Android后,应用整体运行正常,但扫码功能失效。原项目依赖的ZXing.Net.Mobile库与.NET MAUI不兼容,因此切换为ZXing.Net.MAUI库适配。
当前问题
已实现从MainActivity导航到MAUI扫码页面,但存在两个核心问题:
- 扫码页面无法显示相机画面
- 无法将扫码结果回传给
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
相关产品推荐
相关产品推荐

