Basics¶
Getting the Decoded Data¶
Using Capture Helper to retrieve the decoded data from a scanner is as simple as
deriving from CaptureHelperDeviceDecodedDataDelegate
protocol and
implementing the didReceiveDecodedData
delegate.
Note
If the UI should be updated with the decoded data received, the updating code
should be in the main dispatch queue using the DipatchQueue.main.async
or
simply by settings the Capture Helper property dispatchQueue
to
DispatchQueue.main
like this: CaptureHelper.sharedInstance.dispatchQueue = DispatchQueue.main
Here is an example of such implementation for handling the decoded data with Capture Helper:
import UIKit
import SKTCapture
class MasterViewController:
UIViewController,
CaptureHelperDeviceDecodedDataDelegate {
// Capture Helper shareInstance allows to share
// the same instance of Capture Helper with the
// entire application. That static property can
// be used in any views but it is recommended
// to open only once Capture Helper (in the main
// view controller) and pushDelegate, popDelegate
// each time a new view requiring scanning capability
// is loaded or unloaded respectively.
var captureHelper = CaptureHelper.sharedInstance
@IBOutlet weak var decodedData: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// CaptureSDK requires the app to be registered on
// Socket Mobile developer portal
let appInfo = SKTAppInfo()
appInfo.appKey = "<YOUR APP KEY HERE>"
appInfo.appID = "<YOUR APP BUNDLE ID HERE>"
appInfo.developerID = "<YOUR DEVELOPER ID HERE>"
// there is a stack of delegates the last push is the
// delegate active, when a new view requiring notifications from the
// scanner, then push its delegate and pop its delegate when the
// view is done
captureHelper.pushDelegate(self)
// to make all the delegates able to update the UI without the app
// having to dispatch the UI update code, set the dispatchQueue
// property to the DispatchQueue.main
// Do the the same with the property dispatchQueue if the UI needs to
// be updated in any of the completion handlers
captureHelper.dispatchQueue = DispatchQueue.main
// open Capture Helper only once in the application by passing the
// application information (developer ID, application bundle ID and the
// AppKey coming from the application registration on Socket Mobile
// developer portal
captureHelper.openWithAppInfo(appInfo, withCompletionHandler: { (_ result: SKTResult) in
print("Result of Capture initialization: \(result.rawValue)")
})
}
#import "ViewController.h"
#import <CaptureSDK/CaptureSDK.h>
@interface ViewController () <CaptureHelperDelegate>
@property (weak, nonatomic) IBOutlet UILabel *statusLabel;
@property (weak, nonatomic) IBOutlet UITextView *decodedDataTextView;
@property (weak, nonatomic) IBOutlet UIButton *clearButton;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_decodedDataTextView.text = @"";
_decodedDataTextView.layer.borderWidth = 2;
_decodedDataTextView.layer.cornerRadius = 10;
_clearButton.layer.cornerRadius = 10;
_clearButton.layer.borderWidth = 2;
_clearButton.backgroundColor = UIColor.whiteColor;
_clearButton.layer.borderColor = UIColor.blueColor.CGColor;
[CaptureHelper.sharedInstance pushDelegate:self];
[CaptureHelper.sharedInstance openWithCompletionHandler:^(SKTResult result) {
NSLog(@"Opening Capture Helper returned: %ld", (long)result);
}];
}
@end
And the decoded data handler might look like this:
// MARK: - CaptureHelperDeviceDecodedDataDelegate
// This delegate is called each time a decoded data is read from the scanner
// It has a result field that should be checked before using the decoded
// data.
// It would be set to SKTCaptureErrors.E_CANCEL if the user taps on the
// cancel button in the SocketCam View Finder
func didReceiveDecodedData(_ decodedData: SKTCaptureDecodedData?, fromDevice device: CaptureHelperDevice, withResult result: SKTResult) {
if result == SKTCaptureErrors.E_NOERROR {
let str = decodedData?.stringFromDecodedData()!
print("Decoded Data \(String(describing: str))")
decodedData.text = str
}
}
/**
* called when decoded data are received from a device
*
* @param decodedData contains the decoded data
* @param device identifies the device from which the decoded data comes from
* @param result contains an error if something wrong happen while getting the decoded data
* or if the SocketCam trigger operation has been cancelled
*/
-(void)didReceiveDecodedData:(SKTCaptureDecodedData *)decodedData fromDevice:(CaptureHelperDevice *)device withResult:(SKTResult)result {
NSLog(@"receive decoded data: %@", [decodedData stringFromDecodedData]);
dispatch_async(dispatch_get_main_queue(), ^{
self.decodedDataTextView.text = [self.decodedDataTextView.text stringByAppendingString: [decodedData stringFromDecodedData]];
self.decodedDataTextView.text = [self.decodedDataTextView.text stringByAppendingString: @"\n"];
});
}
Note
Here the UI can be directly updated because in the Capture Helper
initialization the UI Context is passed in the dispatchQueue property
of Capture Helper: capture.dispatchQueue = DispatchQueue.main
Device Arrival¶
The Device arrival is fired when a scanner is connected to the host.
This event can be useful for several things such as:
confirming to the user the scanner is present and ready
switching to a view that is ready to receive the decoded data
checking the scanner configuration before setting its configuration
Here is an example of a Device Arrival handler:
func didNotifyArrivalForDevice(_ device: CaptureHelperDevice, withResult result:SKTResult) {
print("didNotifyArrivalForDevice")
scannerStatus.text = device.deviceInfo.name!
}
-(void)didNotifyArrivalForDevice:(CaptureHelperDevice *)device withResult:(SKTResult)result {
NSLog(@"Receive device arrival for %@", device.friendlyName);
dispatch_async(dispatch_get_main_queue(), ^{
_statusLabel.text = device.friendlyName;
});
}
Note
Here the UI can be directly updated because in the Capture Helper
initialization the UI Context is passed in the dispatchQueue property
of Capture Helper: capture.dispatchQueue = DispatchQueue.main
This assumes the View class has been derived from CaptureHelperDevicePresenceDelegate
:
import UIKit
import SKTCapture
class MasterViewController:
UIViewController,
CaptureHelperDeviceDecodedDataDelegate {
...
}
#import "ViewController.h"
#import <CaptureSDK/CaptureSDK.h>
@interface ViewController () <CaptureHelperDelegate>
@property (nonatomic) IBOutlet UILabel *statusLabel;
@end
Device Arrival for Combo devices i.e. S370¶
For a combo device like the S370 which has 2 devices, there will be two didNotifyArrivalForDevice
notifications: one for the NFC reader/writer and one for the Barcode scanner.
The following code shows how you can distinghuish and handle them with the device type:
func didNotifyArrivalForDevice(_ device: CaptureHelperDevice, withResult result: SKTResult) {
print("didNotifyArrivalForDevice: \(String(describing: device.deviceInfo.name))")
if device.deviceInfo.deviceType == .NFCS370 {
// handle the NFC reader of the S370
} else if device.deviceInfo.deviceType == .scannerS370 {
// handle the Barcode scanner of the S370
}
}
Get the Error¶
It is a good idea to be notified when an unexpected error occurs. One possible scenario where this could happen is when the user scans too many barcodes before the application has time to consume them.
Here is an example of the error event handler to display an error message in a status label in the application UI:
func didReceiveError(_ error: SKTResult) {
print("Receive a Capture error: \(error.rawValue)")
errorLabel.text = "The scanner is reporting an error: \(error.rawValue)"
}
/**
* called when a error needs to be reported to the application
*
* @param error contains the error code
* @param message contains an optional message, can be null
*/
-(void)didReceiveError:(SKTResult)error withMessage:(NSString *)message {
NSLog(@"Receive error %d from Capture: %@", error, message);
}
This delegate is defined by the CaptureHelperErrorDelegate
protocol from which
the class should derive.
Note
Here the UI can be directly updated because in the Capture Helper
initialization the UI Context is passed in the dispatchQueue property
of Capture Helper: capture.dispatchQueue = DispatchQueue.main
Getting a Device Property such as Battery Level¶
Capture Helper helps to retrieve information about a particular scanner or to configure a scanner through a Capture Helper Device object that is received in the Device Arrival event and in the DecodedData event.
This Capture Helper Device object is also received in argument of the Device Removal event but since the device is disconnected from the host, only limited operations can be done with this Capture Helper Device at this time.
Here is an example of such a command:
// ask for the Battery Level
device.getBatteryLevelWithCompletionHandler({ (result, batteryLevel) in
self.displayBatteryLevel(batteryLevel, fromDevice: device, withResult: result)
})
...
// MARK: - Utility functions
func displayBatteryLevel(_ level: UInt?, fromDevice device: CaptureHelperDevice, withResult result: SKTResult) {
if result != SKTCaptureErrors.E_NOERROR {
print("error while getting the device battery level: \(result.rawValue)")
}
else{
deviceInfo.text = "the device \((device.deviceInfo.name)! as String) has a battery level: \(String(describing: level))%"
}
}
// ask for the device Battery Level
[device getBatteryLevelWithCompletionHandler:^(SKTResult result, NSInteger levelInPercentage) {
[self displayBatteryLevel: levelInPercentage];
}];
...
#pragma mark - Utility methods
-(void)displayBatteryLevel:(NSInteger)batteryLevelInPercentage {
dispatch_async(dispatch_get_main_queue(), ^{
_statusLabel.text = [NSString stringWithFormat:@"Battery: %ld%%", (long)batteryLevelInPercentage];
});
}
With device
being defined as a CaptureHelperDevice
object.
Please refer to the other topics for more information about configuring the device or retrieving.