The Manatee Works Barcode Scanner SDK is implemented as a software library that provides a lightweight, yet powerful barcode detection and decoding API optimized for mobile platforms. The Barcode Scanner SDK library supports many barcode symbologies and sub-types. The core routines are implemented in a static C library for high performance and portability, and where necessary, native wrappers are provided for the various platforms.

<TLDR> Here is your download link https://github.com/manateeworks/xamarin-shopping-cart-demo-app.</TLDR>

Installation steps

Step 1 - Download and install the latest Microsoft Visual Studio and make sure to include all Xamarin components through the installation.

Step 2 - Download the Manatee Works Barcode Scanner SDK project from the github repository, and Open file: MWBarcodeLibUniversalSDK.vsix.

Step 3 - Start Visual Studio and open the solution: ManateeShoppingCart.sln.

Image

Step 4 - The Manatee Works Barcode Scanner SDK needs a valid license in order to provide accurate results. Using the Barcode Scanner SDK without proper licensing is certainly possible, but the results will be masked with random characters throughout the result string. By first registering with the Mantee Works Developer Network you may generate a free trial license, valid for 30 days.

Step 5 - With license keys in hand, they may now be entered into each project.

           - For project ManateeShoppingCart.Droid, open the CameraPageRenderer.cs and enter your Android license key in row 125:          

int registrationResult = BarcodeConfig.MWB_registerSDK("key");

           - For project ManateeShoppingCart.iOS, open the CameraPageRenderer.cs and enter your iOS license key in row 112:

int registerResult = BarcodeConfig.MWB_registerSDK("key");

           - For project ManateeShoppingCart.UWP, open the BarcodeHelper.cs in NativeComponents folder and enter your Windows license key in row 226:

int registerResult = Scanner.MWBregisterSDK("key");

Set the startup project (depending on platform) and rebuild the ManateeShoppingCart solution.

Overview of the solution

This solution contains four projects:

  • ManateeShoppingCart – This project is the portable class library (PCL) project that holds all of the shared code and shared UI;
  • Droid – This project holds Android specific code and is the entry point for the Android application;
  • iOS – This project holds iOS specific code and is the entry point for the iOS application;
  • UWP – This project holds Universal Windows Platform specific code and is the entry point for the UWP application.

Overview of the Android project

In this project we are including Droid native classes that are used to work with a camera, scan the image, and give us a result from a scanning process:

  • CameraManager.cs
  • MWOverlay.cs
  • IMWBarcodeScanner.cs
  • MWBarcodeScanner.cs
  • ScannerActivity.cs

Unlike the UWP and iOS implementations, the Droid project must have its own activity to use a splash screen, and show it as the first screen on the application. Here in this project that activity is SplashActivity.cs  

ScanPageRenderer.cs is a class that inherits from PageRenderer. This class is helping us show activity as a Xamarin.Forms page, in this case this is ScannerActivity.cs.

DroidMethods.cs is a class that inherits from the NativeMethods interface that is defined in the portable project. Here we write our native Android methods that can be used in the portable project.

DependencyService allows apps to call into platform-specific functionality from shared code. This functionality enables Xamarin.Forms apps to do anything that a native app can do.

Overview of the iOS project

In this project we are including iOS native classes that are used to work with a camera, scan the image, and give us a result from a scanning process:

  • IMWBarcodeScanner.cs
  • MWBarcodeScanner.cs
  • MWOverlay.cs
  • MWResult.cs
  • MWScannerViewController.cs

ScanPageRenderer.cs is a class that inherits from PageRenderer. This class is helping us show UIViewController as a Xamarin.Forms page, in this case this is MWScannerViewController.cs.

IOSMethods.cs is a class that inherits from the NativeMethods interface, which is defined in the portable project. Here we write our native iOS methods that can be used in the portable project.

DependencyService allows apps to call into platform-specific functionality from shared code. This functionality enables Xamarin.Forms apps to do anything that a native app can do.

