banner



How To Install Cordova Plugin

In this article past Hazem Saleh, author of JavaScript Mobile Application Evolution, we will keep to deep swoop into Apache Cordova. You volition acquire how to create your own custom Cordova plugin on the three virtually popular mobile platforms: Android (using the Coffee programming language), iOS (using the Objective-C programming language), and Windows Phone eight (using the C# programming language).

(For more resources related to this topic, encounter here.)

Developing a custom Cordova plugin

Earlier going into the details of the plugin, it is important to note that developing custom Cordova plugins is not a common scenario if you are developing Apache Cordova apps. This is because the Apache Cordova cadre and community custom plugins already cover many of the use cases that are needed to access a device's native functions. So, make sure of two things:

  • You are non developing a custom plugin that already exists in Apache Cordova core plugins.
  • Y'all are not developing a custom plugin whose functionality already exists in other good Apache Cordova custom plugin(south) that are adult by the Apache Cordova development community. Building plugins from scratch can consume precious time from your project; otherwise, yous can salve time by reusing one of the bachelor good custom plugins.

Another thing to note is that developing custom Cordova plugins is an advanced topic. It requires you to exist aware of the native programming languages of the mobile platforms, so make sure you accept an overview of Java, Objective-C, and C# (or at to the lowest degree i of them) earlier reading this section. This will exist helpful in understanding all the plugin development steps (plugin structuring, JavaScript interface definition, and native plugin implementation).


Now, let's outset developing our custom Cordova plugin. It tin be used in order to ship SMS messages from one of the three pop mobile platforms (Android, iOS, and Windows Telephone 8). Before we outset creating our plugin, we need to ascertain its API. The post-obit lawmaking listing shows you how to telephone call the sms.sendMessage method of our plugin, which will be used in gild to send an SMS across platforms:

var messageInfo = {
   phoneNumber: "xxxxxxxxxx",
   textMessage: "This is a exam message"
};
        
sms.sendMessage(messageInfo, office(bulletin) {
   console.log("success: " + message);
}, function(error) {
   console.log("code: " + mistake.code + ", message: " +   fault.message);
});

The sms.sendMessage method has the post-obit parameters:

  • messageInfo: This is a JSON object that contains two main attributes: phoneNumber, which represents the phone number that will receive the SMS message, and textMessage, which represents the text bulletin to be sent.
  • successCallback: This is a callback that will be called if the message is sent successfully.
  • errorCallback: This is a callback that will exist called if the message is not sent successfully. This callback receives an error object equally a parameter. The error object has code (the fault lawmaking) and bulletin (the fault message) attributes.

Using plugman

In addition to the Apache Cordova CLI utility, you can use the plugman utility in order to add or remove plugin(southward) to/from your Apache Cordova projects. However, it'due south worth mentioning that plugman is a lower-level tool that y'all can use if your Apache Cordova application follows platform-centered workflow and not cross-platform workflow. If your application follows cross-platform workflow, then Apache Cordova CLI should be your choice.

If you want your application to run on different mobile platforms (which is a common use case if you want to use Apache Cordova), it's recommend that you lot follow cross-platform workflow. Use platform-centered workflow if you want to develop your Apache Cordova application on a single platform and modify your application using the platform-specific SDK.

Likewise calculation and removing plugins to/from platform-centered workflow, the Cordova projects plugman tin also exist used:

  • To create basic scaffolding for your custom Cordova plugin
  • To add and remove a platform to/from your custom Cordova plugin
  • To add user(s) to the Cordova plugin registry (a repository that hosts the dissimilar Apache Cordova cadre and custom plugins)
  • To publish your custom Cordova plugin(s) to the Cordova plugin registry
  • To unpublish your custom plugin(southward) from the Cordova plugin registry
  • To search for plugin(south) in the Cordova plugin registry

In this department, we will utilize the plugman utility to create the bones scaffolding of our custom SMS plugin. In order to install plugman, you demand to make sure that Node.js is installed in your operating organization. And so, to install plugman, execute the following command:

> npm install -g plugman

After installing plugman, nosotros can offset generating our initial custom plugin artifacts using the plugman create command every bit follows:

> plugman create --name sms --plugin_id com.jsmobile.plugins.sms --  plugin_version 0.0.1

It is of import to annotation the following parameters:

  • –proper noun: This specifies the plugin name ( in our case, sms)
  • –plugin_id: This specifies an ID for the plugin (in our case, com.jsmobile.plugins.sms)
  • –plugin_version: This specifies the plugin version (in our case, 0.0.1)

The post-obit are the two parameters that the plugman create command tin accept as well:

  • –path: This specifies the directory path of the plugin
  • –variable: This can specify extra variables such equally author or clarification

Afterward executing the previous command, nosotros will have initial artifacts for our custom plugin. As we will be supporting multiple platforms, we can utilise the plugman platform add command. The following two commands add the Android and iOS platforms to our custom plugin:

> plugman platform add --platform_name android
> plugman platform add --platform_name ios

In guild to run the plugman platform add together command, we need to run it from the plugin directory. Unfortunately, for Windows Telephone viii platform support, we need to add it manually subsequently to our plugin.

Now, let'due south cheque the initial scaffolding of our custom plugin code. The post-obit screenshot shows the hierarchy of our initial plugin code:

JavaScript Mobile Application Development

Hierarchy of our initial plugin code

As shown in the preceding screenshot, there is one file and ii parent directories. They are as follows:

  • plugin.xml file: This contains the plugin definition.
  • src directory: This contains the plugin native implementation code for each platform. For now, it contains two subdirectories: android and ios. The android subdirectory contains sms.coffee. This represents the initial implementation of the plugin in the Android.ios subdirectory that contains sms.chiliad, which represents the initial implementation of the plugin in iOS.
  • www directory: This mainly contains the JavaScript interface of the plugin. It contains sms.js that represents the initial implementation of the JavaScript API plugin.

We will demand to edit these generated files (and may be, refactor and add new implementation files) in gild to implement our custom SMS plugin.

Plugin definition

First of all, we demand to define our plugin structure. In society to exercise and then, nosotros need to define our plugin in the plugin.xml file. The post-obit code list shows our plugin.xml code:

<?xml version='ane.0' encoding='utf-8'?>
<plugin id="com.jsmobile.plugins.sms" version="0.0.i"
        
   >
   <proper noun>sms</name>
   <description>A plugin for sending sms messages</clarification>
   <license>Apache 2.0</license>
   <keywords>cordova,plugins,sms</keywords>
        
   <js-module name="sms" src="www/sms.js">
       <clobbers target="window.sms" />
   </js-module>
        
   <platform proper name="android">
       <config-file parent="/*" target="res/xml/config.xml">
           <characteristic name="Sms">
               <param name="android-packet" value="com.jsmobile.plugins.sms.Sms" />
           </feature>
       </config-file>
        
       <config-file target="AndroidManifest.xml" parent="/manifest">
         <uses-permission android_name="android.permission.SEND_SMS" />
       </config-file>
       <source-file src="src/android/Sms.java"
                     target-dir="src/com/jsmobile/plugins/sms" />
   </platform>
   <platform name="ios">
       <config-file parent="/*" target="config.xml">
           <feature name="Sms">
               <param proper name="ios-package" value="Sms" />
           </characteristic>
       </config-file>
       <source-file src="src/ios/Sms.h" />
       <source-file src="src/ios/Sms.1000" />
        
       <framework src="MessageUI.framework" weak="truthful" />
   </platform>
        
   <platform name="wp8">
       <config-file target="config.xml" parent="/*">
           <feature proper noun="Sms">
               <param name="wp-package" value="Sms" />
           </feature>
       </config-file>
        
       <source-file src="src/wp8/Sms.cs" />
   </platform>
        
</plugin>

The plugin.xml file defines the plugin structure and contains a top-level <plugin> , which contains the following attributes:

  • /> tag mainly inserts the smsExport JavaScript object that is defined in the world wide web/sms.js file and exported using module.exports (the smsExport object volition exist illustrated in the Defining the plugin's JavaScript interface section) into the window object as window.sms. This ways that our plugin users volition exist able to access our plugin's API using the window.sms object (this will be shown in detail in the Testing our Cordova plugin section).

The <plugin> element can contain i or more <platform> element(s). The <platform> element specifies the platform-specific plugin'due south configuration. Information technology has mainly 1 attribute name that specifies the platform proper name (android, ios, wp8, bb10, wp7, and and so on). The <platform> chemical element can take the following child elements:

  • <source-file>: This chemical element represents the native platform source code that will exist installed and executed in the plugin-client project. The <source-file> element has the post-obit 2 main attributes:
    • src: This attribute represents the location of the source file relative to plugin.xml.
    • target-dir: This attribute represents the target directory (that is relative to the project root) in which the source file will exist placed when the plugin is installed in the client project. This attribute is mainly needed in a Coffee platform (Android), because a file under the x.y.z package must be placed under x/y/z directories. For iOS and Windows platforms, this parameter should be ignored.
  • <config-file>: This element represents the configuration file that volition be modified. This is required for many cases; for example, in Android, in order to send an SMS from your Android awarding, you need to modify the Android configuration file to take the permission to ship an SMS from the device. The <config-file> has two main attributes:
    • target: This attribute represents the file to be modified and the path relative to the project root.
    • parent: This aspect represents an XPath selector that references the parent of the elements to be added to the configuration file.
  • <framework>: This chemical element specifies a platform-specific framework that the plugin depends on. It mainly has the src attribute to specify the framework name and weak attribute to bespeak whether the specified framework should be weakly linked.

Giving this explanation for the <platform> element and getting dorsum to our plugin.xml file, you will notice that we have the following three <platform> elements:

  • Android (<platform proper name="android">) performs the following operations:
    • It creates a <feature> element for our SMS plugin under the root element of the res/xml/config.xml file to register our plugin in an Android project. In Android, the <feature> element's proper noun attribute represents the service name, and its "android-bundle" parameter represents the fully qualified name of the Coffee plugin class:
      <feature proper name="Sms">
         <param name="android-packet"   value="com.jsmobile.plugins.sms.Sms" />
      </feature>
    • It modifies the AndroidManifest.xml file to add the <uses-permission android_name="android.permission.SEND_SMS" /> element (to have a permission to send an SMS in an Android platform) under the <manifest> element.
    • Finally, it specifies the plugin's implementation source file, "src/android/Sms.java", and its target directory, "src/com/jsmobile/plugins/sms" (we will explore the contents of this file in the Developing the Android code section).
  • iOS (<platform name="ios">) performs the following operations:
    • It creates a <feature> chemical element for our SMS plugin under the root element of the config.xml file to register our plugin in the iOS project. In iOS, the <feature> element'due south name attribute represents the service name, and its "ios-packet" parameter represents the Objective-C plugin class proper name:
      <feature proper noun="Sms">
         <param name="ios-package" value="Sms" />
      </feature>
    • It specifies the plugin implementation source files: Sms.h (the header file) and Sms.m (the methods file). We will explore the contents of these files in the Developing the iOS code section.
    • It adds "MessageUI.framework" as a weakly linked dependency for our iOS plugin.
  • Windows Phone viii (<platform name="wp8″>) performs the post-obit operations:
    • It creates a <characteristic> chemical element for our SMS plugin under the root element of the config.xml file to register our plugin in the Windows Telephone 8 project. The <feature> element's proper name attribute represents the service name, and its "wp-package" parameter represents the C# service class name:
      <feature name="Sms">
             <param name="wp-parcel" value="Sms" />
      </characteristic>
    • Information technology specifies the plugin implementation source file, "src/wp8/Sms.cs" (nosotros will explore the contents of this file in the Developing Windows Phone eight code section).

This is all nosotros need to know in guild to understand the construction of our custom plugin; however, there are many more than attributes and elements that are not mentioned here, as we didn't apply them in our example. In order to get the complete list of attributes and elements of plugin.xml, yous tin can check out the plugin specification page in the Apache Cordova documentation at http://cordova.apache.org/docs/en/3.4.0/plugin_ref_spec.medico.html#Plugin%20Specification.

Defining the plugin's JavaScript interface

As indicated in the plugin definition file (plugin.xml), our plugin's JavaScript interface is defined in sms.js, which is located under the www directory. The following code snippet shows the sms.js file content:

var smsExport = {};
        
smsExport.sendMessage = function(messageInfo, successCallback,   errorCallback) {
   if (messageInfo == nix || typeof messageInfo !== 'object') {
       if (errorCallback) {
           errorCallback({
               code: "INVALID_INPUT",
               message: "Invalid Input"
           });
       }
        
       return;
   }
        
   var phoneNumber = messageInfo.phoneNumber;
   var textMessage = messageInfo.textMessage || "Default Text   from SMS plugin";
        
   if (! phoneNumber) {
       console.log("Missing Telephone Number");
        
       if (errorCallback) {
           errorCallback({
               code: "MISSING_PHONE_NUMBER",
               bulletin: "Missing Phone number"
           });
       }
        
       render;
   }
        
   cordova.exec(successCallback, errorCallback, "Sms",   "sendMessage", [phoneNumber, textMessage]);
};
        
module.exports = smsExport;

The smsExport object contains a unmarried method, sendMessage(messageInfo, successCallback, errorCallback). In the sendMessage method, phoneNumber and textMessage are extracted from the messageInfo object. If a phone number is not specified by the user, and so errorCallback will be called with a JSON fault object, which has a code attribute set to "MISSING_PHONE_NUMBER" and a message attribute prepare to "Missing Telephone number". Later on passing this validation, a call is performed to the cordova.exec() API in order to phone call the native code (whether it is Android, iOS, Windows Telephone eight, or any other supported platform) from Apache Cordova JavaScript.

Information technology is important to note that the cordova.exec(successCallback, errorCallback, "service", "action", [args]) API has the following parameters:

  • successCallback: This represents the success callback office that will be chosen (with whatever specified parameter(s)) if the Cordova exec call completes successfully
  • errorCallback: This represents the mistake callback function that volition be called (with whatever specified error parameter(s)) if the Cordova exec call does not complete successfully
  • "service": This represents the native service name that is mapped to a native grade using the <feature> element (in sms.js, the native service name is "Sms")
  • "action": This represents the activity name to be executed, and an action is mapped to a grade method in some platforms (in sms.js, the activeness name is "sendMessage")
  • [args]: This is an array that represents the activeness arguments (in sms.js, the activity arguments are [phoneNumber, textMessage])

Information technology is very of import to note that in cordova.exec(successCallback, errorCallback, "service", "action", [args]), the "service" parameter must lucifer the proper name of the <feature> element, which we set in our plugin.xml file in gild to call the mapped native plugin form correctly.

Finally, the smsExport object is exported using module.exports. Exercise not forget that our JavaScript module is mapped to window.sms using the <clobbers target="window.sms" /> element inside <js-module src="www/sms.js"> chemical element, which we discussed in the plugin.xml file. This means that in order to call the sendMessage method of the smsExport object from our plugin-client application, we use the sms.sendMessage() method.

Developing the Android code

As specified in our plugin.xml file's platform section for Android, the implementation of our plugin in Android is located at src/android/Sms.java. The following code snippet shows the first role of the Sms.java file:

package com.jsmobile.plugins.sms;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.PluginResult;
import org.apache.cordova.PluginResult.Status;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
        
import android.app.Action;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.telephony.SmsManager;
        
public class Sms extends CordovaPlugin {
   private static final String SMS_GENERAL_ERROR =   "SMS_GENERAL_ERROR";
   private static concluding String NO_SMS_SERVICE_AVAILABLE =   "NO_SMS_SERVICE_AVAILABLE";
   private static terminal String SMS_FEATURE_NOT_SUPPORTED =   "SMS_FEATURE_NOT_SUPPORTED";
   private static final String SENDING_SMS_ID = "SENDING_SMS";
        
   @Override
   public boolean execute(String action, JSONArray args,   CallbackContext callbackContext) throws JSONException {
       if (action.equals("sendMessage")) {
           String phoneNumber = args.getString(0);
           Cord message = args.getString(1);
        
           boolean isSupported = getActivity().getPackageManager().hasSystemFeature(PackageManager.  FEATURE_TELEPHONY);
        
           if (! isSupported) {
               JSONObject errorObject = new JSONObject();
        
               errorObject.put("lawmaking", SMS_FEATURE_NOT_SUPPORTED);
               errorObject.put("message", "SMS feature is not   supported on this device");
        
               callbackContext.sendPluginResult(new   PluginResult(Condition.ERROR, errorObject));
               return imitation;
           }
        
           this.sendSMS(phoneNumber, message, callbackContext);
        
           return true;
       }
        
       return false;
   }
        
   // Code is omitted here for simplicity ...
        
   individual Activity getActivity() {
       render this.cordova.getActivity();
   }
}

In order to create our Cordova Android plugin class, our Android plugin class must extend the CordovaPlugin class and must override one of the execute() methods of CordovaPlugin. In our Sms Java form, the execute(String activity, JSONArray args, CallbackContext callbackContext) execute method, which has the following parameters, is overridden:

  • Cord activeness: This represents the action to be performed, and it matches the specified action parameter in the cordova.exec() JavaScript API
  • JSONArray args: This represents the action arguments, and information technology matches the [args] parameter in the cordova.exec() JavaScript API
  • CallbackContext callbackContext: This represents the callback context used when calling a part back to JavaScript

In the execute() method of our Sms grade, phoneNumber and message parameters are retrieved from the args parameter. Using getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY), we can check if the device has a telephony radio with data communication back up. If the device does not accept this feature, this API returns fake, so we create errorObject of the JSONObject blazon that contains an mistake code attribute ("code") and an error message attribute ("message") that inform the plugin user that the SMS feature is not supported on this device. The plugin tells the JavaScript caller that the performance failed past calling callbackContext.sendPluginResult() and specifying a PluginResult object as a parameter (the PluginResult object'south condition is set up to Status.Mistake, and message is prepare to errorObject).

Every bit indicated in our Android implementation, in order to transport a plugin effect to JavaScript from Android, we use the callbackContext.sendPluginResult() method that specifies the PluginResult condition and bulletin. Other platforms (iOS and Windows Telephone 8) take much a similar manner.

If an Android device supports sending SMS messages, then a call to the sendSMS() private method is performed. The post-obit code snippet shows the sendSMS() code:

individual void sendSMS(Cord phoneNumber, Cord message, final   CallbackContext callbackContext) throws JSONException {
   PendingIntent sentPI =   PendingIntent.getBroadcast(getActivity(), 0, new   Intent(SENDING_SMS_ID), 0);
        
   getActivity().registerReceiver(new BroadcastReceiver() {
       @Override
       public void onReceive(Context context, Intent intent) {
           switch (getResultCode()) {
           case Activeness.RESULT_OK:
               callbackContext.sendPluginResult(new   PluginResult(Condition.OK, "SMS message is sent successfully"));
               break;
           case SmsManager.RESULT_ERROR_NO_SERVICE:
               endeavour {
                   JSONObject errorObject = new JSONObject();
        
                   errorObject.put("code", NO_SMS_SERVICE_AVAILABLE);
                   errorObject.put("message", "SMS is non sent   because no service is bachelor");
        
                    callbackContext.sendPluginResult(new   PluginResult(Status.ERROR, errorObject));
               } catch (JSONException exception) {
                   exception.printStackTrace();
               }
               break;
           default:
               attempt {
                   JSONObject errorObject = new JSONObject();
        
                   errorObject.put("lawmaking", SMS_GENERAL_ERROR);
                   errorObject.put("bulletin", "SMS full general error");
        
                   callbackContext.sendPluginResult(new   PluginResult(Condition.ERROR, errorObject));
               } take hold of (JSONException exception) {
                   exception.printStackTrace();
               }
        
                suspension;
           }
       }
   }, new IntentFilter(SENDING_SMS_ID));
        
   SmsManager sms = SmsManager.getDefault();
        
   sms.sendTextMessage(phoneNumber, null, message, sentPI, null);
}

In order to understand the sendSMS() method, let's await into the method's last two lines:

SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, message, sentPI, null);

SmsManager is an Android class that provides an API to transport text messages. Using SmsManager.getDefault() returns an object of SmsManager. In guild to send a text-based message, a call to sms.sendTextMessage() should exist performed.

The sms.sendTextMessage (String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent) method has the following parameters:

  • destinationAddress: This represents the address (phone number) to send the bulletin to.
  • scAddress: This represents the service center address. It can be gear up to naught to use the current default SMS center.
  • text: This represents the text message to exist sent.
  • sentIntent: This represents PendingIntent, which broadcasts when the message is successfully sent or failed. It can be set to null.
  • deliveryIntent: This represents PendingIntent, which broadcasts when the message is delivered to the recipient. It can exist gear up to nix.

Equally shown in the preceding code snippet, nosotros specified a destination accost (phoneNumber), a text message (message), and finally, a pending intent (sendPI) in order to listen to the message-sending status.

If y'all return to the sendSMS() code and look at it from the beginning, you will detect that sentPI is initialized by calling PendingIntent.getBroadcast(), and in society to receive the SMS-sending circulate, BroadcastReceiver is registered.

When the SMS message is sent successfully or fails, the onReceive() method of BroadcastReceiver will be called, and the resultant code tin be retrieved using getResultCode(). The upshot code can indicate:

  • Success when getResultCode() is equal to Activity.RESULT_OK. In this example, a PluginResult object is constructed with status = Status.OK and bulletin = "SMS message is sent successfully", and it is sent to the client using callbackContext.sendPluginResult().
  • Failure when getResultCode() is not equal to Activity.RESULT_OK. In this case, a PluginResult object is synthetic with status = Status.Fault and message = errorObject (which contains the fault code and error bulletin), and it is sent to the client using callbackContext.sendPluginResult().

These are the details of our SMS plugin implementation in the Android platform. Now, allow'due south motion to the iOS implementation of our plugin.

Summary

This article showed yous how to design and develop your own custom Apache Cordova plugin using JavaScript and Java for Android, Objective-C for iOS, and finally, C# for Windows Telephone 8.

Resources for Commodity:


Farther resources on this subject:

  • Edifice Mobile Apps [article]
  • Earthworks into the Architecture [article]
  • And then, what is KineticJS? [commodity]

Source: https://hub.packtpub.com/cordova-plugins/

Posted by: maberrynowely98.blogspot.com

0 Response to "How To Install Cordova Plugin"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel