Plugin Configuration

The Anyline SDK offers a wide range of scanning capabilities covering use cases for ID, License Plate, Barcode, Meter, and so on. Here we discuss how to implement a scanning use case with the Anyline SDK for iOS.

It is possible to configure the scanning behavior either through a JSON configuration or via code. We’ll cover both in this section.

The Configuration object and JSON

A configuration (or config) determines how Anyline components such as a ScanPlugin, ViewPlugin, or ScanView appears or operates. Each of these components can be initialized with a corresponding config object, for instance:

  • An ALScanViewConfig configures an ALScanView,

  • An ALViewPluginConfig configures an ALScanViewPlugin, and

  • An ALPluginConfig configures an ALScanPlugin, and so on.

To initialize a config object, pass a JSON representation of its structure as a parameter in its initializer.

For an in-depth guide on how to structure your configurations through JSON, please refer to Anyline View Configuration.

To give an example, let’s take the ALPluginConfig SDK class:

  • Swift

  • Objective-C

class ALPluginConfig {
  var identifier: String
  var cancelOnResult: NSNumber?
  var startScanDelay: NSNumber?
  var meterConfig: ALMeterConfig?
  // ...
}
@interface ALPluginConfig : NSObject

@property (nonatomic, copy)             NSString *identifier;
@property (nonatomic, nullable, strong) NSNumber *cancelOnResult;
@property (nonatomic, nullable, strong) NSNumber *startScanDelay;

@property (nonatomic, nullable, strong) ALMeterConfig *meterConfig;
// ...

@end

ALPluginConfig includes an identifier string for the plugin, as well as configuration details for all possible use cases supported by Anyline. An example of such a use case, Meter Scanning, can be traced back to a property named meterConfig under ALPluginConfig, the interface of which looks like the following:

  • Swift

  • Objective-C

class ALMeterConfig {
  var scanMode: ALMeterConfigScanMode
}
@interface ALMeterConfig : NSObject

@property (nonatomic, assign) ALMeterConfigScanMode *scanMode;

@end

So in order to construct an Anyline component or its config object, the typical approach is to prepare a JSON string or dictionary matching the required structure for your use case (for the correct structure, consult the schema), and then create the Anyline component or config object using initializer methods that accept the JSON as a parameter:

  • Swift

  • Objective-C

// dictionary describing a config for a
// dial meter-based scanning use case
let JSONDictionary: [String: Any] = [
    "id": "dial-meter-config",
    "meterConfig": [
        "scanMode": "dial_meter",
    ]
]

// create the PluginConfig with the JSON dictionary
let pluginConfig = try ALPluginConfig.withJSONDictionary(JSONDictionary)

// create the ScanPlugin with the PluginConfig
let scanPlugin = try ALScanPlugin(config: pluginConfig)
// dictionary describing a config for a
// dial meter-based scanning use case
NSDictionary *JSONDictionary = @{
    @"id": @"dial-meter-config",
    @"meterConfig": @{
        @"scanMode": @"dial_meter",
    }
};

NSError *error;

// create the PluginConfig with the JSON dictionary
ALPluginConfig *config = [ALPluginConfig withJSONDictionary:JSONDictionary error:&error];

// create the ScanPlugin with the PluginConfig
ALScanPlugin *scanPlugin = [[ALScanPlugin alloc] initWithConfig:config error:&error];

When creating components or configs, error handling is optional, but we recommend you utilize this feature in order to be in control over the Anyline scanning setup.

Any validation issues found while deserializing a JSON would be included in the error object.

Configs

PluginConfig

A PluginConfig determines, among other things, the scanning use case and essential characteristics of an Anyline plugin’s scanning behavior. Its main purpose is to be used to initialize an ALScanPlugin object, whose constructor can take this config object as a parameter.

An ALPluginConfig object may also offer further customization possibilities to handle specific uses cases.

It is perhaps easier to see this config object through its JSON representation (which can also be obtained via the asJSONString method or its equivalents). Here we give one such representation of a scan plugin config designed to scan electric meters:

{
  "id": "METER",
  "meterConfig": {
    "scanMode": "auto_analog_digital_meter"
  }
}

From the JSON above, one can see that the PluginConfig consists of a property named meterConfig, which furthermore indicates that it is going to be run with the auto_analog_digital_meter mode, allowing it to more effectively detect a specific class of electric meters.

For additional details regarding plugin configs, check ALScanViewConfig.h.

To initialize a ScanPlugin, pass a dictionary based on the JSON config object above:

  • Swift

  • Objective-C

do {
  let scanPlugin = try ALScanPlugin(jsonDictionary: configDict)
} catch {
  // handle the error object
}
ALScanPlugin *scanPlugin = [[ALScanPlugin alloc] initWithJSONDictionary:configDict error:&error];

or with an ALPluginConfig object (which is essentially formed using the same configDict object) which you subsequently pass as a parameter to the ALScanPlugin initializer:

  • Swift

  • Objective-C

do {
  let pluginConfig = try ALPluginConfig.withJSONDictionary(configDict)

  // check error to see if you can safely proceed with the next operation
  let scanPlugin = try ALScanPlugin(config: pluginConfig)
} catch {
  // handle the error object
}
ALPluginConfig *pluginConfig = [ALPluginConfig withJSONDictionary:configDict error:&error];

