How to Build Camera Barcode 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 camera barcode scanner apps for both Android and iOS platforms using Xamarin.Forms. Since camera logic is platform-dependent, a bunch of platform-specific code is required.

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:

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 Scanning using Xamarin.Forms

Now, let’s implement our own barcode scanner app.

First, we install Dynamsoft Xamarin Barcode Reader SDK respectively for Android and iOS projects via NuGet.

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 barcodes from video frames:

// Android
private static BarcodeReader barcodeReader = new BarcodeReader("LICENSE-KEY");

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
DynamsoftBarcodeReader reader = new DynamsoftBarcodeReader("LICENSE-KEY");

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;
}
}

Get the 30-day FREE Trial license.

Source Code

https://github.com/Dynamsoft/xamarin/tree/master/examples/XamarinForms

Originally published at https://www.dynamsoft.com on April 7, 2021.

Manager of Dynamsoft Open Source Projects | Tech Lover

Manager of Dynamsoft Open Source Projects | Tech Lover