Developer Tutorial: Xamarin and Xamarin.Forms Barcode Scanning

| Developers

For enterprise applications, integrating barcode and QR code scanning into your Xamarin or Xamarin.Forms app means taking user experience (UX) and real-world performance into account. Going beyond basic scanning features and user interface (UI) elements helps users do their jobs, increases adoption rates, and ensures customer and business goals are met.

This blog explains the key UX and performance principles for successfully adding a Xamarin barcode scanner (including QR codes) to iOS and Android applications. It also includes a step-by-step tutorial for the Scandit Xamarin Barcode Scanner SDK using the SparkScan pre-built UI component.

Why UX matters for Xamarin barcode scanning

A recent Scandit study revealed that over 66% of store associates rate their devices as important or very important for their jobs. Over 50% stated that device intuitiveness is crucial for smartphones and scanning devices.

These figures illustrate the importance of getting navigation, interaction, and feedback right in your Xamarin barcode scanner implementation. Failing to do so may lead to frustration, failure, and complaints from your user base.

Key workflows for Xamarin barcode scanning

Understanding how to support the following workflows helps users do their jobs better:

  • Fast transitions into scanning mode: The last thing users want to worry about is navigating complex menus or waiting for your barcode scanner library to load and start.
  • Start and resume scanning by tapping anywhere on the live camera interface: Making it easy to start scanning improves ergonomics and reduces task times. If a button is preferred over the camera screen, ensure the touch area is large enough for comfortable repeated use.
  • Rapid, easy aiming: Implementing an appropriately sized viewfinder helps users target the right barcode, shows that scanning is live, and indicates how far away to hold the camera. Similarly, restricting the scan area or using an aimer viewfinder helps users select the right item when multiple labels are crowded together.

Supporting users with different scan modes

Allowing users to switch between scanning single and multiple barcodes helps them work more efficiently when the number or configuration of barcodes varies (such as in a shipping warehouse or retail store):

  • Single scan: Allows users to trigger scanning for each barcode individually, providing greater control over their scanning experience.
  • Continuous scan: Allows users to trigger the scanner once and scan multiple barcodes without further interaction. This accelerates workflows in situations where there’s little risk of unwanted or unintentional scans.

Helping users understand success and failure

Your Xamarin app should provide clear and immediate feedback on a barcode scan’s success or failure. Delayed responses lead to user confusion, and unclear results may lead to missing or incomplete data on the back end.

A combination of techniques can be used to help the user, such as:

  • Brush overlays to confirm scanning of the intended item by drawing an object at the coordinates of the target.
  • Playing sounds, vibrating the device, and haptic feedback provide additional cues for a successful capture.
PDF417 with DataMatrix with SparkScan

Get your Xamarin barcode scanner library

Fast, accurate, and reliable scanning performance.


Performance and other development considerations for your Xamarin barcode scanner API

There are open-source and free Xamarin barcode and QR code scanner libraries available, but they may not be the best choice for business-critical environments. Retail environments, warehouses, and last-mile delivery have demanding performance goals and less-than-ideal operating conditions. Low light, awkward scan angles, torn barcodes, and poor internet connectivity can all interfere with scanning performance.

You also want one library that scans a broad range of barcode and QR code types, to reduce complexity and avoid maintenance headaches.

Given the proliferation of open source and commercial options, always check that your chosen Xamarin library comes with developer documentation and has a track record of regular feature updates and bug fixes.

Here are some considerations for choosing your Xamarin barcode scanner library for effective real-world operation.

1. Performance

Consider the following requirements for your scanning library to ensure it works effectively. Make sure to test with different device models and OS versions to be sure your chosen library performs across your device fleet:

  • Accuracy: Inventory management, asset tracking, and similar operations require a Xamarin barcode scanner library with extremely high accuracy levels. A 95% success rate may not be enough for enterprise environments — you should aim for greater than 99% success to reduce user frustration and data quality issues.
  • Speed: A Xamarin barcode scanner library that helps users capture and process barcodes fast means less time wasted and faster business operations.
    Field-of-view and distance: Scanners must handle barcodes on items of various sizes, shapes, and distances from the camera.
  • Start-up time: To avoid frustrated users and slower workflows, your library should support a “standby mode” that minimizes camera start-up delays between scans.
  • Scanning barcodes in degraded conditions: A barcode may be torn, obscured, wrapped in plastic, or moving – your Xamarin library should work under all these scenarios.

