Xamarin SDK

The U Grok It SDK for Xamarin enables easy integration of RFID functionality into a Xamarin app for iOS (ioS 10 or later) or Android. Xamarin is a platform for building native mobile applications using C#.

Xamarin allows two modes of development

  • Native UI wrappers
    Using this method, you use c# wrappers around the native UI, and you can make apps using all the power of the native iOS or Andorid platform. Non-UI code can be common between the iOS and Android aps, but the UI code is specific for each platform.
  • Xamarin.Forms
    Using this method, the entire app can be common between platforms. UI is written using the Xamarin.Forms API. The UI is rendered using native UI lements so the app looks native on each platform, but there is somewhat less UI flexibility.

Xamarin is available here.

This SDK is implemented as a NuGet lackage for Xamarin and is built on the U Grok It iOS and Android SDKs.

Download the SDKs
iOS, Android, Cordova, Xamarin
Tools

The SDK was developed and tested with:

  • Windows - Visual Studio Community 2017 - version 15.5 or later
    Follow these instructions to install Xamarin support: Windows Installation
    NOTE: version 15.5 or later is required to be able to use the latest Android platform, which is required by Xamarin.
    NOTE: iOS development is not supported on Windows
  • Mac - Visual Studio for Mac Community 7.6.10
    Follow these instructions: Setup and Install Visual Studio for Mac
Portable applications NOT SUPPORTED

The SDK cannot be integrated into a portable Xamarin app, because the SDK contains native code and portable apps do not allow native code. The SDK can only be integrated into a shared library app.

Sample apps

The SDK including sample apps is distributed as a ZIP file and includes:

  • UGrokItApi.VERSION.nupkg
    The NuGet package (same as available at nuget.org)
  • samples (folder)
    This folder contains three sample apps. To open the sample, open the .sln file inside the sub-folder.
    • ApiDemoIos
      iOS sample app using the native UI wrappers.
    • ApiDemoAndroid
      Android sample app using the native UI wrappers.
    • ApiDemoForms
      Sample app using Xamarin.Forms, that runs on both iOS and Android.
Integrating the API into an existing app
Android Target Framework

The UGrokIt SDK is built with "target framework" set to use the Android 8.1 platform (Oreo), which is the most recent as of April 2018. Your app needs to use this platform or later. This is set in Build->General.
NOTE: There is a bug in Visual Studio for Mac, so that after setting this target framework, you must close the project and repoen it before you can use a package that requires this framework.

The UGrokIt NuGet package

To integrate the U Grok It API into an existing app, use the NuGet package "UGrokItApi" as documented here: Including a NuGet package in your project

Android Permissions

Edit AndroidManifest.xml and add these permissions:

  • RECORD_AUDIO
  • MODIFY_AUDIO_SETTINGS
    Needed to temporarily set the volume when connecting to the Grokker. The volume is reset when the connection is not active.
  • INTERNET
    Used in a few specific cases, all of which can be disabled. See SDK Internet Usage.

iOS Permissions

Edit Info.plist and add a "Privacy - Microphone Usage Description" entry. This is the message iOS will show the user to request permission to use the microphone.

iOS and Android API

The Xamarin API for iOS and Android is almost exactly the same, with a couple of minor differences because of differences between the platforms. The documentation has iOS ONLY or ANDROID ONLY where this is the case.

Accessing the API

The API is accessed through the Ugi singleton object in the UGrokItApi namespace.

using UGrokItApi;

The singleton object must be explicitly created with the CreateSingleton.

iOS

This is usually done in your application delegate's constructor or in main.c
public AppDelegate() : base()
{
  Ugi.CreateSingleton ();
  Ugi.Singleton().OpenConnection ();
}

Android

This is usually done in app's OnCreate method
  [Application]
  public class MyApp : Android.App.Application {
    public MyApp(IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer) {
    }
    public override void OnCreate() {
      base.OnCreate();
      Ugi.CreateSingleton (this);
      Ugi.Singleton().OpenConnection ();
    }
  }

Xamarin.Forms

This is usually done in app's constructor
  public App () {
    Ugi.CreateSingleton ();
    ...
  }
Housekeeping

A production level app needs to do a few housekeeping functions:

  • Region Setting
    A new Grokker must be configured for the region of the world that it will operate in.
  • Firmware Update
    From time to time, we will release firmware updates for the Grokker.

Calling Ugi.CreateSingleton() as shown above will use standard UI built into the SDK for these functions.

Activities (ANDROID ONLY)