Overview of the UWP project

In this project we are including UWP native pages and classes that are used to work with a camera, scan the image, and give us a result from a scanning process:

  • BarcodeHelper.cs
  • MWOverlay.cs
  • ScannerPageNative.xaml

ExtendedSplash.xaml page is used if we want to keep the splash image on a little longer. If you want to use the ExtendedSplash page you should uncomment this code in App.xaml.cs page:

//Display an extended splash screen if app was not previously running.
if (e.PreviousExecutionState != ApplicationExecutionState.Running)
{
    bool loadState = (e.PreviousExecutionState == ApplicationExecutionState.Terminated);
    ExtendedSplash extendedSplash = new ExtendedSplash(e.SplashScreen, loadState);
    rootFrame.Content = extendedSplash;
    Window.Current.Content = rootFrame;
}


ScanPageRenderer.cs is a class that inherits from PageRenderer. This class is helping us show a UWP native page in Xamarin.Forms page, in this case this is ScannerPageNative.xaml.

UWPContentDialog.xaml is a native ContentDialog that will be used in the portable project.

UWPMethods.cs is a class that inherits from the NativeMethods interface, which is defined in the portable project. Here we write our methods that can be used in the portable project. To achieve this in App.xaml.cs we need to add this code at line 63:

Xamarin.Forms.DependencyService.Register<UWPMethods>();

DependencyService allows apps to call into platform-specific functionality from shared code. This functionality enables Xamarin.Forms apps to do anything that a native app can do.

In Package.appxmanifest we are setting the app name, description, capabilities (in this case we need access to Microphone and Webcam), splash screen image, app logo, etc.

Overview of the Portable project

As we already mentioned, Xamarin.Forms is a cross-platform, natively backed UI toolkit abstraction that allows developers to easily create user interfaces that can be shared across Android, iOS and Windows. The user interfaces are rendered using the native controls of the target platform, allowing Xamarin.Forms applications to retain the appropriate look and feel for each platform.

All pages, classes, interfaces, etc., that are shared for every platform, are placed in this project. 

App Start Screen

When the Splash screen from an entry platform is finished, the first page is the AllListPage.xaml. This is the Xamarin.Forms Page that represents the cross-platform mobile app screens.

Image

Image 1 - Showing shopping lists. Every list can contain multiple items.

Every row in list view contains two action buttons: pencil icon and trash icon. When the user taps or clicks one of them, an appropriate action attached to each of them will be executed. Also tapping or clicking a row will open the list and navigate to the items contained in that list.