The Scandit Xamarin Barcode Scanner SDK also alleviates a common concern among Xamarin developers: performance and resource overhead. The SDK is built on a C/C++ foundation. Core barcode scanning features are designed for efficient background loading and minimal resource consumption.

We list key performance tests at the bottom of the blog to gauge how well your library performs.

2. Low-light conditions

Lighting conditions in the real world vary widely from brightly lit to dark. Think of scanning use cases in retail stockrooms, loading docks, and nighttime deliveries. Your chosen Xamarin library should maintain speed and accuracy under these conditions.

3. Large device fleets with diverse models

Enterprises often have a diverse fleet of employee devices – especially in Bring-Your-Own-Device (BYOD) situations. Your Xamarin barcode scanner API should support efficient operations on different platforms. These could range from the latest multi-core smartphone to a legacy, resource-constrained device.

4. Support for different development frameworks

For developers working across platforms, check that your barcode scanner component supports it. Scandit barcode scanning is also available for Native iOS, Native Android, JavaScript, Flutter, .NET (iOS and Android), React Native, Cordova, Capacitor, and Titanium.

Person scanning a barcode with a smartphone using the Scandit Xamarin Barcode Scanner SDK

Get enterprise-ready features in less time with the Scandit Xamarin Barcode Scanner SDK

The Scandit Xamarin Barcode Scanner SDK integrates into any iOS or Android app to provide intuitive and fast scanning. Developers can also choose to use pre-built SparkScan UI components. Using only a few lines of code, SparkScan provides a floating interface that guides users through the scanning process without requiring app redesign or customization.

The SparkScan UI is built upon robust and researched UX principles. It is optimized for high performance through Scandit’s experiences of working with thousands of customers across various business environments.

Whether you’re using Xamarin.Forms or not, SparkScan also supports UI customization and ensures a consistent UX across all platforms. Additional UI elements are available for developers if their app logic requires displaying errors or additional feedback while scanning. We cover some examples of this below.

Get started with the Scandit Xamarin Barcode Scanner SDK

Follow these SparkScan instructions to add single barcode and QR code scanning to your Xamarin or Xamarin.Forms app.

The steps for adding the Scandit Xamarin Barcode Scanner SDK to your project are the same across Xamarin.iOS, Xamarin.Android and Xamarin.Forms. For easier reading, the remaining steps and code samples are separated into platform-specific sections below.

The prerequisites for all steps are:

  • The latest stable version of Microsoft Visual Studio.
  • A Xamarin.iOS project with a minimum iOS deployment target of 13.0 or higher; or a Xamarin.Android project with target SDK version 23 (Android 6, Marshmallow) or higher.
  • A valid Scandit Data Capture SDK license key. You can sign up for a free test account at ssl.scandit.com.

1. Add the SDK to your project

The Scandit Data Capture SDK is distributed as NuGet packages you obtain from the NuGet site.

You must add the Scandit.DataCapture.Core.Xamarin package, which contains the core functionality used by the other data capture packages, and the Scandit.DataCapture.Barcode.Xamarin (ScanditBarcodeCapture API) to use barcode capture.

You must also consider:

  • When using the Scandit Data Capture SDK, you must set the camera as the frame source for various capture modes. On Xamarin.iOS, you must set the “Privacy – Camera Usage Description” field in the Info.plist file. On Xamarin.Android, you must request camera permissions in your own application before starting scanning. To see how you can achieve this, take a look at our samples.
  • On Android, the Scandit Data Capture SDK uses content providers to initialize scanning capabilities properly. If your own content providers depend on the SDK, choose an initOrder lower than 10 to ensure the SDK is ready first. If not specified, initOrder is zero by default and you have nothing to worry about. For more details, check the official Android <provider> documentation.

