How to Build Camera Barcode and QR Code Scanner App in Xamarin.Forms
Xamarin is a cross-platform framework for building Android and iOS apps using .NET programming. The code structure of Xamarin Android and Xamarin iOS is different. For developers who want to construct UI for Android and iOS from a single codebase, Xamarin.Forms is the only solution. This article shares how to implement mobile barcode and QR code scanner apps for both Android and iOS platforms using Xamarin.Forms and Dynamsoft Barcode Reader SDK. Since camera logic is platform-dependent, a bunch of platform-specific code is required.
License Activation
Get the 30-day FREE Trial license.
Android
Set the license key with an Activity
object that implements the IDBRLicenseVerificationListener
interface:
public class MainActivity : AppCompatActivity, IDBRLicenseVerificationListener
{
DynamsoftBarcodeReader reader;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
...
BarcodeReader.InitLicense("DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ==", this);
reader = new BarcodeReader();
...
}
public void DBRLicenseVerificationCallback(bool isSuccess, Java.Lang.Exception error)
{
if (!isSuccess)
{
System.Console.WriteLine(error.Message);
}
}
}
iOS
DynamsoftBarcodeReader reader = new DynamsoftBarcodeReader("DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ==");
Getting Started with Xamarin.Forms
Setting Up Environment on Windows 10
-
Run Visual Studio Installer and select Mobile development with .NET
-
In Visual Studio 2019, click Tools > Options > Xamarin > iOS Settings > Pair to Mac. Add a Mac IP for remotely building and debugging iOS project.
-
Click the Android icon to install Android SDKs and tools:
The Hello World Program
We create a new project with the mobile app template:
To simplify the project, we select Blank.
Build and test the project for iOS:
If there is nothing wrong, we can take a further step to add code for camera preview.
Peeking Xamarin Camera-relevant APIs
To avoid re-inventing the wheel, we’d better search for Xamarin camera APIs beforehand. Unfortunately, there is only Media Picker available in Xamarin.Essentials. The MediaPicker class lets a user pick or take a photo or video on the device. But what we want is a custom camera view that allows us to do barcode scanning by processing video frames.
Although there is no Xamarin Camera API existed, Xamarin Github repository contains two useful sample code demonstrating how to implement custom content page and view:
- https://github.com/xamarin/xamarin-forms-samples/tree/master/CustomRenderers/ContentPage
- https://github.com/xamarin/xamarin-forms-samples/tree/master/CustomRenderers/View
It is not as convenient as React Native and Flutter camera plugin, though, it is better than nothing.
The two samples implement camera logic differently. The content page sample uses the deprecated Android Camera APIs, whereas the view sample uses the Android Camera2 APIs. The compatibility of Android Camera2 APIs is so far not good for many devices. If you are not going to dig too many camera functionalities, Android Camera APIs are still the best choice.
Implementing Barcode and QR Code Scanning Using Xamarin.Forms
Now, let’s implement our own barcode and QR code scanner app.
First, we install Dynamsoft Xamarin Barcode Reader SDK respectively for Android and iOS projects via NuGet.
Xamarin Shared Code Project
In the shared code project, we define some camera control interfaces in Interfaces/ICaptureUI.cs
:
public interface ICaptureUI: IDisposable
{
/// <summary>
/// Starts the Capture Session.
/// </summary>
void StartSession();
/// <summary>
/// Stops the Capture Session.
/// </summary>
void StopSession();
/// <summary>
/// Determines if the Capture Session is active.
/// </summary>
bool GetSessionActive();
/// <summary>
/// res.
/// </summary>
string GetResults();
/// <summary>
/// Turn on or off the flash.
/// </summary>
void onClickFlash();
}
We create Controls/CaptureUI.cs
which extends ContentView
and is bound to platform-specific camera view:
public class CaptureUI : ContentView
{
}
A capture view model ViewModels/CaptureViewModel.cs
is implemented for receiving the barcode scanning results:
class CaptureViewModel : ViewModelBase
{
public CaptureViewModel()
{
}
/// <summary>
/// Begins a Capture Sequence, preparing the UI and the Timer.
/// </summary>
public void StartCaptureSequence()
{
CaptureHandler = App.CurrentCaptureUI;
Timer t = new Timer(500);
t.Elapsed += new ElapsedEventHandler(Timer_Tick);
t.AutoReset = true;
t.Enabled = true;
}
public void Timer_Tick(object source, ElapsedEventArgs e)
{
Instruction = CaptureHandler.GetResults();
}
/// <summary>
/// The current Instruction to the User.
/// </summary>
public string Instruction
{
get { return _Instruction; }
set
{
_Instruction = value;
UpdateProperty();
}
}
/// <summary>
/// Backing Field for <see cref="Instruction"/>.
/// </summary>
private string _Instruction;
private ICaptureUI CaptureHandler { get; set; }
}
Finally, we open MainPage.xaml
file to design the UI, adding the custom view and binding the barcode scanning results to a label:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:DBRXFSample.Controls"
x:Class="DBRXFSample.MainPage">
<Grid
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<controls:CaptureUI x:Name="Capture"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" />
<Image Source="scannerbox" HorizontalOptions="Center" VerticalOptions="Center"/>
<Label Text="DBR Is Scanning Continuously" TextColor="#FF4646" FontSize="18" HorizontalOptions="Center" Margin="0,100,0,0" />
<StackLayout
HorizontalOptions="Center"
VerticalOptions="Center"
Margin="0,480,0,0">
<Button x:Name="flash" ImageSource="flashon" HorizontalOptions="Center" WidthRequest="50" HeightRequest="50" Clicked="flash_Clicked" />
<Label x:Name="label" Text="{Binding Instruction}" TextColor="#000000" BackgroundColor="#7F999999"/>
</StackLayout>
</Grid>
</ContentPage>
Xamarin Android and iOS Project
The diagram shows the relationship between Xamarin.Forms view and platform-specific view.
According to Microsoft’s online tutorial, we can quickly implement the corresponding camera views.
Afterward, we can use the following code to decode barcode and QR code from video frames:
Android
try
{
YuvImage image = (YuvImage)msg.Obj;
if (image != null)
{
int[] stridelist = image.GetStrides();
TextResult[] text = barcodeReader.DecodeBuffer(image.GetYuvData(), previewWidth, previewHeight, stridelist[0], EnumImagePixelFormat.IpfNv21, "");
if (text != null && text.Length > 0)
{
for (int i = 0; i < text.Length; i++)
{
if (i == 0)
msg1.Obj = "Code[1]: " + text[0].BarcodeText;
else
msg1.Obj = msg1.Obj + "\n\n" + "Code[" + (i + 1) + "]: " + text[i].BarcodeText;
}
}
}
}
catch (BarcodeReaderException e)
{
msg1.Obj = "";
e.PrintStackTrace();
}
iOS
results = reader.DecodeBuffer(buffer, width, height, bpr, EnumImagePixelFormat.Argb8888, "", out errorr);
if (results != null && results.Length > 0)
{
for (int i = 0; i < results.Length; i++)
{
if (i == 0)
result = "Code[1]: " + results[0].BarcodeText;
else
result = result + "\n\n" + "Code[" + (i + 1) + "]: " + results[i].BarcodeText;
}
}
Source Code
https://github.com/Dynamsoft/xamarin-barcode-qrcode/tree/master/examples/XamarinForms