At the bottom of the page there is an entry field. This field will be used to add a new list, by typing the new list's name:

  • Add a New List
    Image

    Image 2 - Showing an active keyboard on "add new list" field
    public void entryNewListCompleted(object sender, EventArgs args)
    {
      Entry entry = ((Entry)sender);
    
      list = new ListsModel();
    
      if (entry.Text != null && entry.Text.Trim().Length > 0)
      {
        int id = 1;
        if (allLists.Count > 0)
        id = ((int)allLists.Max(x => x.ID)) + 1;
    
        list.ID = id;
        list.Name = entry.Text;
    
        allLists.Insert(0, list);
        Application.Current.Properties["AllLists"] = JsonConvert.SerializeObject(allLists);
      }
    
      entry.Text = "";
      entry.Unfocus();
    }

    Code Snippet - Action attached to entry field Add new List

    ListsModel is a class that represents every item in the list view. The Application base class offers the features that are exposed in our project default App subclass. One of the features is a static Properties dictionary that can be used to store data. This can be accessed from anywhere in Xamarin.Forms code using Application.Current.Properties. The Properties dictionary uses a string key and stores an object value. Because the Properties dictionary can only serialize primitive types for storage in our case, we need to convert our ObservableCollection<ListsModel> object in JSON format first and then store the value. Notice how at the end of the method we use entry.Unfocus() to hide the keyboard.

 

  • Edit list: By pressing on the pencil button a popup window appears to change the name of the list:

     Image

    Image 3 - Showing a popup that allows editting a list's name
    public async void imgEditTapped(object sender, EventArgs args)
    {
      try
      {
        int editID = int.Parse(((TappedEventArgs)args).Parameter.ToString());
        list = allLists.First(x => x.ID == editID);
    
        if (list != null && list.ID > 0)
        {
          listViewAllLists.ItemsSource = null;
          await DependencyService.Get<NativeMethods>().ShowDialog(list, "Are you sure that you want to edit name for " + list.Name);
          Application.Current.Properties["AllLists"] = JsonConvert.SerializeObject(allLists);
        }
      }
      catch (Exception ex)
      {
        Debug.WriteLine(ex.Message);
      }
      finally
      {
        listViewAllLists.ItemsSource = allLists;
      }
    }
    Code snippet - Action attached to the editImage button

    As we discussed before in this topic, with DependencyService we can use platform-specific functionality from a portable project. Here we are using our native content dialog that we created appropriate for the platform use.
  • Delete item: Pressing on the trash button the selected list is deleted:

    Image

    Image 4 - Showing a delete list popup
    public async void imgDeleteTapped(object sender, EventArgs args)
    {
      try
      {
        int deleteID = int.Parse(((TappedEventArgs)args).Parameter.ToString());
        list = allLists.First(x => x.ID == deleteID);
        listViewAllLists.SelectedItem = list;
    
        if (list != null && list.ID > 0)
        {
          var answer = await DisplayAlert("", "Are you sure you want do delete " + list.Name, "OK", "CANCEL");
          if (answer)
          {
            //On Windows
            //Have some problem with autofocus on entry after delete, that's why here i disable entry and after that in listViewItemDisappearing it is enabled again		                        
            if (Device.OS == TargetPlatform.Windows)
                entryNewList.IsEnabled = false;
    
            allLists.Remove(list);
            Application.Current.Properties["AllLists"] = JsonConvert.SerializeObject(allLists);
          }
        }
      }
      catch (Exception ex) { }
    
      listViewAllLists.SelectedItem = null;
    }
    Code snippet - Action attached to the "delete list" button

    For these popups we are using DisplayAlert, a modal pop-up to alert the user or ask simple questions of them. In our case we will be asking for confirmation to delete the list.

 

List Items

After creating lists, if we tap on the row from List View we can add items to the appropriate list. Same like in lists, you can add, edit or delete every list item.

Image

Image 5 - Showing a filled list with 4 items

Add a new Item

New items can be added in two ways:

  1.  Add a new item by typing the item name in the "Add new item" entry field.

    Image

    Image 6 - Showing how to add a new entry in the list
          public void entryNewItemCompleted(object sender, EventArgs args)
          {
            Entry entry = ((Entry)sender);
    
            item = new ItemModel();
    
            if (entry.Text != null && entry.Text.Trim().Length > 0)
            {
              int id = 1;
              if (selectedList.Items.Count > 0)
              id = ((int)selectedList.Items.Max(x => x.ID)) + 1;
    
              item.ID = id;
              item.Name = entry.Text;
              item.BarcodeType = "Barcode type";
              item.BarcodeResult = "Result";
    
              selectedList.Items.Insert(0, item);
              SaveListChanges();
            }
            entry.Text = "";
            entry.Unfocus();
          }
    Code snippet - Action associated with the add new Item entry field
     
  2. The other option is to press on the barcode button in the right corner. When the barcode button is pressed we navigate to the ScanPage.xaml page. This is an important part of our app as it initializes the Barcode Scanner and prepares the app for scanning.
    public async void imgScanNewTapped(object sender, EventArgs args)
    {
      if (Device.OS == TargetPlatform.iOS)
          await Navigation.PushAsync(new ScanPage(selectedList.Items, selectedListIndex, -1));
      else
          await Navigation.PushModalAsync(new ScanPage(selectedList.Items, selectedListIndex, -1));
    }

    Code snippet - Navigate to the Barcode Scanner Page

 

