So, what’s in a plugin anyway? Plugins consist of several things:

Aside from the metadata, everything else is optional — you should only include what you need in order to make your plugin function as desired. If you don’t need JavaScript code, don’t include it. If you aren’t using hooks, then you don’t need those either. Although documentation and tests aren’t required, both are highly suggested as they can help the user better understand your plugin, and provide your user with some assurance that the plugin will work correctly.

A plugin is typically structured as follows:

Plugin Structure Description
cordova-plugin-your-plugin/ Plugin root
   package.json npm metadata
   plugin.xml Plugin metadata and configuration
   README.md English documentation
   doc/locale Documentation other than English
   tests/ Please add tests!
   types/ TypeScript typings
   src/platform Platform-specific native code
     android/ Native Android code
       YourPlugin.java  
     ios/ Native iOS code
       CDVYourPlugin.h  
       CDVYourPlugin.m  
   www/ JavaScript code & web assets
     yourPlugin.js API for JavaScript consumers

Note: the structure above is representational. For a good example, see the Device Plugin.

When providing documentation, the convention is to provide the English translation in README.md in your plugin’s root directory. Other translations go in docs/[local]/README.md. Be sure to provide examples, constants, errors that can be thrown, etc. so that the user has an idea how to properly utilize your plugin.

Metadata

Metadata controls a lot of aspects of your plugin, including how people find your plugin, but also how your plugin is configured, and how it affects your consumer’s app. There are two types of metadata:

Descriptive metadata

Descriptive metadata includes things like the name of the plugin, the version, the repository where it is located, and so on. In plugin.xml, an example looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android"
  id="cordova-plugin-device" version="1.1.5-dev">
  <name>Device</name>
  <description>Cordova Device Plugin</description>
  <license>Apache 2.0</license>
  <keywords>cordova,device</keywords>
  <repo>https://git-wip-us.apache.org/repos/asf/cordova-plugin-device.git</repo>
  <issue>https://issues.apache.org/jira/browse/CB/component/12320648</issue>

Note: The complete plugin metadata used in this section is from the Device Plugin’s Metadata.

The equivalent package.json metadata looks like this:

{
  "name": "cordova-plugin-device",
  "author": "Apache Software Foundation",
  "license": "Apache-2.0",
  "version": "1.1.5-dev",
  "description": "Cordova Device Plugin",
  "types": "./types/index.d.ts",
  "cordova": {
    "id": "cordova-plugin-device",
    "platforms": ["android", "ios", "windows", "wp8", ... ] },
  "repository": { "type": "git", "url": "https://..." },
  "keywords": ["cordova", "device", "ecosystem:cordova", "cordova-ios", "cordova-android", ... ],

Note: The sample is from the Device Plugin’s package.json file.

Tip: You’ll want to specify what platforms are supported in your plugin using the cordova.platforms key — this is used by the Cordova plugin search page to indicate what platforms your plugin supports.

Asset and code metadata

With the preamble out of the way, the plugin’s metadata typically moves on to defining the JavaScript entry point, native code files, and other assets.

JavaScript modules

Typically run-time plugins will provide some sort of JavaScript API that the consumer’s app can interact with. This isn’t a hard-and-fast rule, however, since some plugins can operate independently and don’t return data to the app’s webview. (docs)

To specify a module, the following pattern is used (note the path to the source file, and a unique name for the file):

<js-module src="www/device.js" name="device">
  [<children/>]
</js-module>

You can then replace [<children/>] with any of the following, depending upon your API’s needs:

Children Description
<clobbers target="device" /> overwrites window.device
<merges target="device" /> merges with window.device
<runs /> runs, but doesn’t export

It is important to point out that by specifying one or more JavaScript modules, references will be automatically injected into your consumer’s index.html file.

Tip: Unless necessary, target cordova.plugins.yourPlugin. Polyfills and implementations of standards are example exceptions.

Assets and native code

Run-time plugins will also often provide native code and other assets (such as images and such). Because these are often platform-specific and we don’t want to copy unnecessary files to each platform, <platform> tags are used to indicate which assets go to which platforms. (docs)

Here’s an example:

<platform name="android">
  <source-file src="src/android/Device.java" target-dir="src/org/apache/cordova/device" />
</platform>
<platform name="ios">
    <header-file src="src/ios/CDVDevice.h" />
    <source-file src="src/ios/CDVDevice.m" />
    <framework src="libz.tbd" />
</platform>

Note: the above example comes from the Device Plugin plugin metadata.

There are several additional tags that you can use: <asset>, <resource-file>, and lib-file. See the docs for the low-down.

Tip: You can include third-party libraries: iOS supports Cocoapods, and Android supports AARs with Gradle.

Bug: On iOS hidden (dot) files may not be copied. See CB-10135

Plugin class mapping

The plugin metadata also maps calls from your JavaScript APIs to your native code, like so:

Tip: Use <param name="onload" value="true" /> to initialize your plugin at startup — use only if necessary

Manifest modifications

Often times you’ll need to modify the consumer app’s configuration files. Sometimes this will be the app’s config.xml file, but other times you may need to modify a plist or AndroidManifest.xml file.

There are two types of modifications: insertion of elements to the manifest via config-file, or additions of attributes to existing elements via edit-config. For example:

Dependencies

Sometimes you’ll need to specify dependencies for a plugin as well. This can be done in one of two ways: using plugin.xml or using package.json (preferred since 6.1.0).

Using plugin.xml:

Using package.json (docs):

"engines": {
  "cordovaDependencies": {
    "2.0.0": { // plugin version (applies to any ver 2+)
      "cordova-plugin-console": ">1.0.0",
      "cordova": ">6.0.0" // cordova-cli above version 6
    }
  }
}

What about the rest?

Well, sometimes it helps to actually see everything in action. So, we’re going to create an actual plugin in the next step, and you’ll be able to see how we put everything together.


Navigation: