In this module, we will explore how to extend the functionality of your Apache Cordova applications by integrating native code. This is particularly useful when you need to access device features that are not available through existing Cordova plugins or when you need to optimize performance for specific tasks.

Key Concepts

  1. Understanding Native Code Integration:

    • Native code refers to code written in the native programming languages of the target platforms (e.g., Java/Kotlin for Android, Swift/Objective-C for iOS).
    • Cordova allows you to call native code from JavaScript, enabling you to leverage platform-specific features.
  2. When to Use Native Code:

    • When existing plugins do not provide the required functionality.
    • When performance optimization is necessary.
    • When you need to access new or experimental features of the platform.
  3. Basic Workflow:

    • Create a custom plugin.
    • Write the native code for each platform.
    • Expose the native functionality to JavaScript.

Creating a Custom Plugin

Step-by-Step Guide

  1. Create the Plugin Structure:

    • Use the Cordova CLI to create a new plugin.
    cordova plugin create com.example.myplugin MyPlugin
    
  2. Define the Plugin Interface:

    • Edit the plugin.xml file to define the plugin's interface and specify the native code files for each platform.
  3. Implementing Native Code for Android:

    • Navigate to the src/android directory and create a Java class for your plugin.
    • Example: MyPlugin.java
    package com.example.myplugin;
    
    import org.apache.cordova.CordovaPlugin;
    import org.apache.cordova.CallbackContext;
    import org.json.JSONArray;
    import org.json.JSONException;
    
    public class MyPlugin extends CordovaPlugin {
        @Override
        public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
            if (action.equals("coolMethod")) {
                String message = args.getString(0);
                this.coolMethod(message, callbackContext);
                return true;
            }
            return false;
        }
    
        private void coolMethod(String message, CallbackContext callbackContext) {
            if (message != null && message.length() > 0) {
                callbackContext.success("Hello, " + message);
            } else {
                callbackContext.error("Expected one non-empty string argument.");
            }
        }
    }
    
  4. Implementing Native Code for iOS:

    • Navigate to the src/ios directory and create an Objective-C or Swift class for your plugin.
    • Example: MyPlugin.m
    #import <Cordova/CDV.h>
    
    @interface MyPlugin : CDVPlugin
    - (void)coolMethod:(CDVInvokedUrlCommand*)command;
    @end
    
    @implementation MyPlugin
    
    - (void)coolMethod:(CDVInvokedUrlCommand*)command {
        NSString* message = [command.arguments objectAtIndex:0];
        CDVPluginResult* pluginResult = nil;
    
        if (message != nil && [message length] > 0) {
            pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[NSString stringWithFormat:@"Hello, %@", message]];
        } else {
            pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Expected one non-empty string argument."];
        }
    
        [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
    }
    
    @end
    
  5. Exposing Native Functionality to JavaScript:

    • Create a JavaScript interface to call the native methods.
    • Example: www/MyPlugin.js
    var exec = require('cordova/exec');
    
    var MyPlugin = {
        coolMethod: function (message, successCallback, errorCallback) {
            exec(successCallback, errorCallback, 'MyPlugin', 'coolMethod', [message]);
        }
    };
    
    module.exports = MyPlugin;
    
  6. Using the Plugin in Your Cordova App:

    • Add the plugin to your Cordova project.
    cordova plugin add path/to/your/plugin
    
    • Call the plugin method from your JavaScript code.
    document.addEventListener('deviceready', function () {
        MyPlugin.coolMethod('World', function (result) {
            console.log(result); // "Hello, World"
        }, function (error) {
            console.error(error);
        });
    }, false);
    

Practical Exercise

Exercise: Create a Custom Plugin to Access Battery Level

  1. Objective: Create a custom Cordova plugin that retrieves the device's battery level.

  2. Steps:

    • Follow the steps outlined above to create a new plugin.
    • Implement the native code to access the battery level for both Android and iOS.
    • Expose the battery level functionality to JavaScript.
    • Use the plugin in a Cordova app to display the battery level.

Solution

  1. Create the Plugin Structure:

    cordova plugin create com.example.battery BatteryPlugin
    
  2. Define the Plugin Interface:

    • Edit plugin.xml to include the necessary files and permissions.
  3. Implementing Native Code for Android:

    • BatteryPlugin.java
    package com.example.battery;
    
    import org.apache.cordova.CordovaPlugin;
    import org.apache.cordova.CallbackContext;
    import org.json.JSONArray;
    import org.json.JSONException;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.os.BatteryManager;
    
    public class BatteryPlugin extends CordovaPlugin {
        @Override
        public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
            if (action.equals("getBatteryLevel")) {
                this.getBatteryLevel(callbackContext);
                return true;
            }
            return false;
        }
    
        private void getBatteryLevel(CallbackContext callbackContext) {
            IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
            Intent batteryStatus = cordova.getActivity().registerReceiver(null, ifilter);
            int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
            int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
            float batteryPct = level / (float) scale * 100;
            callbackContext.success((int) batteryPct);
        }
    }
    
  4. Implementing Native Code for iOS:

    • BatteryPlugin.m
    #import <Cordova/CDV.h>
    
    @interface BatteryPlugin : CDVPlugin
    - (void)getBatteryLevel:(CDVInvokedUrlCommand*)command;
    @end
    
    @implementation BatteryPlugin
    
    - (void)getBatteryLevel:(CDVInvokedUrlCommand*)command {
        UIDevice* device = [UIDevice currentDevice];
        device.batteryMonitoringEnabled = YES;
        float batteryLevel = device.batteryLevel * 100;
        CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:(int)batteryLevel];
        [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
    }
    
    @end
    
  5. Exposing Native Functionality to JavaScript:

    • www/BatteryPlugin.js
    var exec = require('cordova/exec');
    
    var BatteryPlugin = {
        getBatteryLevel: function (successCallback, errorCallback) {
            exec(successCallback, errorCallback, 'BatteryPlugin', 'getBatteryLevel', []);
        }
    };
    
    module.exports = BatteryPlugin;
    
  6. Using the Plugin in Your Cordova App:

    document.addEventListener('deviceready', function () {
        BatteryPlugin.getBatteryLevel(function (level) {
            console.log('Battery Level: ' + level + '%');
        }, function (error) {
            console.error(error);
        });
    }, false);
    

Summary

In this module, we learned how to extend the functionality of Apache Cordova applications by integrating native code. We covered the basic workflow of creating a custom plugin, implementing native code for both Android and iOS, and exposing the native functionality to JavaScript. By following the practical exercise, you should now be able to create your own custom plugins to access device-specific features and optimize performance.

Next, we will explore performance optimization techniques to ensure your Cordova applications run smoothly and efficiently.

© Copyright 2024. All rights reserved