We will be using the Navigation interface to manage the page navigation experience. With this code, we navigate from ItemsPage to ScanPage, passing parameters into the constructor of ScanPage.

ScanPage is also a Xamarin.Forms page but using a ScanPageRenderer.cs from the appropriate platform we are showing native page for UWP, activity for Droid or UIViewController for IOS in the Xamarin.Forms page.

Manage List items

After each successful barcode reading, a new item, with the appropriate type and result, is entered into a list. The following actions may be made against each item:

  1. Edit item: When pressing the item in the list view, a Popup window appears. The item's name can be edited in this window. A confirmation is needed to save the change:

    .Image

    Image 7 - Showing the popup that lets us edit the name of an item (Milk)
    public async void listViewItemTapped(object sender, ItemTappedEventArgs args)
    {
      if (selectedList.ActionType == ItemsActionType.Check)
      return;
    
      try
      {
        item = (ItemModel)args.Item;
    
        if (item != null && item.ID > 0)
        {
          listItemsView.ItemsSource = null;
    
          await DependencyService.Get<NativeMethods>().ShowDialog(item, "Are you sure that you want to edit name for " + item.Name);
          SaveListChanges();
        }
      }
      catch (Exception ex)
      {
        Debug.WriteLine(ex.Message);
      }
      finally
      {
        listItemsView.ItemsSource = selectedList.Items;
      }
    }

    Code Snippet - Edit the item action is tapped and a popup is shown

    The user can even change the barcode associated with this item. By tapping on the barcode button next to each item they may navigate to the ScanPage and scan a barcode again.

      public async void imgScanEditTapped(object sender, EventArgs args)
      {
        try
        {
          int selectedID = int.Parse(((TappedEventArgs)args).Parameter.ToString());
          item = selectedList.Items.First(x => x.ID == selectedID);
          listItemsView.SelectedItem = item;
    
          if (item != null && item.ID > 0)
          {
             if (Device.OS == TargetPlatform.iOS)
                await Navigation.PushAsync(new ScanPage(selectedList.Items, selectedListIndex, selectedList.Items.IndexOf(item)));
             else
                await Navigation.PushModalAsync(new ScanPage(selectedList.Items, selectedListIndex, selectedList.Items.IndexOf(item)));
          }
        }
        catch (Exception ex) { }
    
        listItemsView.SelectedItem = null;
      }

    Code Snippet - Change the Barcode associated with an item

  2. Delete an item: Press on the trash icon to delete an item from the list:

    Image

    Image 8 - Delete item named Milk
     
    public async void imgActionTapped(object sender, EventArgs args)
    {
      try
      {
        int actionID = int.Parse(((TappedEventArgs)args).Parameter.ToString());
        item = selectedList.Items.First(x => x.ID == actionID);
        listItemsView.SelectedItem = item;
    
        if (item != null && item.ID > 0)
        {
          if (selectedList.ActionType == ItemsActionType.Edit)
          {
            var answer = await DisplayAlert("", "Are you sure you want do delete " + item.Name, "OK", "CANCEL");
            if (answer)
            {
               //On Windows
               //Have some problem with autofocus on entry after delete, that's why here i disable entry and after that in listViewItemDisappearing it is enabled again		                        
               if (Device.OS == TargetPlatform.Windows)
                  entryNewItem.IsEnabled = false;
    
            selectedList.Items.Remove(item);
            SaveListChanges();
            }
          }
          else
          if (selectedList.ActionType == ItemsActionType.Check)
          {
            if (item.Checked)
            {
              ((Image)sender).Source = "Assets/checkboxBlank36x36.png";
              item.Checked = false;
              item.ActionImageUrl = "Assets/checkboxBlank36x36.png";
            }
            else
            {
              ((Image)sender).Source = "Assets/checkboxMarked36x36.png";
              item.Checked = true;
              item.ActionImageUrl = "Assets/checkboxMarked36x36.png";
            }
            SaveListChanges();
          }
        }
      }
      catch (Exception ex) { }
    
      listItemsView.SelectedItem = null;
    }
    Code Snippet - The delete button is tapped and the appropriate action (delete) is taken
     

