Capture Helper

Capture Helper is the easiest and recommended way for adding the barcode scanning capabilities to a C# application (Windows or Xamarin).

Capture Helper Initialization

To use Capture Helper, first create an instance of Capture Helper and register for the events your application requires and open Capture Helper. If opening Capture Helper returns an error such as SktErrors.ESKT_UNABLEOPENDEVICE (-27), it might be because the Socket Mobile Companion software is not installed or not running.

Here is a typical Capture Helper initialization:

public Form1()
{
    InitializeComponent();

    // initialize CaptureHelper
    capture = new CaptureHelper()
    {
        // make the events running in UI Thread context
        // Note this MUST be done on the UI thread.  If not,
        // UI updates from CaptureHelper will not occur
        // Setting this is optional.
        ContextForEvents = SynchronizationContext.Current;
    };

    // register for the Capture Helper events
    capture.DeviceArrival += CaptureDeviceArrival;
    capture.DeviceRemoval += CaptureDeviceRemoval;
    capture.DeviceOwnershipChange += CaptureDeviceOwnershipChange;
    capture.DecodedData += CaptureDecodedData;
    capture.Errors += CaptureErrors;
    capture.DevicePowerState += DevicePowerState;
    capture.Terminate += Terminate;

    ...
}

Note

The line capture.ContextForEvents = SynchronizationContext.Current; allows your application to handle the Capture Helper events directly in the User Interface (UI) Thread context so the UI can be directly updated. Setting ContextForEvents is optional, if none of the event handlers updates the UI then this line can be removed. CaptureHelper.ContextForEvents can ONLY be set on the UI thread. CaptureHelper.ContextForEvents is a public member, so it can be set at any time.

Note

For Xamarin, if the UI has to be updated in the Capture event handlers and if the System.Windows assembly is not used, it is probably best to use RunOnUiThread() and don’t specify any context for the events.

In the OnFormOpening override method of the form object proceed to open the communication between this application and Socket Mobile Companion software as shown below:

protected async override void OnFormOpening(FormOpeningEventArgs e)
{
    base.OnFormOpening(e);
    string appId = "windows:com.mycompany.myapp";
    string developerId = "520CE559-D74D-4447-9E65-0E35512A0344";
    string appKey = "MC3CFQD76T2AE/Jus4JJ6nxZJyub3WBxXgIVAKglTx239tKjR+LNspa46Y9io2w5";

    long result = await capture.OpenAsync(appId, developerId, appKey);

    if (!SktErrors.SKTSUCCESS(result))
    {
        labelCaptureVersion.Text = "Unable to connect to Socket Mobile Companion";
        DialogResult dialogResult = MessageBox.Show(
            "Unable to open Capture, is Socket Mobile Companion Service running?",
            "Error",
            MessageBoxButtons.OK,
            MessageBoxIcon.Warning);
    }
}

From that moment on, if a Socket Cordless Scanner connects to the host, the application CaptureDeviceArrival handler is invoked, and when the user then scans a barcode the CaptureDecodedData is invoked with the decoded data.

Note

For Xamarin, the websocket implementation is incomplete in the earlier version, therefore it should be disabled by adding this line capture.DoNotUseWebSocket = true; before calling the OpenAsync method.

Minimal implementation

Assuming the only thing that matters to the application is to receive the decoded data, a minimal implementation could be as simple as:

public Form1()
{
    InitializeComponent();
    // initialize CaptureHelper
    capture = new CaptureHelper();
    capture.ContextForEvents = WindowsFormsSynchronizationContext.Current;
    capture.DecodedData += CaptureDecodedData;

    string appId = "windows:com.mycompany.myapp";
    string developerId = "520CE559-D74D-4447-9E65-0E35512A0344";
    string appKey = "MC3CFQD76T2AE/Jus4JJ6nxZJyub3WBxXgIVAKglTx239tKjR+LNspa46Y9io2w5";

    long result = await capture.OpenAsync(appId, developerId, appKey);

    if (!SktErrors.SKTSUCCESS(result)) {
        labelCaptureVersion.Text = "Unable to connect to Socket Mobile Companion";
    }
}

async void CaptureDecodedData(object sender, CaptureHelper.DecodedDataArgs e)
{
    textBoxDecodedData.Text = e.DecodedData.DataToUTF8String;
}

Of course this sample won’t help the user if for some reason the scanner is not connected to the host, or if there is an error occurring while using Capture. For these reasons we highly recommend to track the device presence, to handle the error event and to collect the Capture version.

Note

The line capture.ContextForEvents = WindowsFormsSynchronizationContext.Current; allows the application to handle the Capture Helper events directly in the UI Thread context so the UI can be directly updated. If none of the event handlers updates the UI then this line can be removed.

Note

