MediumHow to create Ionic 4 wrapper for native libraries | by Taron Qalashyan | Medium
Sitemap
Taron Qalashyan

Taron Qalashyan

How to create Ionic 4 wrapper for native libraries

5 min readJun 10, 2021

--

When you have experience in native mobile apps development and start to use Hybrid technology, the first thing you look up is the usage of native libraries. When I have started to use Ionic 4, I had a problem with the usage of some native libraries in my new Ionic 4 project. Spent a lot of time to find full instruction on how can I do it but found just separate parts of wrapper creation steps and decided to create full instruction based on some articles and my experience.

Press enter or click to view image in full size

The wrapper for Ionic 4 should have 3 layers:

  1. Native library for iOS and Android
  2. Cordova Custom Plugin which contains:
  • Native interface (swift for iOS and java for Android) to call methods from native libraries. The native interface should extend CDVPlugin class and should have the same public methods for both platforms Android and iOS.
  • JS interface to be able to call java interface methods from the Cordova-based applications.

3. Ionic 4 wrappers based on the Cordova custom plugin to be able to use the functionality of the native libraries.

Prerequisite installation

  • Plugman — npm install -g plugman
  • Cordova — npm install -g cordova
  • Ionic — npm install -g ionic@latest

Step 1 — Create Cordova Plugin

Navigate the directory we would like the plugin created, open the terminal and run this command. This command will generate all the necessary files for our plugin but we will need to add the platforms.

plugman create --plugin_id <plugin_id> --plugin_version <plugin_version> --name <plugin_name>

Replace plugin_id, version and name with your plugin parameters.
Now when we have the main structure of the plugin we can add platform support for our library. Navigate to the newly created folder and run the following commands to add Android and iOS support

Android

plugman platform add --platform_name android

iOS

plugman platform add --platform_name ios

Adding package.json and plugin details

At this point, we have already added the platform we wish to build for, we will also need to add package.json file to the plugin directory and can do by this commend, this will prompt us to enter the details

plugman createpackagejson ./

Now we have a very basic plugin inside the plugin -> src folder, but we need to add our code into the Android/iOS plugin class, we also might need to adjust the class files respectively to individual packages/folders and class names. If encounter any error during this process, please make sure your class name and packages match the plugin package correctly or change it.

Add Android Plugin Class

package package_name_change_me;// Cordova-required packages
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class plugin_name_change_me extends CordovaPlugin {@Override
public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) {
// Verify that the user sent a you action
if (!action.equals(method_name_sent_from_js_change_me)) {
callbackContext.error("\"" + action
+ "\" is not a recognizedaction.");
return false;
}
// Get properties sent from JS
String msg;
try {
JSONObject options = args.getJSONObject(0);
message = options.getString("msg");
} catch (JSONException e) {
callbackContext.error("Error encountered: "
+ e.getMessage());
return false;
}
//Add your functionality here

// Send a positive result to the callbackContext
callbackContext.success("Success");
return true;
}
}

Add iOS Plugin Class

@objc(plugin_name_change_me) class plugin_class_name_change_me :
CDVPlugin, CallbackListenerDelegate {
var callbackListener: CallbackListenerObjCImplementation!
@objc(method_name_change_me:)
func method_name_change_me(command: CDVInvokedUrlCommand) {
// Get properties sent from JS
let msg = command.arguments[0] as? String ?? "def_value"

//Add your functionality here
// Create a positive result.
pluginResult = CDVPluginResult(
status: CDVCommandStatus_OK,
messageAs: msg
)
// Send the result
self.commandDelegate!.send(pluginResult,
callbackId: command.callbackId
)
}
}

Update plugin.xml

Get Taron Qalashyan’s stories in your inbox

Join Medium for free to get updates from this writer.

Inside the plugin directory, we will find the plugin.xml for the plugin configuration