From here, follow the steps for your development framework:

Close up damaged label with SparkScan boxes on shelves

Testing the Xamarin barcode scanner SDK is easy

Integrate with just a few lines of code or use our samples

Xamarin.iOS

Follow these steps to add barcode scanning and pre-built UI components using SparkScan to your Xamarin.iOS app. For additional help and examples of how to integrate barcode scanning:

1. Create a new data capture context instance

To add barcode capture capabilities to your Xamarin.iOS app, you must create a new data capture context. The context expects a valid Scandit Data Capture SDK license key during construction.

DataCaptureContext dataCaptureContext = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --");

2. Configure the SparkScan mode

The SparkScan mode is configured through SparkScanSettings, which allows you to register one or more listeners who are informed whenever a new barcode is scanned.

The following code sets up SparkScan for scanning EAN13 barcodes, but you can change this to the symbologies for your use case (e.g., Code 128, Code 39).

SparkScanSettings settings = new SparkScanSettings();
HashSet<Symbology> symbologies = new HashSet<Symbology>()
{
    Symbology.Ean13Upca
};
settings.EnableSymbologies(symbologies);

Next, create a SparkScan instance with the initialized settings::

SparkScan sparkScan = new SparkScan(settings);

3. Create a SparkScanView

SparkScan comes with a built-in user interface called SparkScanView. It includes:

  • Camera preview screen
  • Large-sized scan button
  • Quick-access toolbar to adjust scanning settings

The appearance of SparkScanView is customized through SparkScanViewSettings.

SparkScanViewSettings viewSettings = new SparkScanViewSettings();
// setup the desired appearance settings by updating the fields in the object above

Adding a SparkScanView automatically adds a scanning interface to your application.

To add SparkScanView to your view hierarchy, construct a new SparkScan view:

SparkScanView sparkScanView = SparkScanView.Create(parentView, dataCaptureContext, sparkScan, viewSettings);

The SparkScan view is automatically added to the provided parentView.

To ensure an optimal start-up time and that scanning is stopped when the app goes into the background, call SparkScanView.ViewWillAppear() and SparkScanView.ViewWillDisappear() in your UIViewController’s ViewWillAppear and ViewWillDisappear callbacks:

public override void ViewWillAppear(bool animated)
{
    base.ViewWillAppear(animated);
    sparkScanView.ViewWillAppear();
}

public override void ViewWillDisappear(bool animated)
{
    base.ViewWillDisappear(animated);
    sparkScanView.ViewWillDisappear();
}

4. Register the listener for new barcode scans and update your data

To keep track of scanned barcodes, implement the ISparkScanListener interface and register the listener to the SparkScan mode:

// Register self as a listener to monitor the spark scan session.
sparkScan.AddListener(this);

Whenever a new barcode is scanned, the application calls ISparkScanListener.OnBarcodeScanned(). You can retrieve the newly scanned code by calling SparkScanSession.NewlyRecognizedBarcodes. The returned list contains only one barcode entry.

public void OnBarcodeScanned(SparkScan sparkScan, SparkScanSession session, IFrameData? data)
{
    if (session.NewlyRecognizedBarcodes.Count == 0)
    {
        return;
    }

    // Gather the recognized barcode
    Barcode barcode = session.NewlyRecognizedBarcodes[0];

    // This method is invoked from a recognition internal thread.
    // Run the specified action in the UI thread to update the internal barcode list.
    DispatchQueue.MainQueue.DispatchAsync(() =>
    {
        // Update the internal list and the UI with the barcode retrieved above
        this.latestBarcode = barcode;
    });
}

You can also register the ISparkScanListener interface to subscribe to corresponding events:

sparkScan.BarcodeScanned += (object sender, SparkScanEventArgs args) =>
{
    if (args.Session.NewlyRecognizedBarcodes.Count == 0)
    {
        return;
    }

    // Gather the recognized barcode
    Barcode barcode = args.Session.NewlyRecognizedBarcodes[0];

    // This method is invoked from a recognition internal thread.
    // Run the specified action in the UI thread to update the internal barcode list.
    DispatchQueue.MainQueue.DispatchAsync(() =>
    {
        // Update the internal list and the UI with the barcode retrieved above
        this.latestBarcode = barcode;
    });
}

