Migrating to Anyline 43.0.0

We have completed a major update to the Anyline classes in version 43. If you are coming from a previous Anyline version, it is helpful to go over some of the more significant changes in this page. For more detailed information about the classes, please head over to attachment$./documentation/index.html.

It is also worth having a look at Plugin Configuration for more specific implementation guidance.

New way to initialize the scan plugin

Initializing a scan plugin now works differently. In previous versions, to implement a scan use case you have to initialize the following classes: a scan view, a scan view plugin, and a scan plugin, the latter two of which are determined specifically based on your scanning use case, for instance AnylineOcrConfig and OcrScanViewPlugin:

Old example with Universal Serial Number
scanView = findViewById(R.id.scan_view);

AnylineOcrConfig anylineOcrConfig = new AnylineOcrConfig();

scanView.setScanConfig(jsonObject);

//init the scanViewPlugin config
OcrScanViewPlugin scanViewPlugin = new OcrScanViewPlugin(getApplicationContext(), anylineOcrConfig, scanView.getScanViewPluginConfig(), "OCR");

//init the scan view
scanView.setScanViewPlugin(scanViewPlugin);

//set the listener
scanViewPlugin.addScanResultListener((ScanResultListener<OcrScanResult>) result -> {
        Log.i(TAG, "Regex, allowed chars: result: " + result.getResult());
    });

With Anyline 43, it is now only necessary to initialize an ScanView and an ScanViewPlugin, the latter already giving rise to an appropriate ScanPlugin by passing in a configuration suitable for the use case targeted.

In addition, the scan view config is now initialized together with its scan view plugin.

New example with Universal Serial Number
binding = ActivityScanBinding.inflate(layoutInflater)
setContentView(binding.root)
scanView = binding.scanView

val jsonString = "{\"viewPluginConfig\":{" +
    "\"pluginConfig\":{" +
        "\"id\":\"UNIV_SERIAL_NR\"," +
        "\"ocrConfig\":{" +
            "\"scanMode\":\"AUTO\"," +
            "\"model\":\"USNr.any\"}," +
        "\"cancelOnResult\":true}" +
    "}" +
"}"

scanView.init(JSONObject(jsonString))

scanView.scanViewPlugin.resultReceived = Event { data ->
    Log.i(TAG, "Regex, allowed chars: result: " + data.result)
}

As you can see here, ScanViewPlugin is the only scan view plugin class used, with the details for serial number scanning being completely defined within the configuration string.

As discussed in Building Plugins Programmatically, it is possible to still create and structure Anyline components by hand, however, we strongly recommend to initialize scan view plugins using a properly-formatted JSON config file.

After initializing a ScanViewPlugin, modifying its configurations’s attributes at runtime will not affect how the plugin behaves. Indeed, most properties are now read-only.

To achieve the desired outcome, you should instead fully recreate a ScanView, ScanViewPlugin, etc, with the necessary config changes.

Composite Plugins

Nesting composite plugins is currently not supported in this version of Anyline.

The ViewPluginComposite class, which replaces the old plugin composite type AbstractScanViewPluginComposite, is now (along with ScanViewPlugin) a concrete implementation of the ViewPluginBase protocol.

This class introduces a new way to subscribe to the multiple results, that a composite can return. You can check it out under the section new listeners.

New JSON config file structure

There are also changes in the way Anyline parses JSON config files. Now, any top-level config key name should end with Config (for example, scanFeedBackConfig, flashConfig, etc).

{
    "cameraConfig": {
        ...
    },
    "flashConfig": {
        ...
    },
    "viewPluginConfig": {
        "pluginConfig": {
            ...
        },
        "cutoutConfig": {
            ...
        },
        "scanFeedbackConfig": {
            ...
        }
    }
}

Please refer to Plugin Configuration for more details.

New listeners

We’ve also made some changes to the listeners to ScanPlugin, ScanViewPlugin, and ScanView, streamlining the interface and eliminating the need to implement listeners for different use cases.

Result listeners such as OcrScanResult, LicensePlateScanResult, and so on, no longer exist in the new version and have now been replaced by a single class: ScanResult.

Old listeners
scanViewPlugin.addScanResultListener((ScanResultListener<OcrScanResult>) result -> {
    // ...
 });

scanViewPlugin.addScanResultListener((ScanResultListener<LicensePlateScanResult>) result -> {
    // ...
});
New listeners
scanView.scanViewPlugin.resultReceived = Event { data ->
    // (access license plate results or OCR results in the same way)
}

scanView.scanViewPlugin.resultsReceived = Event { data ->
    // (access license plate results or OCR results in the same way)
}

To round it up, here are the other methods from PluginCallback that provide additional information about a scanning session:

public Event<JSONObject> errorReceived;
public Event<JSONObject> visualFeedbackReceived;
public Event<JSONObject> scanInfoReceived;
public Event<JSONObject> runSkippedReceived;

In each method, the Event parameter can be examined by using the JSONObject property.

All listeners are now optional, so you can simply implement only the methods which you choose to use.

New result type

ScanResult is now structured in a way in that result types of use cases we support are now strongly-typed and are defined as part of the result object, which means that for example if you are scanning OCRs, then an ocrResult will be a non-null property that you can expect the result to be found in.

private val onResult: (ScanResult) -> Unit = {
    val ocrString = it.pluginResult.ocrResult.text
}

Check the API Documentation section for more result types.


Questions or need further assistance? Reach us at [email protected].