<?xml version='1.0' encoding='utf-8'?>
<plugin id="plugin_id_change_me" version="0.0.1"
xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android">
<name>plugin_name_change_me</name>
<description>plugin_description_change_me</description>
<license>MIT</license>
<keywords>cordova,android,</keywords>
<repo>plugin_repo_change_me</repo>
<issue>issue_reporting_change_me</issue>
<engines>
<engine name="cordova" version="&gt;=3.0.0" />
</engines>
<js-module name=plugin_name_change_me src="www/toastyplugin.js">
<clobbers target="plugin_target_change_me" />
</js-module>
<platform name="android">
<config-file parent="/*" target="res/xml/config.xml">
<feature name="feature_chnagem_me">
<param name="android-package" value="
java_class_pachage_change_me" />
</feature>
</config-file><framework custom="true" src="src/android/test.gradle" type="
gradleReference" />
<lib-file src="src/android/replace_me.aar" /><resource-file src="src/android/assets/svm_models.zip" target="
assets/svm_models.zip" />
<resource-file src="src/android/assets/tessdata.zip" target="
assets/tessdata.zip" />
<source-file src="java1_file_with_path_change_me" target-dir="
target_dir_path_change_me" />
<source-file src="java2_file_with_path_change_me" target-dir="
target_dir_path_change_me" />
</platform><platform name="ios">
<config-file parent="/*" target="config.xml">
<feature name="feature_chnagem_me">
<param name="ios-package" value="feature_change_me" />
</feature>
</config-file>
<config-file target="*-Info.plist" parent="
NSCameraUsageDescription">
<string>Used to scan QR code, MRZ and documents</string>
</config-file>
<source-file src="swift_file_path" /><header-file src="src/ios/lib/callbackListenerObjC.h"/><header-file src="src/ios/lib
/callbackListenerObjCImplementation.h"/>
..........
<header-file src="src/ios/lib/public_types.h"/>
<source-file src="src/ios/lib
/callbackListenerObjCImplementation.mm"/>
<source-file src="src/ios/lib/libjpeg.a" framework="true"/><source-file src="src/ios/lib/replace_me.a"
framework="true" />
<source-file src="src/ios/lib/libtiff.a" framework="true"/><framework src="QuartzCore.framework" />
<framework src="AVFoundation.framework" embed="false" />
<framework src="AudioToolbox.framework" embed="false" />
<framework src="CoreMedia.framework" embed="false" />
<framework src="libiconv.tbd"/>
<framework src="libc++.tbd"/>
<framework src="src/ios/lib/tesseract.framework" custom="true"/><framework src="src/ios/lib/leptonica/1.76.0/leptonica.
framework" embed="false" custom="true"/>
<framework src="src/ios/lib/opencv2.framework" embed="false"
custom="true"/>
<resource-file src="src/ios/lib/svm_models.zip"/>
<resource-file src="src/ios/lib/tessdata.zip"/>
</platform>
</plugin>

Update the JavaScript bridge

Inside the www directory in the plugin, we will find the JavaScript bridge for the plugin and we need to change the content of this file as well to make sure that our nativeToast part of the plugin is called

var exec = require('cordova/exec');exports.<our_method_name> = function (arg0, success, error) {
exec(success, error, 'class_name_change_me',
'method_name_change_me', [arg0]);
};

Step 2 — Create Ionic 4 Wrapper

First of all, we need to clone the repository or download and install gulp CLI

git clone https://github.com/ionic-team/ionic-native
sudo npm install --global gulp-cli
npm install

Go to the ionic-native directory and run the following command to create the template file for the Ionic 4 new plugin.

gulp plugin:create -n plugin_name_change_me

The plugin will available at src -> @ionic-native -> plugins -> plugin_name_change_me

Here is the final change for our nativeToast plugin

import { Injectable } from '@angular/core';
import { Plugin, Cordova, IonicNativePlugin } from '@ionic-native/core';
@Plugin({
pluginName: 'cordova_plugin_name_change_me',

plugin: 'cordova_plugin_pachage_change_me', // npm package name, example: cordova-plugin-camera

pluginRef: 'cordova_clobbers_target_change_me', // the variable reference to call the plugin, example: navigator.geolocation

repo: '', // the github repository URL for the plugin
platforms: ['Android', 'iOS'] // Array of platforms supported,
example: ['Android', 'iOS']
})
@Injectable()
export class native_plugin_name_change_me extends IonicNativePlugin {
@Cordova()
cordova_plugin_method_name_change_me(arg1: string,
arg2: number): Promise<any> {
return; // We add return; here to avoid any compiler errors
}
}

After all changes, we will run the following command in the root of the ionic-native directory to generate the build folder

npm run build

Step 3 — Integrate the wrapper

Install Cordova Plugin

Go to our Ionic 4 Application directory and run this command to install the plugin

cordova plugin add our_plugin_path

Install Ionic 4 Wrapper Plugin

To add the wrapper simply copy to ionic-native directory -> dist ->@ionic-native ->plugins ->plugin_name_our_project node_modules -> @ionic-native

Integration

Add the wrapper to the root module provider with the necessary imports

import { plugin_name_change_me } from '@ionic-native/plugin_name_change_me/ngx';@NgModule({
imports: [... ],
providers:[plugin_name_change_me]
})

In our component, we will call the plugin via the defined method

import { plugin_name_change_me } from '@ionic-native
/plugin_name_change_me/ngx';
....
constructor(private plugin_obj:plugin_name_change_me){}
public pluginMethodCall(){

this.plugin_obj.cordova_plugin_method_name_change_me("")
.then(r=>{
console.log('success');
}).catch((e)=>{
console.error(e);
})
}

Links

Ionic 4: https://ionicframework.com/docs
Cordova Plugin Development: https://cordova.apache.org/docs/en/10.x/guide/hybrid/plugins/

--

--