5. Customize the user interface

To illustrate how you can customize the SparkScan user interface, here are two elements you can control to change scanning behavior:

Control the scanner through a hardware button
Allowing users to control scanning with their device’s volume button can improve ergonomics when they wear gloves or have difficulty tapping a screen.

SparkScan offers a built-in API for this using SparkScanViewSettings.hardwareTriggerEnabled.

Hide controls from the settings toolbar
SparkScanView allows you to configure the toolbar to prevent users from accessing specific scanning controls. For example, to disable access to the sound mode button for users working in noisy environments, set soundModeButtonVisible to false.

Xamarin.Android

Follow these steps to add barcode scanning and pre-built UI components using SparkScan to your Xamarin.Android app. For additional help and examples of how to integrate barcode scanning:

1. Create a new data capture context instance

To add barcode capture capabilities to your Xamarin.iOS app, you must create a new data capture context. The context expects a valid Scandit Data Capture SDK license key during construction.

DataCaptureContext dataCaptureContext = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --");

2. Configure the SparkScan mode

The SparkScan mode is configured through SparkScanSettings, which allows you to register one or more listeners who are informed whenever a new barcode is scanned.

The following code sets up SparkScan for scanning EAN13 barcodes, but you can change this to the symbologies for your use case (e.g., Code 128, Code 39).

SparkScanSettings settings = new SparkScanSettings();
HashSet<Symbology> symbologies = new HashSet<Symbology>()
{
    Symbology.Ean13Upca
};
settings.EnableSymbologies(symbologies);

Next, create a SparkScan instance with the initialized settings:

SparkScan sparkScan = new SparkScan(settings);

3. Create a SparkScanView

SparkScan comes with a built-in user interface, called SparkScanView, that guides users through the scanning process and integrates with any app without requiring redesign or customization. It includes:

  • Camera preview screen
  • Large-sized scan button
  • Quick-access toolbar to adjust scanning settings

The appearance of SparkScanView is customized through SparkScanViewSettings.

SparkScanViewSettings viewSettings = new SparkScanViewSettings();
// setup the desired appearance settings by updating the fields in the object above

Adding a SparkScanView automatically adds a scanning interface to your application.

To add SparkScanView to your view hierarchy, construct a new SparkScan view:

SparkScanView sparkScanView = SparkScanView.Create(parentView, dataCaptureContext, sparkScan, viewSettings);

The SparkScan view is automatically added to the provided parentView (preferably an instance of SparkScanCoordinatorLayout).

To ensure the correct functioning of SparkScanView, call sparkScanView.onPause() and sparkScanView.onResume() in your Fragment/Activity onPause and onResume callbacks:

protected override void OnPause()
{
    sparkScanView.OnPause();
    base.OnPause();
}

protected override void OnResume()
{
    sparkScanView.OnResume();
    base.OnResume();
}

4. Register the listener for new barcode scans and update your data

To keep track of scanned barcodes, implement the ISparkScanListener interface and register the listener to the SparkScan mode:

// Register self as a listener to monitor the spark scan session.
sparkScan.AddListener(this);

Whenever a new barcode is scanned, the application calls ISparkScanListener.OnBarcodeScanned(). You can retrieve the newly scanned code by calling SparkScanSession.NewlyRecognizedBarcodes. The returned list contains only one barcode entry.

public void OnBarcodeScanned(SparkScan sparkScan, SparkScanSession session, IFrameData? data)
{
    if (session.NewlyRecognizedBarcodes.Count == 0)
    {
        return;
    }

    // Gather the recognized barcode
    Barcode barcode = session.NewlyRecognizedBarcodes[0];

    // This method is invoked from a recognition internal thread.
    // Run the specified action in the UI thread to update the internal barcode list.
    RunOnUiThread(() =>
    {
        // Update the internal list and the UI with the barcode retrieved above
        this.latestBarcode = barcode;
    });
}