// check error to see if you can safely proceed with the next operation
ALScanPlugin *scanPlugin = [[ALScanPlugin alloc] initWithConfig:pluginConfig];

ViewPluginConfig

A ViewPluginConfig is an aggregate config structure that holds a PluginConfig, a CutoutConfig, and a ScanFeedbackConfig:

  • The PluginConfig, as discussed in the previous section, determines the use case and scanning behavior of the plugin.

  • A CutoutConfig includes details about the camera view cutout to be displayed on the scan view, including where it lies within the scan view, or how much space the cutout region occupies.

  • A ScanFeedbackConfig holds properties to help you configure how the objects of interest positioned within the camera cutout are visually treated, and what happens when a scan result is found.

An example JSON representation of a ScanViewPluginConfig is shown below for the meter use case:

{
    "pluginConfig": {
        "id": "METER",
        "meterConfig": {
            "scanMode": "auto_analog_digital_meter"
        },
        "cancelOnResult": true
    },
    "cutoutConfig": {
        "maxWidthPercent": "75%",
        "maxHeightPercent": "90%",
        "ratioFromSize": { "width": 7, "height": 3 },
        "cornerRadius": 8,
        "strokeColor": "#8be9fd",
        "strokeWidth": 3
    },
    "scanFeedbackConfig": {
        "style": "rect",
        "strokeWidth": 2,
        "strokeColor": "#0099FF",
        "fillColor": "#220099FF",
        "beepOnResult": true,
        "vibrateOnResult": true,
        "blinkAnimationOnResult": true
    }
}

To create a ScanViewPluginConfig, prepare an NSDictionary from a JSON object like the one above, and then pass it as a parameter to its initializer:

  • Swift

  • Objective-C

do {
  let scanViewPluginConfig = try ALScanViewPluginConfig.withJSONDictionary(configDict)
  let scanViewPlugin = try ALScanViewPlugin(config: scanViewPluginConfig)
} catch {
  // handle the error object
}
ALScanViewPluginConfig *scanViewPluginConfig = [ALScanViewPluginConfig withJSONDictionary:configDictionary
                                                                                    error:&error];
ALScanViewPlugin *scanViewPlugin = [[ALScanViewPlugin alloc] initWithConfig:scanViewPluginConfig error:&error];
When creating an ALScanViewPlugin in this way, a corresponding ScanPlugin is also automatically created (based on the details found within pluginConfig node of the JSON) and becomes part of the ScanViewPlugin.

ScanViewConfig

An ALScanViewConfig, which is the root Anyline config object, contains configuration details controlling the camera and flash (torch) modules of the ScanView, as well as the ViewPluginConfig (or ViewPluginCompositeConfig). You can initialize an ALScanView with an instance of an ALScanViewConfig.

An aggregated example of the configs in JSON form can look like the following:

{
  "cameraConfig": {
    "captureResolution": "1080p"
  },
  "flashConfig": {
    "mode": "manual",
    "alignment": "bottom_left",
    "offset": { "x": 0, "y": -40 }
  },
  "viewPluginConfig": {
    "pluginConfig": { ... },
    "scanFeedbackConfig": { ... }
  }
}

Construct an ALScanViewConfig with a JSON string or dictionary as follows:

  • Swift

  • Objective-C

do {
  let scanViewConfig = try ALScanViewConfig.withJSONDictionary(JSONDict)
  let scanView = try ALScanView(frame: frame, scanViewConfig: scanViewConfig)
} catch {
  // handle errors
}
ALScanViewConfig *scanViewConfig = [ALScanViewConfig withJSONDictionary:JSONDict error:&error];
// check error

ALScanView *scanView = [[ALScanView alloc] initWithFrame:frame
                                          scanViewConfig:scanViewConfig
                                                   error:&error];
// check error

CameraConfig and FlashConfig

The FlashConfig allows you to configure the torch module, which can include the visibility and location of the flash toggle button within the scan view. You can also set a custom image to be used in the torch toggle view.

The CameraConfig defines a few properties determining the properties of the camera module in use by Anyline.

It is possible to create ALCameraConfig and ALFlashConfig individually, if needed. Each of the two config objects can be used to customize an ALScanViewConfig.

  • Swift

  • Objective-C

do {
  let scanViewConfig = try ALScanViewConfig.withJSONDictionary(scanViewJSONConfig)
  // use camera and flash configs from separate JSON sources
  scanViewConfig.cameraConfig = try ALCameraConfig.withJSONDictionary(cameraJSONConfig)
  scanViewConfig.flashConfig = try ALFlashConfig.withJSONDictionary(flashJSONConfig)
} catch {
  // handle errors
}
// NOTE: check error object at each step
ALScanViewConfig *scanViewConfig = [ALScanViewConfig withJSONDictionary:configJSONDictionary error:&error];

scanViewConfig.cameraConfig = [ALCameraConfig withJSONDictionary:cameraJSONConfig error:&error];
scanViewConfig.flashConfig = [ALFlashConfig withJSONDictionary:flashJSONConfig error:&error];

Questions or need further assistance? Please reach out to the Anyline Support Helpdesk.