Xamarin.Forms.iOS

This section will guide you through the implementation process of an Anyline Xamarin.iOS Scan View Renderer for the Xamarin.Forms project, including configuration and handling scan results.

Apple Developer Account

In order to set up an Apple Developer Account and the device, please follow the Device Provisioning Guide from the Xamarin Documentation.

Developing on a Windows Machine

If you want to develop on a Windows machine, you will require a Mac Build Host.
For more information, please check out the Windows Installation Guide from the Xamarin Documentation on how to install and run Xamarin.iOS projects on Windows.

Setup

Add the Anyline SDK via NuGet

To access the functionality of our SDK, simply right-click on your project, go to manage Nuget packages.. and search for "Anyline".

Select Anyline.Xamarin.SDK.iOS, install the latest available version, and accept the license agreement.

Generate an Anyline License Key

In order to run the Anyline SDK in your app, you require a license key.

In order to create a license key for your application, you have to identify the bundle identifier of your Xamarin.iOS app.

License <> Bundle Identifier

Every license is bound to an bundle identifier. If you change your bundle identifier, you will require a new license. This also ensures that your license key cannot be used in any other application.

How to identify the Bundle Identifier

To generate a license key for your application, refer to the bundle identifier of your Xamarin.iOS project. It is located under Properties > iOS Application > Identifier.

Initialize the SDK

In this step we will implement the service that will be called by the IAnylineSDKService in the Xamarin.Forms project. For this, create a new class in your Xamarin.iOS called AnylineSDKService.cs:

using Foundation;

[assembly: Xamarin.Forms.Dependency(typeof(Anyline.iOS.AnylineSDKService))]
namespace Anyline.iOS
{
	public class AnylineSDKService : IAnylineSDKService
	{
		public bool SetupWithLicenseKey(string licenseKey, out string licenseErrorMessage)
		{
			AnylineXamarinSDK.iOS.AnylineSDK.SetupWithLicenseKey(licenseKey, out NSError licenseError);

			if (licenseError == null)
			{
				licenseErrorMessage = null;
				return true;
			}
			else
			{
				licenseErrorMessage = licenseError.LocalizedDescription;
				return false;
			}
		}
	}
}

Providing an Anyline Configuration to the Scan View

With the Anyline Configuration, you can define your whole use case, including scanning parameters and the look & feel of your scanning view.
The configuration parameters define the visual information presented to the user, as well as the scan settings (like the resolution, etc.) and feedback that is presented to the user.

Have a look at the Scanning Capabilities section for more specific implementation details.

You can adapt your scan view easily by adding a .json file as an asset to your project and loading it. In this example, we will create a .json file and configure it for the MRZ scanning.

Visual Studio

  • In your Resources treenode, right-click on the folder and select Add > New Item…​

  • Choose Visual C# > Text File and name it scanConfig.json

Build Action

Make sure that the build action for this file is set to BundleResource.

Now open the file and paste the code from the following example:

scanConfig.json
{
	"cameraConfig": {
		"captureResolution": "1080p",
		"zoomGesture": true
	},
	"flashConfig": {
		"mode": "manual",
		"alignment": "top_left"
	},
	"viewPluginConfig": {
		"pluginConfig": {
			"id": "ID",
			"cancelOnResult": true,
			"mrzConfig": {
				"strictMode": false,
				"cropAndTransformID": false
			}
		},
		"cutoutConfig": {
			"maxWidthPercent": "90%",
			"maxHeightPercent": "90%",
			"alignment": "center",
			"ratioFromSize": {
				"width": 50,
				"height": 31
			},
			"cropPadding": {
			},
			"outerColor": "000000",
			"outerAlpha": 0.3,
			"strokeWidth": 2,
			"strokeColor": "0099FF",
			"cornerRadius": 4,
			"feedbackStrokeColor": "0099FF"
		},
		"scanFeedbackConfig": {
			"style": "rect",
			"visualFeedbackRedrawTimeout": 100,
			"strokeWidth": 2,
			"strokeColor": "0099FF",
			"fillColor": "220099FF",
			"beepOnResult": true,
			"vibrateOnResult": true,
			"blinkAnimationOnResult": false
		}
	}
}