On Andriod, Activities that use U Grok It need to notify the Ugi object of state changes. U Grok It uses these notifications to:

  • Know when the app is active
    When the app becomes inactive, U Grok It closes the connection to the Grokker and stops using the audio input/output. To know when the app is active, U Grok It counts the number of active Activities.
  • Screen rotation
    If the Android device is phone-sized and has the audio jack on top, U Grok It will rotate the screen to correct for the user having to hold the device upside down. This is only done when an Activity is active.

This is done by calling the ActivityOnCreate(), ActivityOnDestroy(), ActivityOnResume() and ActivityOnPause() methods of the Ugi singleton object.

  public class MainActivity : Activity, IUgiInventoryDelegate
  {

    protected override void OnCreate (Bundle savedInstanceState)
    {
      base.OnCreate (savedInstanceState);
      Ugi.Singleton().ActivityOnCreate (this, true);
    }

    protected override void OnDestroy ()
    {
      base.OnDestroy ();
      Ugi.Singleton().ActivityOnDestroy (this);
    }

    protected override void OnResume ()
    {
      base.OnDestroy ();
      Ugi.Singleton().ActivityOnResume (this);
    }

    protected override void OnPause ()
    {
      base.OnDestroy ();
      Ugi.Singleton().ActivityOnPause (this);
    }
  }
App lifecycle (Xamarin.Forms ONLY)

To access the added Xamarin.Forms API, add:

using UGrokItApiForms;

Add the following the the app's lifecycle methods (this allows UGrokIt to know when the app is active, and to handle screen rotation, if desired)

  public class App : Application {
    public App () {
      Ugi.CreateSingleton ();
      UgiForms.AppOnCreate (true, true);
      ...
    }
    protected override void OnStart () {
      UgiForms.AppOnStart ();
      ...
    }
    protected override void OnSleep () {
      UgiForms.AppOnSleep ();
      ...
    }
    protected override void OnResume () {
      UgiForms.AppOnResume ();
      ...
    }
  }
Opening and Closing a connection to the grokker

Communication with the grokker is done via the audio port. For an application that uses U Grok It functionality all the time, this is done in the application delegate's init and applicationWillTerminate methods. For an application that only uses U Grok It occasionally, the connection can be opened and closed at the appropriate points.

  Ugi.Singleton().OpenConnection();
  Ugi.Singleton().CloseConnection();

OpenConnection returns immediately, it does not wait for a connection to the grokker to actually be established. If a grokker is connected, the connection takes 400-500ms (just under half a second) for the connection sequence. Your app can get notification of connection state changes vis the ConnectionStateChanged delegate:

  Ugi.Singleton().ConnectionStateChanged += ConnectionStateHandler;

The handler method looks like this:

  void ConnectionStateHandler(Ugi.ConnectionStates state) {
    if (state == Ugi.ConnectionStates.Connected) {
      // Connection was established...
    }
  }

Usually a state changed method is not needed, using the Inventory methods described below takes care of this.

Inventory

Finding RFID tags is accomplished by running inventory. Once inventory is started, the grokker continually looks for RFID tags and reports them back to the iOS device.

Starting inventory returns a UgiInventory object that holds the results of the inventory. The application can either save the UgiInventory object or can use Ugi.Singleton ().ActiveInventory to get to it.

UgiInventory does some useful aggregation of the raw data from the grokker and reports back to your application via an InventoryDelegate object. Inventory can be run either with a configuration built from one of the pre-defined inventory types or with a custom UgiRfidConfiguration object.

The application can tell the grokker to report all RFID tags it finds:

  Ugi.Singleton().StartInventory(this,    // delegate object
        UgiRfidConfiguration.ConfigWithInventoryType(
                        UgiRfidConfiguration.InventoryTypes.LocateDistance));

Or the application can pass a specific tag to find:

  UgiEpc epc = UgiEpc.FromString("35fffffff99c70a063405c48");
  Ugi.Singleton().StartInventory(this,    // delegate object
        UgiRfidConfiguration.ConfigWithInventoryType(
                        UgiRfidConfiguration.InventoryTypes.LocateDistance),
        epc);

Or the application can pass an array of tags to find:

  UgiEpc epc1 = UgiEpc.FromString("35fffffff99c70a063405c48");
  UgiEpc epc2 = UgiEpc.FromString("35fffffff956734504747454");
  Ugi.Singleton().StartInventory(this,    // delegate object
        UgiRfidConfiguration.ConfigWithInventoryType(
                        UgiRfidConfiguration.InventoryTypes.LocateDistance),
        new List() { epc1, epc2});