For Xamarin, if the UI has to be updated in the Capture event handlers and if the System.Windows assembly is not used, it is probably best to use RunOnUiThread() and don’t specify any context for the events.

Note

For Xamarin, the websocket implementation is incomplete in the earlier version, therefore it should be disabled by adding this line capture.DoNotUseWebSocket = true; before calling the OpenAsync method.

Device connection awareness

This is a great way to confirm if the scanner is correctly connected to the application or even to drive the UI when the scanner connects or scans. Capture Helper automatically opens the device as soon as it receives its connection notification. Once the device is open, Capture Helper fires the device arrival event with a CaptureHelperDevice instance to represent this particular device. That CaptureHelperDevice instance is used at each event related to the device, and can be used to retrieve or configure the device settings.

For an application to be aware of Device connections, there are 2 events that can be monitored: DeviceArrival and DeviceRemoval. Here is sample code on how to register for these events along with the DecodedData event. The devices are added into a ListBox in this particular case:

public Form1()
{
  InitializeComponent();
  // initialize CaptureHelper
  capture = new CaptureHelper();

  capture.ContextForEvents = WindowsFormsSynchronizationContext.Current;
  capture.DeviceArrival += CaptureDeviceArrival;
  capture.DeviceRemoval += CaptureDeviceRemoval;
  capture.DecodedData += CaptureDecodedData;

  labelStatus.Text = "no scanner connected";

  string appId = "windows:com.mycompany.myapp";
  string developerId = "520CE559-D74D-4447-9E65-0E35512A0344";
  string appKey = "MC3CFQD76T2AE/Jus4JJ6nxZJyub3WBxXgIVAKglTx239tKjR+LNspa46Y9io2w5";

  long result = await capture.OpenAsync(appId, developerId, appKey);

  if (!SktErrors.SKTSUCCESS(result)) {
      labelCaptureVersion.Text = "Unable to connect to Socket Mobile Companion (" + result + ")";
  }

}

void CaptureDeviceRemoval(object sender, CaptureHelper.DeviceArgs e)
{
    RemoveDeviceFromListBox(listBoxDevices, e.CaptureDevice);
}

void CaptureDeviceArrival(object sender, CaptureHelper.DeviceArgs e)
{
    AddDeviceIntoListBox(listBoxDevices, e.CaptureDevice);
    labelStatus.Text = e.CaptureDevice.GetDeviceInfo().Name;
}

async void CaptureDecodedData(object sender, CaptureHelper.DecodedDataArgs e)
{
    textBoxDecodedData.Text = e.DecodedData.DataToUTF8String;
}

Note

The line capture.ContextForEvents = WindowsFormsSynchronizationContext.Current; allows the application to handle the Capture Helper events directly in the UI Thread context the UI can be directly updated. If none of the event handlers updates the UI then this line can be removed.

Note

For Xamarin, if the UI has to be updated in the Capture event handlers and if the System.Windows assembly is not used, it is probably best to use RunOnUiThread() and don’t specify any context for the events.

Note

For Xamarin, the websocket implementation is incomplete in the earlier version, therefore it should be disabled by adding this line capture.DoNotUseWebSocket = true; before calling the OpenAsync method.

Adding features to Capture Helper

Capture Helper is implemented as partial class. If your application needs a feature that is not implemented in Capture Helper, that feature can be added by creating a CaptureHelper partial class, copy-pasting a similar feature from the provided CaptureHelper, and modifying it to match your application needs.

Capture Helper with Debug Traces

If the application is compiled in Debug mode it is possible to activate the traces from Capture Helper. The application should pass a Capture Debug Console object that implements the unique method void PrintLine(string message). Here is sample code showing the details of this feature by first creating a DebugConsole class (or whatever other name you pick) derived from CaptureHelperDebug as shown here:

#if DEBUG
    class DebugConsole : CaptureHelperDebug
    {

        public void PrintLine(string message)
        {
            Debug.WriteLine(message);
        }
    }
#endif

Then after creating the Capture Helper instance this DebugConsole instance is passed to the Capture Helper instance as shown here:

public Form1()
{
    InitializeComponent();
    // initialize CaptureHelper
    capture = new CaptureHelper();
#if DEBUG
    capture.DebugConsole = new DebugConsole();
#endif
    capture.ContextForEvents = WindowsFormsSynchronizationContext.Current;
    capture.DeviceArrival += CaptureDeviceArrival;
    capture.DeviceRemoval += CaptureDeviceRemoval;
    capture.DeviceOwnershipChange += CaptureDeviceOwnershipChange;
    capture.DecodedData += CaptureDecodedData;
    capture.Errors += CaptureErrors;
    capture.DevicePowerState += DevicePowerState;
    capture.Terminate += Terminate;
    ...