You can also register the ISparkScanListener interface to subscribe to corresponding events:

sparkScan.BarcodeScanned += (object sender, SparkScanEventArgs args) =>
{
    if (args.Session.NewlyRecognizedBarcodes.Count == 0)
    {
        return;
    }

    // Gather the recognized barcode
    Barcode barcode = args.Session.NewlyRecognizedBarcodes[0];

    // This method is invoked from a recognition internal thread.
    // Run the specified action in the UI thread to update the internal barcode list.
    RunOnUiThread(() =>
    {
        // Update the internal list and the UI with the barcode retrieved above
        this.latestBarcode = barcode;
    });
}

5. Customize the user interface

To illustrate how you can customize the SparkScan user interface, here are two elements you can control to change scanning behavior:

Turn the device flashlight (torch) on or off during scanning
Automatically activating the device’s flashlight helps users locate and scan barcodes in low-light environments.

SparkScan offers a built-in API for this using SparkScanViewSettings.DefaultTorchState, with values for on, off, and auto (the flashlight is turned on or off based on the available illumination).

Display customizable toasts
SparkScanView allows you to display brief messages to the user to provide feedback. For example, to display a customized toast to the user, call ShowToast() with the desired string.

Xamarin.Forms

Follow these steps to add barcode scanning and pre-built UI components using SparkScan to your Xamarin.Forms app. For additional help and examples of how to integrate barcode scanning:

1. Create a new data capture context instance

To add barcode capture capabilities to your Xamarin.Forms app, you must create a new data capture context. The context expects a valid Scandit Data Capture SDK license key during construction.

DataCaptureContext dataCaptureContext = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --");

2. Configure the SparkScan mode

The SparkScan mode is configured through SparkScanSettings, which allows you to register one or more listeners who are informed whenever a new barcode is scanned.

The following code sets up SparkScan for scanning EAN13 barcodes but you can change this to the symbologies for your use case (e.g., Code 128, Code 39).

SparkScanSettings settings = new SparkScanSettings();
HashSet<Symbology> symbologies = new HashSet<Symbology>()
{
    Symbology.Ean13Upca
};
settings.EnableSymbologies(symbologies);

Next, create a SparkScan instance with the initialized settings:

SparkScan sparkScan = new SparkScan(settings);

3. Create a SparkScanView

SparkScan comes with a built-in user interface, called SparkScanView, that guides users through the scanning process and integrates with any app without requiring redesign or customization. It includes:

  • Camera preview screen
  • Large-sized scan button
  • Quick-access toolbar to adjust scanning settings

The appearance of SparkScanView is customized through SparkScanViewSettings.

SparkScanViewSettings viewSettings = new SparkScanViewSettings();
// setup the desired appearance settings by updating the fields in the object above

Adding a SparkScanView automatically adds a scanning interface to your application.

To add SparkScanView to your view hierarchy, add it as the last item to AbsoluteLayout or RelativeLayout layouts to ensure other UI components are visible:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:scandit="clr-namespace:Scandit.DataCapture.Barcode.Spark.UI.Unified;assembly=ScanditBarcodeCaptureUnified">
  <ContentPage.Content>
    <AbsoluteLayout>
      <!-- Your other UI components comes here before SparkScanView -->
      <scandit:SparkScanView
        x:Name="SparkScanView"
        AbsoluteLayout.LayoutBounds="0,0,1,1"
        AbsoluteLayout.LayoutFlags="All"
        DataCaptureContext="{Binding DataCaptureContext}"
        SparkScan="{Binding SparkScan}"
        SparkScanViewSettings="{Binding ViewSettings}">
      </scandit:SparkScanView>
    </AbsoluteLayout>
  </ContentPage.Content>
</ContentPage>

To ensure an optimal start-up time and that scanning is stopped when the app goes into the background, call SparkScanView.OnAppearing() and SparkScanView.OnDisappearing() in your Page.OnAppearing and Page.OnDisappearing callbacks:

protected override void OnAppearing()
{
    base.OnAppearing();
    this.SparkScanView.OnAppearing();
}

