I am in the process of converting a Xamarin.Android project to .NET MAUI. The project is a lightweight wrapper around a WebView, with the UI primarily being handled by a separate project written in HTML, JavaScript, and CSS. The app interacts with native Android features such as Bluetooth, camera, etc. The only two views in the project are InitializationActivity (where the user enters the URL of the website) and MainActivity (which displays the website in a WebView).
After converting the project to target .net8.0-android, the app works fine except for one feature: QR/Barcode scanning. In the Xamarin.Android project, I used the ZXing.Net.Mobile library, where I had a custom layout, and called MobileBarcodeScanner.Scan() in my .cs file to open the camera for scanning. However, ZXing.Net.Mobile is incompatible with .NET MAUI, so I am trying to upgrade to ZXing.Net.MAUI.
In ZXing.Net.MAUI, it seems I need to have a MAUI content page for the scan and navigate to that page from my MainActivity. I managed to navigate to the scanner page, but the camera is not showing up. I am also unsure how to send the scan result back to my MainActivity and then to my WebView, as it is all a JavaScript call.
Here is the relevant code:
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" />