This JSON builds the whole MRZ scanning use-case.

Adding the ScanPage Renderer

using Anyline;
using Anyline.iOS;
using AnylineXamarinSDK.iOS;
using CoreGraphics;
using Foundation;
using System;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(ScanExamplePage), typeof(ScanPageRenderer))]
namespace Anyline.iOS
{
    public class ScanPageRenderer : PageRenderer, IALScanPluginDelegate
    {
        private CGRect frame;
        private bool initialized;

        private ALScanView _scanView;

        protected override void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null || Element == null)
            {
                return;
            }

            InitializeAnyline();
        }

        public override void ViewDidAppear(bool animated)
        {
            base.ViewDidAppear(animated);

            if (!initialized) return;

            StartAnyline();
        }

        private void InitializeAnyline()
        {
            NSError error = null;

            if (initialized)
                return;

            try
            {
                // This is the main intialization method that will create our use case depending on the JSON configuration.
                _scanView = ALScanViewFactory.WithConfigFilePath("scanConfig.json", this, out error);

                if (error != null)
                {
                    throw new Exception(error.LocalizedDescription);
                }

                View.AddSubview(_scanView);

                // Pin the leading edge of the scan view to the parent view

                _scanView.TranslatesAutoresizingMaskIntoConstraints = false;

                _scanView.LeadingAnchor.ConstraintEqualTo(View.LeadingAnchor).Active = true;
                _scanView.TrailingAnchor.ConstraintEqualTo(View.TrailingAnchor).Active = true;
                _scanView.TopAnchor.ConstraintEqualTo(View.SafeAreaLayoutGuide.TopAnchor).Active = true;
                _scanView.BottomAnchor.ConstraintEqualTo(View.SafeAreaLayoutGuide.BottomAnchor).Active = true;

                _scanView.StartCamera();

                initialized = true;
            }
            catch (Exception e)
            {
                ShowAlert("Init Error", e.Message);
            }
        }

        private void StartAnyline()
        {
            NSError error = null;
            var success = _scanView.ScanViewPlugin.StartWithError(out error);
            if (!success)
            {
                if (error != null)
                {
                    ShowAlert("Start Scanning Error", error.DebugDescription);
                }
                else
                {
                    ShowAlert("Start Scanning Error", "error is null");
                }
            }
        }

        private void ShowAlert(string title, string text)
        {
            new UIAlertView(title, text, (IUIAlertViewDelegate)null, "OK", null).Show();
        }

        #region Handling Results
        [Export("scanPlugin:resultReceived:")]
        public void ResultReceived(ALScanPlugin scanPlugin, ALScanResult scanResult)
        {
			(Element as ScanExamplePage).ShowResultsAction?.Invoke(scanResult.ToString(), scanResult.Image.AsJPEG().ToArray());
		}
        #endregion


        #region teardown
        public override void ViewWillDisappear(bool animated)
        {
            base.ViewWillDisappear(animated);

            initialized = false;

            if (_scanView?.ScanViewPlugin == null)
                return;

            _scanView.ScanViewPlugin.Stop();
        }

        public override void ViewDidDisappear(bool animated)
        {
            base.ViewDidDisappear(animated);
            Dispose();
        }

        protected override void Dispose(bool disposing)
        {
            _scanView?.RemoveFromSuperview();
            _scanView?.Dispose();
            _scanView = null;
            base.Dispose(disposing);
        }
        #endregion
    }
}

That’s it!

Your Xamarin.Forms iOS project is all setup and ready to scan! Select a device and start scanning MRZ strings. For more detailed information, check the full Xamarin.iOS and the Native iOS SDK documentation.

Full Source Code

You can find the full source code on GitHub.
Open the solution in Visual Studio, build and deploy the application onto your iOS device.

Reduce Final App Size

Check now the Reduce App Size to learn how to remove unnecessary assets and reduce the final app size.