protected override void OnDisappearing()
{
    base.OnDisappearing();
    this.SparkScanView.OnDisappearing();
}

4. Register the listener for new barcode scans and update your data

To keep track of scanned barcodes, implement the ISparkScanListener interface and register the listener to the SparkScan mode:

// Register self as a listener to monitor the spark scan session.
sparkScan.AddListener(this);

Whenever a new barcode is scanned, the application calls ISparkScanListener.OnBarcodeScanned(). You can retrieve the newly scanned code by calling SparkScanSession.NewlyRecognizedBarcodes. The returned list contains only one barcode entry.

public void OnBarcodeScanned(SparkScan sparkScan, SparkScanSession session, IFrameData? data)
{
    if (session.NewlyRecognizedBarcodes.Count == 0)
    {
        return;
    }

    // Gather the recognized barcode
    Barcode barcode = session.NewlyRecognizedBarcodes[0];

    // This method is invoked from a recognition internal thread.
    // Run the specified action in the UI thread to update the internal barcode list.
    Device.InvokeOnMainThreadAsync(() =>
    {
        // Update the internal list and the UI with the barcode retrieved above
        this.latestBarcode = barcode;
    });
}

You can also register the ISparkScanListener interface to subscribe to corresponding events:

{
    if (args.Session.NewlyRecognizedBarcodes.Count == 0)
    {
        return;
    }

    // Gather the recognized barcode
    Barcode barcode = args.Session.NewlyRecognizedBarcodes[0];

    // This method is invoked from a recognition internal thread.
    // Run the specified action in the UI thread to update the internal barcode list.
    Device.InvokeOnMainThreadAsync(() =>
    {
        // Update the internal list and the UI with the barcode retrieved above
        this.latestBarcode = barcode;
    });
}

5. Customize the user interface

To illustrate how you can customize the SparkScan user interface, here is an example of how to trigger an error state based on different scanning conditions:

Trigger an error state
You may want to show an error message when scanning specific barcodes (e.g. barcodes already added or barcodes from a wrong lot). SparkScan provides a built-in error state to trigger an error feedback prompt to the user, with the following customization options:

  • Error message text.
  • Feedback type (sound, vibration).
  • Timeout of the error message where the scanner is paused for the specified time – the user can restart scanning by tapping the trigger button.
  • Color of the flashing screen upon scan, set by ISparkScanViewFeedback.
  • Color of the highlight box around the scanned barcode.

To emit an error, you must implement a ISparkScanFeedbackDelegate and set it to the SparkScanView. You can then trigger an error or success feedback to the user with ISparkScanFeedbackDelegate.GetFeedbackForBarcode().

This image shows an example of error feedback overlaid on device screens using the Scandit Xamarin Barcode Scanner SDK. On the right is a yellow “Duplicate barcode” error, and on the left a red “Wrong barcode” error.

Example error feedback overlaid on device screens using the Scandit Xamarin Barcode Scanner SDK, showing a yellow “Duplicate barcode” error on the right and a red “Wrong barcode” error on the left.

Testing barcode scanning performance

The best way to test a potential Xamarin barcode scanner API is to run it under real-world conditions. Whether you’re using the Scandit Xamarin Barcode Scanner SDK or another library, here are several performance-testing questions to ask:

  • Is there clear guidance to streamline workflows and provide instant feedback to avoid user confusion?
  • Can you scan barcodes orientated differently, such as upside down and sideways? If you flip the device upside down, can you still scan barcodes successfully?
  • Can you scan barcodes at a distance? Are you able to zoom in and capture barcodes if needed?
  • Can you scan barcodes with reflections and glare?
  • Do you receive scanning feedback in loud environments and while wearing headphones?

You can also use our sample sheet of barcodes to evaluate your app’s performance quickly.

Your Xamarin barcode scanner library is more than just a technical choice

User-centric design and performance are critical goals when selecting and implementing a barcode scanner in your Xamarin app. Fewer user frustrations and adaptability to growing business demands are preferable to low adoption rates, bug reports, and unhappy business leaders.

Next: Dive deeper into how to make a barcode scanning app performant →