The Anyline Plugin
The Anyline SDK is based around the concept of plugins. Plugins can be brought in and configured to implement your scanning use case for your application.
This section describes how to implement and use the Anyline SDK plugins for iOS.
Overview
The examples provided here are based on a simple meter scanning use case. A more detailed discussion can be found in the next section, as well in the iOS API Reference. |
Each use case needs the following components to scan:
-
A ScanPlugin - handles image processing and the scanning functionality itself
-
A ScanViewPlugin - handles the scan view user interface and visual feedback
-
A ScanView - a UIView that holds the camera and flash components and manages the aforementioned ScanViewPlugin and ScanPlugin
Adding an Anyline Plugin to your UIViewController
The first step is to add these three main components of Anyline to your UIViewController as properties: the Scan Plugin (handling the scanning part), the Scan View Plugin (handling the UI) and the Scan View (handling camera, flash and overall communication between Anyline components).
Begin by declaring the three components as properties on your UIViewController:
// The three components of an Anyline use case
@property (nonatomic, strong) ALScanViewPlugin *scanViewPlugin;
@property (nonatomic, strong) ALScanPlugin *scanPlugin;
@property (nonatomic, strong) ALScanView *scanView;
ScanViewPlugin
Initialize the Scan View Plugin
By this time, you should already have initialized the Anyline SDK with the license key for your application. For more details, please see Initialize the Anyline SDK. |
The first component you would have to create is the Scan View Plugin, which can be done using a configuration object in JSON form, which we henceforth call a config. This config can either derive from a file included with the app bundle or a hard-coded string variable.
For a discussion on how to configure your plugins, please go to Plugin Configuration.
For the code snippet below, and the ones the follow, it is assumed that the Anyline.h header file has been included in the source code where you are using Anyline:
|
The example below shows one of the more straightforward ways that you can use to create a Scan View Plugin.
Here, JSONConfigDictionary
is formed by calling the asJSONObject
extension method on an NSString
object that
holds the plugin config in a JSON representation.
The following code is run during the viewDidLoad
part of the UIViewController:
NSString *JSONConfigString = @"{\"flashConfig\":{\"mode\":\"manual\"},\"cameraConfig\":{\"captureResolution\":\"1080p\",\"zoomGesture\":true},\"viewPluginConfig\":{\"pluginConfig\":{\"id\":\"METER\",\"meterConfig\":{\"scanMode\":\"auto_analog_digital_meter\"}}}}";
NSDictionary *JSONConfigDictionary = [JSONConfigString asJSONObject];
NSError *error;
self.scanViewPlugin = [[ALScanViewPlugin alloc] initWithJSONDictionary:JSONConfigDictionary error:&error];
if (error) {
// handle the error.
}
While creating each component, we recommend that you pass in an Note that if an error object has been passed back with a non-null value, then the object associated with the initializer was likely not successfully created, so the error object can provide some insight into the problem and potentially suggest a course of action. |
ScanPlugin
Obtain and configure the Scan Plugin
Once the Scan View Plugin is successfully created, the Scan Plugin can be readily obtained through its
associated scanPlugin
property.
self.scanPlugin = self.scanViewPlugin.scanPlugin;
self.scanPlugin.delegate = self;
The main reason you would need to have a reference to a Scan Plugin object is for you to set its delegate to this class, the UIViewController where your scanning use case resides.
Implementing the ScanPluginDelegate
Then, you would also have to declare your UIViewController as implementing the ALScanPluginDelegate
protocol:
class MyScanViewController: UIViewController <ALScanPluginDelegate>
Afterwards you will need to implement a number of methods from that protocol. This will be discussed in more detail in a subsequent section.
Just to give you a small example, you can add the following method implementation in your view controller:
- (void)scanPlugin:(ALScanPlugin *)scanPlugin resultReceived:(ALScanResult *)scanResult {
NSLog(@"the result: ", scanResult.pluginResult.meterResult.value);
}
ScanView
Lastly, you will want to instantiate a ScanView with the previously created ScanViewPlugin and a ScanViewConfig object.
Create a ScanViewConfig object
A ScanViewConfig object controls how the ScanView appears and behaves. Like the ScanViewPluginConfig before it, it is a JSON object that can be created from a JSON string:
NSError *error;
NSString *scanViewConfigJSONStr = @"{\"flashConfig\":{\"mode\":\"manual\"},\"cameraConfig\":{\"captureResolution\":\"1080p\",\"zoomGesture\":true},\"viewPluginConfig\":{\"pluginConfig\":{\"id\":\"METER\",\"meterConfig\":{\"scanMode\":\"auto_analog_digital_meter\"}}}}";
NSDictionary *scanViewConfigDictionary = [scanViewConfigJSONStr asJSONObject];
ALScanViewConfig *scanViewConfig = [[ALScanViewConfig alloc] initWithJSONDictionary:scanViewConfigDictionary error:&error];
if (error) {
// handle the error
}
Create the Scan View and add it to the view hierarchy
With the ScanViewPlugin object and the ScanViewConfig object (as well as the CGRect
frame for the view), you can now
create the ScanView object and start the camera module:
self.scanView = [[ALScanView alloc] initWithFrame:frame
scanViewPlugin:scanViewPlugin
scanViewConfig:scanViewConfig
error:&error];
if (error) {
// handle the error
}
[self.view addSubview:self.scanView];
[self.scanView startCamera];
Final steps
Once the scan view is displayed and running, the scan view plugin can be started. This will finally begin to process the frame images that are regularly supplied by the camera module.
The following call is preferably done in the viewDidAppear
part of the UIViewController:
[self.scanViewPlugin startWithError:&error];
Stopping the scan process
The scan process normally ends when the plugin manages to return a result by calling the delegate method -[scanPlugin:resultReceived:]
. You would then have an ALResult
object containing the scan results (to be
discussed later).
You can also stop scanning at any time by calling stop
on the ScanViewPlugin.
[self.scanViewPlugin stop];
Complete Source Code
The source code for the above example is shown here:
#import <Anyline/Anyline.h>
@interface ALSimpleScanViewController () <ALScanPluginDelegate>
@property (nonatomic, strong) ALScanView *scanView;
@property (nonatomic, strong) ALScanViewPlugin *scanViewPlugin;
@property (nonatomic, strong) ALScanPlugin *scanPlugin;
@property (nonatomic, readonly) NSString *scanViewConfigJSONStr;
@end
NSString * const kConfigJSONString = @"{\"cameraConfig\":{\"captureResolution\":\"1080p\",\"pictureResolution\":\"1080p\"},\"flashConfig\":{\"mode\":\"manual_on\",\"alignment\":\"top_left\"},\"viewPluginConfig\":{\"pluginConfig\":{\"id\":\"com.anyline.configs.plugin.auto-meter\",\"meterConfig\":{\"scanMode\":\"auto_analog_digital_meter\"},\"cancelOnResult\":true},\"cutoutConfig\":{\"animation\":\"fade\",\"maxWidthPercent\":\"100%\",\"maxHeightPercent\":\"100%\",\"width\":750,\"alignment\":\"top_half\",\"ratioFromSize\":{\"width\":3,\"height\":1},\"offset\":{\"x\":0,\"y\":0},\"cropOffset\":{\"x\":0,\"y\":0},\"cropPadding\":{\"x\":0,\"y\":0},\"cornerRadius\":8,\"strokeColor\":\"#8be9fd\",\"strokeWidth\":3,\"outerColor\":\"#282A36\",\"feedbackStrokeColor\":\"#0099FF\",\"outerAlpha\":0.85},\"scanFeedbackConfig\":{\"style\":\"rect\",\"visualFeedbackRedrawTimeout\":100,\"strokeWidth\":2,\"strokeColor\":\"#0099FF\",\"fillColor\":\"#220099FF\",\"beepOnResult\":true,\"vibrateOnResult\":true,\"blinkAnimationOnResult\":true}}}";
@implementation ALSimpleScanViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Step 1. Create a scan view plugin config with a JSON dictionary. You may use `asJSONObject`
// to transform the JSON string of a plugin config into a dictionary representation suitable for
// the Anyline iOS SDK.
NSDictionary *configDict = [kConfigJSONString asJSONObject];
NSError *error;
ALScanViewPluginConfig *scanViewPluginConfig = [[ALScanViewPluginConfig alloc]
initWithJSONDictionary:configDict error:&error];
if (!scanViewPluginConfig) {
if (error) {
NSLog(@"there was an error: %@", error.localizedDescription);
// handle the error.
}
return;
}
// Step 2. Create the scan view plugin using the scan view plugin config. A cutout config and a
// scan feedback config can also be included, but in this case, they are omitted, so defaults
// will be used.
//
// NOTE: creating a scan view plugin with a config from a JSON string is also possible:
// self.scanViewPlugin = [ALScanViewPluginFactory withJSONDictionary:scanViewConfigDict];
self.scanViewPlugin = [[ALScanViewPlugin alloc] initWithConfig:scanViewPluginConfig error:&error];
if (!self.scanViewPlugin) {
if (error) {
NSLog(@"there was an error: %@", error.localizedDescription);
}
return;
}
// Step 3. To get notified for the scan result, set an ALScanPluginDelegate. This property is
// owned by the scan plugin, which you can find from the scan view plugin.
self.scanPlugin = self.scanViewPlugin.scanPlugin;
self.scanPlugin.delegate = self;
// Step 4. Using the scan view plugin as parameter, create the scan view and add it to the
// view hierarchy.
self.scanView = [[ALScanView alloc] initWithFrame:CGRectZero
scanViewPlugin:self.scanViewPlugin error:&error];
if (!self.scanView) {
if (error) {
NSLog(@"there was an error: %@", error.localizedDescription);
// handle the error.
}
return;
}
[self.view addSubview:self.scanView];
self.scanView.translatesAutoresizingMaskIntoConstraints = false;
[self.scanView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor].active = YES;
[self.scanView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor].active = YES;
[self.scanView.topAnchor constraintEqualToAnchor:self.view.topAnchor].active = YES;
[self.scanView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor].active = YES;
// Step 5. Start the scan view camera, as well as the scan view plugin to start processing
// frames (in viewDidAppear:)
[self.scanView startCamera];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSError *error;
BOOL success = [self.scanViewPlugin startWithError:&error];
if (!success) {
// handle the error.
if (error) {
NSLog(@"there was an error: %@", error.localizedDescription);
}
}
}
// MARK: - ALScanPluginDelegate
- (void)scanPlugin:(ALScanPlugin *)scanPlugin resultReceived:(ALScanResult *)scanResult {
NSLog(@"Scan Result: %@", scanResult.pluginResult.meterResult.value);
}
@end
Questions or need further assistance? Reach us at [email protected].