Inventory runs until the application stops it.

  Ugi.Singleton().ActiveInventory.StopInventory(() => {
    // code to run when inventory is completely stopped
  });
Inventory Delegate methods

The inventory code reports back to the application via the inventory delegate object. The delegate object must implement the IUgiInventoryDelegate protocol:

public class MainActivity : Activity, IUgiInventoryDelegate

Only a subset of the inventory delegate methods are discussed here.

New tag found

When a new tag is found, the delegate is notified via inventoryTagFound (the detailedPerReadData is nil unless the Grokker was told to return detailed per-read data).

  public void InventoryTagFound(UgiTag tag,
                                UgiDetailedPerReadData[] detailedPerReadData) {
    // tag was found for the first time
  }

The UgiTag object contains information about the tag including:

  • Its EPC code
  • The time the tag was first read, the time the tag was most recently read
  • The total number of times this tag has been read
  • A history of how many times this tags has been read in recent time intervals (the default being the number of reads per 500ms going back 10 seconds, but this is configurable)
Subsequent finds of previously found tag

When a tag is found again, the delegate is notified via inventoryTagSubsequentFinds (the detailedPerReadData is nil unless the Grokker was told to return detailed per-read data).

  public void InventoryTagSubsequentFinds(UgiTag tag, int count,
                  UgiDetailedPerReadData[] detailedPerReadData) {
    // tag found count more times
  }
Tag visibility changed

When a tag is first found, has not been seen for a while (by default 10 seconds, but configurable), or is seen again after not being seen for awhile, the delegate is notified via:

  public void InventoryTagChanged(UgiTag tag, bool firstFind) {
    if (firstFind) {
      // tag was found for the first time
    } else if (tag.IsVisible) {
      // tag was not visible, is now visible again
    } else {
      // tag is no longer visible
    }
  }

Usually the delegate either implements InventoryTagChanged, or implements InventoryTagFound (and sometimes InventoryTagSubsequentFinds).

Tag filtering

The delegate can filter which tags are kept track of via:

  public bool InventoryFilter(UgiEpc epc) {
    if (this tag should be ignored) {
      return true;
    } else {
      return false;
    }
  }

If this method returns true, the tag is ignored entirely; InventoryTagFound, InventoryTagSubsequentFinds and InventoryTagChanged are never called for it.

List of found tags

While inventory is running, the app can access the list of found tags via the tags property of the UgiInventory object. Usage is typically:

  foreach (UgiTag tag in Ugi.Singleton().ActiveInventory.Tags) {
    // do something with tag
  }
Tag Access (read, write, ...)

Methods in UgiInventory allow tag access for reading, writing and locking. All of these functions work similarly.

Tag programming (changing tag EPC)

While inventory is running, the app can program tags via:

  UgiEpc oldEpc = UgiEpc.FromString("35fffffff99c70a063405c48");
  UgiEpc newEpc = UgiEpc.FromString("35fffffff956734504747454");
    Ugi.Singleton().ActiveInventory.ProgramTag(oldEpc, newEpc
                    UgiInventory.NO_PASSWORD,
                    (UgiTag tag, UgiInventory.TagAccessReturnValues result) => {
      if (result == UgiInventory.TagAccessReturnValues.Ok) {
        // tag programmed successfully
      } else {
        // tag programming was unsuccessful
      }
    });

Sometime after the ProgramTag method is called, the completion will be with the success or failure of the programming.

Grokker Configuration
Inventory

The UgiRfidConfiguration object holds the configuration to be used during inventory. Several pre-defined types can be used, defined in the UgiInventoryTypes enum. Values that can be configured include:

  • Power level
    Initial, minimum and maximum power levels can be set. If a range is provided (minimum != maximum), then the power level is varied over this range.
  • Q value
    Initial, minimum and maximum Q values can be set. If a range is provided (minimum != maximum), then the Q value is dynamically adjusted based on the number of tags in range
  • Session
    The inventory session (0, 1, 2, or 3)
  • Power level and sensitivity for writing tags
    The power level and sensitivity used when writing data to tags
  • Sensitivity
    The reader sensitivity

For more detailed information about RFID and configuration, see RFID Configuration

SDK Internet Usage

The SDK uses the Internet in a few cases, see SDK Internet Usage for details.

Localization

The SDK contains user visible strings for updating firmware, setting region of the world, and UI building blocks. It is localized into Spanish, French and German. If you are interested in localizations to other languages, contact us.