Using web standards and JavaScript to build a native app may have its limitations because apps developed using native code can interact deeply with the operating system. This is only partially true when dealing with PhoneGap apps because its architecture allows developers to extend the framework capabilities with the help of custom plugins.
In this chapter you will:
In order to be productive quickly with PhoneGap plugins, it's important to keep in mind how the framework works. A PhoneGap app consists of three main layers:
The user interface and the business logic are the app's main source code and are the parts on which most developers concentrate their development efforts. The custom plugins are strictly integrated in the framework and are exposed to the user through JavaScript. PhoneGap provides a callback architecture that allows a developer to design a custom plugin and extend its functionalities. You can imagine a plugin as an additional component of the framework that works like all the PhoneGap APIs: it acts as a bridge between the WebView and the native platform on which the app is running.
When you plan to write a custom plugin, keep in mind that you have to write the native code from scratch for all the platforms you want to support. Before starting to write a plugin you should check if what you are searching for has been implemented already at https://github.com/phonegap/phonegap-plugins. This repository is not a comprehensive list but the community around PhoneGap is working hard to keep it up-to-date.
In order to use the features implemented in a custom plugin, you have to install it in your project. Depending on the target platform this involves different steps; most of the time, however, the accompanying readme.md
file available in the plugin repository will help.
When working on the Android platform the first step is to copy the plugin source code to the platforms/android/src
folder of the project and register the plugin by adding it to the config.xml
file stored in the folder platforms/android/res/xml
. The config.xml
file contains several other settings and all the plugins, as an XML node that indicates the name and the package of the plugin:
<plugin name='HelloWorld' value='com.gnstudio.pg.HelloWorld' />
Depending on the type of the plugin, you should also update the app permissions in the platforms/android/AndroidManifest.xml
file. For instance, when using a plugin that is able to send SMS you have to explicitly grant permission to the app adding the following XML node to the AndroidManifest.xml
file:
<uses-permission android:name="android.permission.SEND_SMS"/>
In order to add a plugin to the iOS platform, manually copy the plugin source code (the .h
and .m
files only) to the Xcode project by dragging the files on the plugins folder you find in the Xcode project navigator. When you drop the files, a dialog box pops up; check the option to copy the files into the destination group.
When working with the Windows Phone 8 platform, it's enough to add the source code to the platforms/windows/plugins
folder and add the plugin to the config.xml
file stored in the platforms/windows
folder.
It's not an easy task to manually manage the plugins in a PhoneGap project; thankfully there is a command-line tool that makes your life easier.
The
Apache Cordova Plugman project http://github.com/apache/cordova-plugman is an open source command-line utility distributed as an npm
module to facilitate the installation and uninstallation of plugins. Plugman supports the Android BlackBerry 10 and iOS platforms. The installation process is the same as any other npm
module; remember that if you install it globally (using the -g
option) you have to run the command as root:
$ npm install plugman -g
Once installed, you can use several commands from your command-line tool to get the source code of a plugin, install and uninstall it, and package the plugin to be distributed with your app (plugman is part of the cordova-cli tool, you don't have to install it if you are already using it).
--fetch
, retrieves a plugin from a directory, a Git repository, or by name into the specified plugins directory.$ plugman --fetch https: //github.com/phonegap-build/GAPlugin.git --plugins_dir PATH_TO_YOUR_PLUGINS_DIR
--install
, installs a plugin for a specific target platform in a PhoneGap project. The plugin can be installed by name or by URL.--uninstall
, uninstalls by name a previously installed plugin.$ plugman --uninstall --platform android --project PLATFORM_PROJECT_PATH --plugin PLUGIN_NAME
--list
, lists all the plugins previously fetched using Plugman.--prepare
, sets up the plugin, properly injecting the needed JavaScript files and defining the appropriate permissions. The --prepare
command is implicitly called when you install or uninstall a plugin.Plugman is integrated into the Cordova command-line tool so that you can achieve similar results using the plugin add
, plugin remove
, and plugin list
commands. In order to add a plugin to your project, it's enough to run the add
command from your project
folder specifying the path to the plugin. The plugin source files are then copied to the plugins folder.
$ cordova plugin add PATH_TO_THE_PLUGIN
In order to add the plugin to a target platform, you can run the compile
command or the prepare
command.
When using Plugman as a standalone utility you can specify variables at install time using the --variable
argument. Such variables are necessary for plugins requiring API keys or other custom, user-defined parameters.
A PhoneGap plugin is a bridge between the WebView and the native platform the app is running on. Plugins are composed of a single JavaScript interface used across all platforms and native implementations following platform-specific plugin interfaces that the JavaScript will call into. There are no restrictions about how to develop the JavaScript interface. The only mandatory implementation is the way to communicate between JavaScript and the native environment using the
cordova.exec
function.
var arguments = [/* Optional arguments will go here */]; cordova.exec(onSuccess, onError, 'ClassName', 'method', arguments);
The cordova.exec
function accepts as arguments a success handler, a failure handler, the name of the native class (i.e., the name specified in the config.xml
file previously mentioned), the method to call, and an array with the arguments required by the native code. The success and failure handlers will get back as arguments the parameters returned by the native code.
When working with Android as the target platform, you have to be familiar with Java to write a custom plugin. A PhoneGap plugin in fact has to extend the CordovaPlugin
class and override the execute
method.
@Override public boolean execute(String action, JSONArray args, CallbackContext callback) { // The calls to private methods will be defined here return false; }
This method accepts the following three arguments:
action
, a string used in order to understand in the native code how to handle the request.args
, an ordered sequence of values (i.e., a Java JSONArray http://www.json.org/javadoc/org/json/JSONArray.html
).callback
, an instance of the org.apache.cordova.api.CallbackContext
class to use in order to call the success and the failure handlers. It's using the callback
argument that you will be able to execute functions inside your JavaScript.When working with iOS as the target platform, you have to be familiar with Objective-C to write a custom plugin. The native part of your plugin will consist of at least two files: a header file (i.e., a .h
file) and a source file (a .m
file) which together implement the logic you need. These two files together define a class in Objective-C; more information about Objective-C is available in the online reference at http://developer.apple.com/library/ios/#referencelibrary/GettingStarted/Learning_Objective-C_A_Primer/.
The plugin interface extends the Cordova CDV.h
interface and contains the definition of all the public methods you can call from JavaScript.
#import <Cordova/CDV.h> @interface MyPluginClass : CDVPlugin - (void)someMethod:(CDVInvokedUrlCommand*)command; @end
The implementation of the interface completes the class definition in Objective-C and contains the native code that will be executed though the JavaScript layer.
#import 'Plugin.h' #import 'AppDelegate.h' @implementation MyPluginClass - (void)someMethod:(CDVInvokedUrlCommand *)command{ NSLog(@'YOU ARE READING THIS NATIVELY FROM A PLUGIN'), } @end
When Windows Phone 8 is your target platform, you have to be familiar with C# to create a custom plugin. In fact, the plugin is a C# class that extends the Cordova BaseCommand
class and implements the public methods that can be executed though the JavaScript layer.
using WPCordovaClassLib.Cordova; using WPCordovaClassLib.Cordova.Commands; using WPCordovaClassLib.Cordova.JSON; public class Echo: BaseCommand{ public void echo(string options) { // The native code to be executed will go here } }
Regardless of the native target platform, it's a good habit to organize the source code of a custom plugin following a precise pattern. The contributors of the Plugman project suggest using a folder structure as follows:
|-plugin.xml |---src | |---android | | |-CustomPlugin.java | |---ios | | |-CustomPlugin.h | | |-CustomPlugin.m | |---windows | |-CustomPlugin.cs |-README.md |---www |-customplugin.js |-plugin.png
The plugin.xml
file is the manifest of the plugin; it's where a developer can specify the name of the plugin, the versions of PhoneGap supported by the plugin, the assets to copy in the www
directory of the PhoneGap project during the installation, the supported platforms, and so on. All this information will be used when installing a plugin using the available command-line tools; if you are interested in a complete list of tags allowed in the config.xml
file, refer to the online documentation at https://github.com/apache/cordova-plugman.
A good plugin is always distributed with a very well-organized JavaScript interface. Take a look at the example at https://github.com/shazron/KeychainPlugin/blob/master/www/keychain.js, which exposes the plugin API with a JavaScript object and the prototype
property.
3.145.77.114