# Apache Cordova Documentation

# BlackBerry 10 Plugins

This section provides details for how to implement native plugin code on the BlackBerry 10 platform. Before reading this, see Application Plugins for an overview of the plugin's structure and its common JavaScript interface. This section continues to demonstrate the sample echo plugin that communicates from the Cordova webview to the native platform and back.

The Echo plugin basically returns whatever string the `window.echo` function sends from JavaScript:

        window.echo = function(str, callback) {
            cordova.exec(callback, function(err) {
                callback('Nothing to echo.');
            }, "Echo", "echo", [str]);
        };

A Cordova plugin for BlackBerry 10 contains both JavaScript and native code, which communicate with each other through a framework provided by JNEXT. Every plugin must also include a `plugin.xml` file.

## Creating the Native Class

To create the native portion of your plugin, open the BlackBerry 10 NDK IDE and select File → New → BlackBerry Project → Native Extension → BlackBerry 10. Enter the desired project name and location, then press Finish.

The project created by the IDE contains sample code for a memory plugin. You may replace or modify these files to implement your own functionality:

- `*name*_js.hpp`: C++ header for the JNEXT code.

- `*name*_js.cpp`: C++ code for JNEXT.

The native interface for the JNEXT extension can be viewed in the plugin header file located in the project's public directory. It also features constants and utility functions available from within native code. The plugin must be derived from `JSExt`, which is defined in `plugin.h`. That is, you must implement the following class:

        class JSExt
        {
        public:
            virtual ~JSExt() {};
            virtual string InvokeMethod( const string& strCommand ) = 0;
            virtual bool CanDelete( void ) = 0;
        private:
            std::string m_id;
        };

The extension should include the `plugin.h` header file. In the `Echo` example, you use `JSExt` as follows in the `echo_js.hpp` file:

        #include "../public/plugin.h"
        #include <string>

        #ifndef ECHO_JS_H_
        #define ECHO_JS_H_

        class Echo : public JSExt
        {
        public:
            explicit Echo(const std::string& id);
            virtual ~Echo();
            virtual std::string InvokeMethod(const std::string& command);
            virtual bool CanDelete();
        private:
            std::string m_id;
        };

        #endif // ECHO_JS_H_

The `m_id` attribute contains the `JNEXT` id for the object, which is passed to the class as an argument to the constructor. It is needed for the native side to trigger events on the JavaScript side. The `CanDelete` method determines whether the native object can be deleted. The `InvokeMethod` function is called as a result from a request from JavaScript to invoke a method of this particular object. The only argument to this function is a string passed from JavaScript that this method parses to determine which of the native object's methods should execute. These methods are implemented in `echo_js.cpp`. Here is the `InvokeMethod` function for the `Echo` example:

        string Echo::InvokeMethod(const string& command) {

            //parse command and args from string
            int index = command.find_first_of(" ");
            string strCommand = command.substr(0, index);
            string strValue = command.substr(index + 1, command.length());

            // Determine which function should be executed
            if (strCommand == "echo") {
                return strValue;
            } else {
                return "Unsupported Method";
            }
        }

The native plugin must also implement the following callback functions:

- `extern char* onGetObjList( void );`

- `extern JSExt* onCreateObject( const string& strClassName, const string& strObjId );`

The `onGetObjList` function returns a comma-separated list of classes supported by JNEXT. JNEXT uses this function to determine the set of classes that JNEXT can instantiate. The `Echo` plugin implements the following in `echo_js.cpp`:

        char* onGetObjList() {
            static char name[] = "Echo";
            return name;
        }

The `onCreateObject` function takes two parameters. The first is the name of the requested class to be created from the JavaScript side, with valid names as those returned in `onGetObjList`. The second parameter is the class's unique object id. This method returns a pointer to the created plugin object. The `Echo` plugin implements the following in `echo_js.cpp`:

        JSExt* onCreateObject(const string& className, const string& id) {
            if (className == "Echo") {
                return new Echo(id);
            }
            return NULL;
        }

## Creating the Plugin's JavaScript

The plugin must contain the following JavaScript files:

- `client.js`: This is considered the client side and contains the API available to a Cordova application. The API in `client.js` calls makes calls to `index.js`. The API in `client.js` also connects callback functions to the events that fire the callbacks.

- `index.js`: Cordova loads `index.js` and makes it accessible through the cordova.exec bridge. The `client.js` file makes calls to the API in the `index.js` file, which in turn makes call to JNEXT to communicate with the native side.

The client and server side (`client.js` and `index.js`) interacts through the `Cordova.exec` function. The `client.js` needs to invoke the `exec` function and provide the necessary arguments. The `Echo` plugin implements the following in the `client.js` file:

        var service = "org.apache.cordova.blackberry.echo",
            exec = cordova.require("cordova/exec");

        module.exports = {
            echo: function (data, success, fail) {
                exec(success, fail, service, "echo", { data: data });
            }
        };

The `index.js` component uses JNEXT to interact with the native side. Attaching a constructor function named `Echo` to JNEXT allows you to perform the following key operations using the `init` function:

- Specify the required module exported by the native side. The name of the required module must match the name of a shared library file (`.so` file):

      JNEXT.require("libecho")

- Create an object by using an acquired module and save the ID that's returned by the call:

      self.m_id = JNEXT.createObject("libecho.Echo");

  When the application calls the `echo` function in `client.js`, that call in turn calls the `echo` function in `index.js`, where the `PluginResult` object sends data as a response back to `client.js`. Since the `args` argument passed into the functions was converted by `JSON.stringfy()` and encoded as a `URIcomponent`, you must call the following:

      data = JSON.parse(decodeURIComponent(args.data));

You can now send the data back, as in the following:

        module.exports = {
            echo: function (success, fail, args, env) {
                var result = new PluginResult(args, env),
                data = JSON.parse(decodeURIComponent(args.data)),
                response = echo.getInstance().echo(data);
                result.ok(response, false);
            }
        };

## Plugin Architecture

You can place the plugin's artifacts, including the `plugin.xml` file, the JavaScript and C++ source files, and the `.so` binary files within any directory structure, as long as you correctly specify the file locations in the `plugin.xml` file. Here is a typical structure:

project_directory (>plugin.xml)

- www (>client.js)
- src
  - blackberry10 (>index.js, native >*.cpp, *.hpp)
  - device (>binary file *.so)
  - simulator (>binary file *.so)

The list shows the hierarchical relationship among the top-level folders. The parenthesis shows the contents of a given directory. All directory names appear in bold text. File names are preceded by the `>` sign.

## The plugin.xml file

The `plugin.xml` file contains the extension's namespace and other metadata. Set up the `Echo` plugin as follows:

        <plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
            id="org.apache.cordova.blackberry.echo"
            version="1.0.0">
            <js-module src="www/client.js">
                <merges target="navigator" />
            </js-module>
            <platform name="blackberry10">
                <source-file src="src/blackberry10/index.js" />
                <lib-file src="src/blackberry10/native/device/libecho.so" arch="device" />
                <lib-file src="src/blackberry10/native/simulator/libecho.so" arch="simulator" />
                <config-file target="www/config.xml" parent="/widget">
                    <feature name="org.apache.cordova.blackberry.echo" value="org.apache.cordova.blackberry.echo" />
                </config-file>
            </platform>
        </plugin>