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 (e.g., a Windows implementation class for Xamarin).

<TLDR> Here is your download link https://github.com/manateeworks/xamarin-shopping-cart-demo-app... go do your thing.</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 - Once you get license keys it should be entered in your projects.

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

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

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

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

           - For ManateeShoppingCart.UWP(Universal Windows Platform) project open the BarcodeHelper.cs in NativeComponents folder and enter your windows license key in row 226:

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

Set startup project depends of platform and rebuild 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 (UWP) specific code and is the entry point for the UWP application;

Overview of the Droid 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

Apart from UWP and IOS in Droid project if we want to use splash screen we must to create our own activity, and show it as first screen on 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 Xamarin.Forms page, in this case this is ScannerActivity.cs.

DroidMethods.cs is a class that inherits from the NativeMethods interface which 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 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 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 which 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 entry platform is finished, the first page you will see is the AllListPage.xaml. This is the Xamarin.Forms Page that represents the cross-platform mobile app screens.

Image

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

Every row in list view contains two action buttons: pencil icon and trash icon. When you tap or click 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 where you can 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: If you press on the trash button you can delete the selected list:

    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 item in a list.

Image

Image 5 - Showing a filled list with 4 items

Add a new Item

You can add a new item in two ways:

  1.  Add your 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 platform we are using we are showing native page for UWP, activity for Droid or UIViewController for IOS in the Xamarin.Forms page.

Manage List items

After a successful barcode reading, a new item with appropriate type and result is entered in our list. With this new item we can do the following actions:

  1. Edit item: When you press the item in the list view, a Popup window appears. In this window we can edit the item's name. 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

    We can even change the Barcode associated with this item. By tapping on the barcode button next to each item we 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: If you press on the trash icon you can delete it 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 we are 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, we change the property to Check, change 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 we can cross the items out of the list and mark them as done

While we are in shopping mode, the navigation bar and status bar background colors are changed. If we want go back to edit the list, we can press the Edit list button from the navigation bar.

 

Conclusion

If you followed the instructions you should have 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 support Droid, IOS and UWP devices
2017-02-20
2017-03-16
Make your own Barcode Shopping application with Xamarin
Make your own Barcode Shopping application with Xamarin
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