Building Cordova Plugin with Windows Runtime Component

In my last article, I shared how to build WinRT component with Dynamsoft Barcode Reader C++ SDK. This article shows how to use the generated Dynamsoft.dll and Dynamsoft.winmd files in a Cordova plugin project for building Windows 10 apps.

Installation

My First Windows App with Cordova

Run VS 2017 command line tool.

Install Cordova:

npm install -g cordova

Create a new project:

cordova create test com.dynamsoft.test Test

Add windows platform:

cordova platform add windows

Build the app:

cordova build windows

You may see the following error:

c:\Prog
ram Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\Microsoft\VisualStudio\v15.0\JavaScript\Microsoft.Visual
Studio.WJProject.Default.props" was not found.

cordova windows build error

The error means you don’t have JavaScript-relevant SDK and tools installed. Open Visual Studio installer to check it.

vs2017 cordova

Creating Cordova Plugin with WinRT and Native DLLs

We can follow the official tutorial to create a basic Cordova plugin.

Here is mine:

cordova windows plugin

Note: we can use ildasm.exe, which is located under C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.2 Tools, to view .winmd files.

The package.json file is created by NPM command:

{
  "name": "cordova-windows-barcode",
  "version": "0.0.1",
  "description": "Cordova Windows barcode",
  "cordova": {
    "id": "cordova-windows-barcode",
    "platforms": [
      "windows"
    ]
  },
  "keywords": [
    "cordova",
    "barcode",
    "ecosystem:cordova",
    "cordova-windows"
  ],
  "author": "Dynamsoft",
  "license": "MIT"
}

Configure JavaScript modules, C++/WinRT component, and native DLLs in plugin.xml:

<?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" id="barcode" version="0.1.0">

    <js-module src="www/barcode.js" name="Barcode">
        <clobbers target="cordova.plugins.barcode" />
    </js-module>

    <!-- windows -->
    <platform name="windows">
        <js-module src="src/windows/barcodeProxy.js" name="BarcodeProxy">
            <merges target="" />
        </js-module>
        <resource-file src="src/windows/libs/x86/DynamsoftBarcodeReaderx86.dll" target="DynamsoftBarcodeReaderx86.dll" arch="x86" reference="true" />
        <resource-file src="src/windows/libs/x86/DynamicPdf.dll" target="DynamicPdf.dll" arch="x86" reference="true" />
        <resource-file src="src/windows/libs/x86/vcomp110.dll" target="vcomp110.dll" arch="x86" reference="true" />

        <framework src="src/windows/libs/x86/BarcodeComponent.winmd" target-dir="x86" arch="x86" custom="true"/>
        <framework src="src/windows/libs/x86/Dynamsoft.winmd" target-dir="x86" arch="x86" custom="true" implementation="src/windows/libs/x86/Dynamsoft.dll"/>
    </platform>
</plugin>

To communicate with the native platform, call cordova.exec in barcode.js:

function BarcodeReader() {
}

BarcodeReader.prototype.decodeFileStream = function(successCallback, errorCallback) {
    cordova.exec(successCallback, errorCallback, "Barcode", "decodeFileStream");
};

var barcodeReader = new BarcodeReader();

module.exports = barcodeReader;

In barcodeProxy.js, use the file picker to load image files and call decodeFileStream() to read barcodes:

cordova.commandProxy.add('Barcode', {
  decodeFileStream: function(successCallback, errorCallback) {
    var picker = new Windows.Storage.Pickers.FileOpenPicker();
    picker.ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail;
    picker.SuggestedStartLocation =
        Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
    picker.fileTypeFilter.append('.jpg');
    picker.fileTypeFilter.append('.jpeg');
    picker.fileTypeFilter.append('.png');

    picker.pickSingleFileAsync().then(function(file) {
      if (file != null) {
        Windows.Storage.FileIO.readBufferAsync(file).then(function(buffer) {
            let reader = new Dynamsoft.BarcodeReader();
            let result = reader.decodeFileStream(buffer);
            successCallback(result);
        });
      } else {
        errorCallback('Operation cancelled.');
      }
    });
  }
});

Add the plugin to your project:

cordova plugin add <local plugin path>

Specify the arch(x86 or x64) to run the app:

cordova run windows -- --arch="x86"

Unfortunately, the app fails to work when calling the native API. I debugged the app in Visual Studio, and got the exception:

Exception is about to be caught by JavaScript library code at line 15, column 13 in ms-appx-web://com.dynamsoft.test/www/plugins/barcode/src/windows/barcodeProxy.js
0x8007007e - JavaScript runtime error: The specified module could not be found.

cordova module not found

It seems to be a bug because the module is out there. After I created an empty .winmd file built with the C# template and added it as a reference, the exception was gone.

cordova windows barcode reader

References

Source Code

https://github.com/yushulx/cordova-windows-barcode