Implementing the Anyline Plugin

As described here, the Anyline SDK is based around the concept of plugins. Plugins can be brought in and configured to implement your scanning use case for your application.

This section walks you through the steps in order to set up a view and work with Anyline plugins for your UWP application.

Overview

The examples provided here are based on a simple meter scanning use case. A more detailed discussion can be found in the next section, as well in the API Reference.

Adding the ScanView to your Page

Let’s create a new blank page in your project and call it "ScanPage". This will create two files:

  • ScanPage.xaml: The view.

  • ScanPage.xaml.cs: The code-behind.

Open The first step is to add the ScanView to the XAML code of your Page in order to embed it into the view. In our case, we’ll call it "AnylineScanView".

<Page
    x:Class="AnylineExamples.ScanPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:AnylineExamples"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    xmlns:anyline="using:Anyline.SDK.Views"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid>
        <anyline:ScanView x:Name="AnylineScanView"/>
    </Grid>
</Page>

In the code-behind (ScanPage.xaml.cs), You’ll now have access to the ScanView and are almost ready to configure your scanner.

Before we jump into the code, let’s first add a config file to your project.

  • Right-click on your project, select Add…​New Item…​Text File and call it "meter_config.json"

  • Right-click on that file, select Properties…​ and set the Build Action to "Content"

Open the file and add the following code:

{
  "cameraConfig": {
    "captureResolution": "1080p"
  },
  "flashConfig": {
    "mode": "manual",
    "alignment": "top_right"
  },
  "viewPluginConfig": {
    "pluginConfig": {
      "id": "MyMeterPlugin",
      "meterConfig": {
        "scanMode": "auto_analog_digital_meter"
      },
      "cancelOnResult": true
    },
    "cutoutConfig": {
      "style": "rect",
      "alignment": "top",
      "strokeWidth": 2,
      "strokeColor": "FFFFFF",
      "cornerRadius": 4,
      "outerColor": "000000",
      "outerAlpha": 0.5,
      "feedbackStrokeColor": "0099FF",
      "width": 550,
      "maxWidthPercent": "90%",
      "maxHeightPercent": "90%",
      "ratioFromSize": {
        "width": 2.25,
        "height": 1
      }
    },
    "scanFeedbackConfig": {
      "style": "CONTOUR_RECT",
      "strokeColor": "0099FF",
      "strokeWidth": 2,
      "fillColor": "220099FF",
      "cornerRadius": 2,
      "redrawTimeout": 200,
      "animationDuration": 75,
      "blinkOnResult": true,
      "beepOnResult": true,
      "vibrateOnResult": true
    }
  }
}

You’ll find what each of the parameters means in the View Configuration section.

Initialize the ScanView

By this time, you should already have initialized the Anyline SDK with the license key for your application. For more details, please see Initialize the Anyline SDK.

Now it’s time to initalize the ScanView with that configuration.

In ScanPage.xaml.cs, override the OnNavigatedTo method as follows:

protected async override void OnNavigatedTo(NavigationEventArgs args)
{
    base.OnNavigatedTo(args);
    try
    {
        await ScanView.InitAsync("meter_config.json");
    } catch (Exception e)
    {
        // handle exception here!
    }
}

This will instantiate & configure all necessary objects and attach them to the ScanView automatically.

If you call ScanView.ScanViewPlugin, you’ll get the instance of your configured ScanViewPlugin. This property gives you a ViewPluginBase, which can either be a ScanViewPlugin or a ViewPluginComposite. This depends on whether you are using a parallel/sequential scanning workflow or not.

Handling Results

Once your plugin is configured, you can directly register to listen to events of the ScanView.ScanViewPlugin.ScanPlugin.

// once the scan view is initialized, we can hook on the plugin events
// depending on the configuration, the ViewPlugin is either a
// ViewPluginComposite or a ScanViewPlugin
if (AnylineScanView.ScanViewPlugin is Anyline.SDK.ViewPlugins.ScanViewPlugin scanViewPlugin)
{
    // A ScanViewPlugin holds a ScanPlugin which is the scanning component and delivers us a scan result
    scanViewPlugin.ScanPlugin.ResultReceived += ScanPlugin_ResultReceived;
} else if (AnylineScanView.ScanViewPlugin is Anyline.SDK.ViewPlugins.ViewPluginComposite viewPluginComposite)
{
    // A ViewPluginComposite holds multiple ScanViewPlugins, which run either sequentially or in parallel
    // In this case, we simply want to get all scan results once the workflow is done
    viewPluginComposite.AllResultsReceived += ViewPluginComposite_AllResultsReceived;
}

...

private void ScanPlugin_ResultReceived(object sender, Anyline.SDK.Plugins.ScanResult scanResult)
{
    // do something with the result image
    AnylineImage image = scanResult.Image;

    // do something with the meter result
    MeterResult meterScanResult = scanResult.PluginResult.MeterResult;

    // do something with the result as a JSON object
    JObject json = scanResult.ResultJsonObject;
}

private void ViewPluginComposite_AllResultsReceived(object sender, List<Anyline.SDK.Plugins.ScanResult> scanResults)
{
    // do something with all results of the composite
}

Handling camera events

A common scenario is to start the camera once the scan view is initialized, and once the camera is opened successfully, start the scanning process. Here’s how to do that:

// register to camera events (in 'OnNavigatedTo')
AnylineScanView.CameraView.CameraOpened += CameraView_CameraOpened;
AnylineScanView.CameraView.CameraClosed += CameraView_CameraClosed;

...

private void CameraView_CameraOpened(object sender, Size resolutionSize)
{
    try
    {
        // start scanning once the camera is opened
        AnylineScanView.StartScanning();
    }
    catch (Exception e)
    {
        Debug.WriteLine("Unable to start scanning: " + e.Message);
    }
}

private void CameraView_CameraClosed(object sender, bool closedSuccessfully)
{
    // stop scanning when the camera is closed
    AnylineScanView.StopScanning();
}
Final things

Once you navigate away from your page, you want to consider cleaning up resources. This includes stopping the camera and more importantly, disposing the ScanView.

You also might want to unregister any events that might keep the GarbageCollector from freeing resources.

// clean up any dependencies here
protected override async void OnNavigatingFrom(NavigatingCancelEventArgs args)
{
    base.OnNavigatingFrom(args);

    // unregister events
    Window.Current.VisibilityChanged -= Current_VisibilityChanged;

    await AnylineScanView.StopCameraAsync();

    // IMPORTANT: call dispose to clean up all resources!
    AnylineScanView.Dispose();
}

And voilá - That’s all it takes - You’re ready to scan now 👏🎉.

You can find the complete source code in our GitHub examples.