Shopping mode

ListModel class has a property ActionType that can be Edit or Check. When editing list items or creating new ones, the ActionType property for that list is Edit. When a shopping icon from the navigation bar is pressed, the property is changed to Check, changing the trash icon to the check icon, and the user can check done (bought) items for that list.

Image
Image 9 - Showing a Checkout List

private void shoppingClick(object sender, EventArgs e)
{
  listItemsView.Unfocus();

  if (selectedList.ActionType == ItemsActionType.Check)
  {
    gridAddNewItem.IsVisible = true;

    foreach (ItemModel item in selectedList.Items)
    {
      item.ActionImageUrl = "Assets/trash36x36.png";
      item.ScanEditImageUrl = "Assets/barcode36x36.png";
    }

    selectedList.ActionType = ItemsActionType.Edit;
    ((ToolbarItem)sender).Icon = "Assets/shopping.png";
    ((ToolbarItem)sender).Text = "Shopping";

    if (this.Parent != null)
    {
      try
      {
         ((NavigationPage)this.Parent).BarBackgroundColor = Color.FromHex("#1ab78d");
         DependencyService.Get<NativeMethods>().SetStatusBar("#1ab78d");

         listItemsView.SeparatorColor = Color.FromHex("#1ab78d");
       }
       catch { }
    }
  }
  else
  {
    gridAddNewItem.IsVisible = false;

    foreach (ItemModel item in selectedList.Items)
    {
      if (item.Checked)
         item.ActionImageUrl = "Assets/checkboxMarked36x36.png";
      else
         item.ActionImageUrl = "Assets/checkboxBlank36x36.png";

      item.ScanEditImageUrl = "";
    }

    selectedList.ActionType = ItemsActionType.Check;
    ((ToolbarItem)sender).Icon = "Assets/Pencil36x36.png";
    ((ToolbarItem)sender).Text = "Edit List";

    if (this.Parent != null)
    {
      try
      {
         ((NavigationPage)this.Parent).BarBackgroundColor = Color.FromHex("#e5a82d");
         DependencyService.Get<NativeMethods>().SetStatusBar("#e5a82d");

         listItemsView.SeparatorColor = Color.FromHex("#e5a82d");
      }
      catch { }
    }
  }

  SaveListChanges();

  listItemsView.ItemsSource = null;
  listItemsView.ItemsSource = selectedList.Items;
}

Code Snippet - When checkout is active the items in the list are marked as done

While in shopping mode, the navigation bar and status bar background colors are changed. Press the Edit list button from the navigation bar to return to editing. 

 

Conclusion

If you followed the instructions you should have an app that can work on Android, IOS, and UWP devices that utilizes the Manatee Works Barcode Scanner built on the Xamarin cross-platform framework. The app enables the user with the ability to create lists, add items to those lists, modify those items, attach them to barcodes, and check-off the same items when done.

This app should not be used in production. It is here for tutorial purposes, and maintains only a small set of possible features that a real-life shopping cart app should have.

Here we explain in short steps how to make your own Barcode Shopping application with Xamarin that will support Android, IOS and UWP devices.
2017-02-20
2017-10-26
Xamarin Barcode Shopping Application
Xamarin Barcode Shopping Application
ManateeWorks
info@manateeworks.com
Mobile apps need to be increasingly more engaging to succeed. Manatee Works can help. Our mobile barcode scanner SDK is available on all major mobile development platforms.
ManateeWorks