Creating the Java part of the extension

To work with a JavaScript extension in your BlackBerry WebWorks application, you must define the extension and export the source code as a JAR file. Then you must import this JAR file into your BlackBerry WebWorks application project that uses the JavaScript extension. You can then use the BlackBerry WebWorks Packager to package your application.

The JAR file for the JavaScript extension consists of the following components:

File

Description

A Java file that contains a class that implements the WidgetExtension interface

This class implements the WidgetExtension interface. WidgetExtension provides four methods used to load and unload the extension in your application and provides access to additional resources such as the BlackBerry WebWorks config.xml file and the associated BrowserField object.

For more information, see Define a class that implements the WidgetExtension interface.

A Java file that contains a class that extends the Scriptable class

This class maps the keywords that are provided by a BlackBerry WebWorks application to the internal BlackBerry device logic. This class calls the invoke methods that are defined by subclasses of ScriptableFunction.

For more information, see Define a class that extends Scriptable.

A Java file that contains a class that extends the ScriptableFunction class

This class overrides invoke() which contains the logic of the function that the BlackBerry WebWorks application calls.

For more information, see Define a class that extends ScriptableFunction.

A library.xml file that contains the feature ID and internal class name of the extension

This XML file defines the correlation between the feature ID and the internal class name of the JavaScript extension. This file defines the name that the BlackBerry WebWorks application uses to invoke the JavaScript extension.

For more information, see Create a library XML file.

Your JavaScript extension can also reference precompiled classes. For more information, see Use precompiled classes in an extension.

Define a class that implements the WidgetExtension interface

  1. Create a Java class file named SampleExtension.java.
  2. Import the required classes.
    import net.rim.device.api.browser.field2.BrowserField;
    import net.rim.device.api.script.ScriptEngine;
    import net.rim.device.api.web.WidgetConfig;
    import net.rim.device.api.web.WidgetExtension;
    import org.w3c.dom.Document;
  3. Define a class that implements the WidgetExtension interface. In this code sample, the class is SampleExtension. Define the four methods that WidgetExtension requires that you implement, described in steps 3 to 7. In this code sample, we declare two class variables, _widgetNameForFutureUse and _browserFieldForFutureUse, which are assigned values in register(), described in step 6.
    public final class SampleExtension implements WidgetExtension
    {
        String _widgetNameForFutureUse;
        BrowserField _browserFieldForFutureUse;
    
        public String[] getFeatureList()
        {
        }
    
        public void loadFeature(String feature, String version, Document doc, ScriptEngine scriptEngine) throws Exception
        {
        }
    
        public void register(WidgetConfig widgetConfig, BrowserField browserField)
        {
        }
       
        public void unloadFeatures(Document doc)
        {
        }
    }
  4. The application calls the getFeatureList() when the JavaScript extension is created. Define the getFeatureList() method to provide a full list of feature IDs that the BlackBerry WebWorks application can provide extensions for. This method is called when the BlackBerry WebWorks Packager parses the config.xml file that requires the feature. In this code sample, getFeatureList() provides one feature ID, sample.
    public String[] getFeatureList()
    {
        String[] result = new String[1];
        result[0] = "sample.alert";
        return result;
    }
  5. The loadFeature() method is called when the BlackBerry WebWorks application loads a resource that requires a feature ID that you supplied in getFeatureList(). Define this method to allow your application to add your extension to the script engine. In this code sample, the string sample.alert maps to a new AlertSample object.
    public void loadFeature(String feature, String version, Document doc, ScriptEngine scriptEngine) throws Exception
    {
        if (feature.equals("sample.alert")) 
        {
            scriptEngine.addExtension("sample.alert", new AlertSample());
        }
    }
  6. The register() method provides access to the config.xml file or BrowserField object, if required. Define this method to be called when the BrowserField object is initialized.
    public void register(WidgetConfig widgetConfig, BrowserField browserField)
    {
        _widgetNameForFutureUse = widgetConfig.getName();
        _browserFieldForFutureUse = browserField;
    }
  7. Define the unloadFeatures() method to perform any clean up when your extension is unloaded.

Code sample: Defining a class that implements the WidgetExtension interface

package sample; 

import net.rim.device.api.browser.field2.BrowserField;
import net.rim.device.api.script.ScriptEngine;
import net.rim.device.api.web.WidgetConfig;
import net.rim.device.api.web.WidgetExtension;
import org.w3c.dom.Document;

public final class SampleExtension implements WidgetExtension
{
    String _widgetNameForFutureUse;
    BrowserField _browserFieldForFutureUse;
  
    public String[] getFeatureList()
    {
        String[] result = new String[1];
        result[0] = "sample.alert";
        return result;
    }

    public void loadFeature(String feature, String version, Document doc, ScriptEngine scriptEngine) throws Exception
    {
        if (feature.equals("sample.alert")) 
        {
            scriptEngine.addExtension("sample.alert", new AlertSample());
        }
    }

    public void register(WidgetConfig widgetConfig, BrowserField browserField)
    {
        _widgetNameForFutureUse = widgetConfig.getName();
        _browserFieldForFutureUse = browserField;
    }

    public void unloadFeatures(Document doc)
    {
    }
}

Define a class that extends Scriptable

This class maps the keywords that are provided by a BlackBerry WebWorks application to internal BlackBerry device logic.

  1. Create a Java file named AlertSample.java.
  2. Import the required classes.
    import net.rim.device.api.script.Scriptable;
    import.net.rim.device.api.system.Alert;
  3. Define the AlertSample class, extending Scriptable with an empty constructor.
    public final class AlertSample extends Scriptable 
    {
        public AlertSample()
        {
        }
    }
  4. In AlertSample, define a String constant, FIELD_VIBRATE_SUPPORTED. This String defines the name of the JavaScript function that your application uses to check if vibration is supported on the BlackBerry device. BlackBerry devices have different hardware configurations, and it is good practice to check for specific functionality before you use the functionality in your application.
    public final class AlertSample extends Scriptable 
    {
        public static final String FIELD_VIBRATE_SUPPORTED = "vibrateSupported";
    
        public AlertSample()
        {
        }
    
    }
  5. Define a String constant, FIELD_VIBRATE. This String defines the name of the JavaScript function that your application uses to invoke the invoke() method, derived from the parent class, in the class that extends ScriptableFunction. In this code sample, the class that extends ScriptableFunction is the Vibrate class.
    public final class AlertSample extends Scriptable 
    {
        public static final String FIELD_VIBRATE_SUPPORTED = "vibrateSupported";
        public static final String FIELD_VIBRATE = "vibrate";
    
        public AlertSample()
        {
        }
    
    }
  6. In AlertSample, initialize a variable of type Vibrate to connect the functionality that is defined in Vibrate. Next, create an instance of Vibrate in the AlertSample constructor.
    public final class AlertSample extends Scriptable 
    {
        public static final String FIELD_VIBRATE_SUPPORTED = "vibrateSupported";
        public static final String FIELD_VIBRATE = "vibrate";
    
        private Vibrate _callVibrate;
    
        public AlertSample()
        {
            _callVibrate = new Vibrate();
        }
    
    }
  7. Define a method named getField(), derived from the parent class, that takes the name of the function that is called by the application. This method is invoked when you use the dot (.) extender on your JavaScript object.
    public final class AlertSample extends Scriptable 
    {
        public static final String FIELD_VIBRATE_SUPPORTED = "vibrateSupported";
        public static final String FIELD_VIBRATE = "vibrate";
    
        private Vibrate _callVibrate;
    
        public AlertSample()
        {
            _callVibrate = new Vibrate();
        }
    
        public Object getField(String name) throws Exception
        {
            return super.getField(name);
        }
    
    }
  8. In getField(), which is derived from the parent class, check the function that the application calls. In this code sample, if it is vibrateSupported, the application returns the boolean returned by Alert.isVibrateSupported(). If it is vibrate, the application invokes the invoke() method from the Vibrate class.
    public final class AlertSample extends Scriptable 
    {
        public static final String FIELD_VIBRATE_SUPPORTED = "vibrateSupported";
        public static final String FIELD_VIBRATE = "vibrate";
    
        private Vibrate _callVibrate;
    
        public AlertSample()
        {
            _callVibrate = new Vibrate();
        }
    
        public Object getField(String name) throws Exception
        {
            if(name.equals(FIELD_VIBRATE_SUPPORTED))
            {
                return new Boolean(Alert.isVibrateSupported());
            }
            else if(name.equals(FIELD_VIBRATE))
            {
                return this._callVibrate;
            }
            return super.getField(name);
        }
    
    }

Code Sample: Defining a class that extends Scriptable

package sample;

import net.rim.device.api.script.Scriptable;
import net.rim.device.api.system.Alert;

public final class AlertSample extends Scriptable 
{
    public static final String FIELD_VIBRATE_SUPPORTED = "vibrateSupported";
    public static final String FIELD_VIBRATE = "vibrate";

    private Vibrate _callVibrate;

    public AlertSample()
    {
        _callVibrate = new Vibrate();
    }

    public Object getField(String name) throws Exception
    {
        if(name.equals(FIELD_VIBRATE_SUPPORTED))
        {
            return new Boolean(Alert.isVibrateSupported());
        }
        else if(name.equals(FIELD_VIBRATE))
        {
            return this._callVibrate;
        }
        return super.getField(name);
    }

}

Define a class that extends ScriptableFunction

The following steps describe how to trigger a vibrate notification in the BlackBerry WebWorks application by extending the ScriptableFunction class.

  1. Create a Java file named Vibrate.java.
  2. Import the required classes.
    import net.rim.device.api.script.ScriptableFunction;
    import net.rim.device.system.Alert;
  3. Define the Vibrate class, extending ScriptableFunction.
    public final class Vibrate extends ScriptableFunction
    {
    
    }
  4. In Vibrate, define invoke(), to vibrate the BlackBerry device for a specified duration (passed in as argument from the BlackBerry WebWorks application). If vibration is not supported by the device, this method does nothing by returning the constant, UNDEFINED.
    public final class Vibrate extends ScriptableFunction
    {
        public Object invoke(Object obj, Object[] args) throws Exception
        {
            if(!Alert.isVibrateSupported()) 
            {
                return UNDEFINED;
            }
            
            if (args.length == 1)
            {
                int duration = ((Integer)args[0]).intValue();
                Alert.startVibrate(duration);
            }
    
            return UNDEFINED;
        }
    }

Code sample: Defining a class that extends ScriptableFunction

package sample;

import net.rim.device.api.script.ScriptableFunction;
import net.rim.device.api.system.Alert;

public final class Vibrate extends ScriptableFunction
{
    public Object invoke(Object obj, Object[] args) throws Exception
    {
        if(!Alert.isVibrateSupported()) 
        {
            return UNDEFINED;
        }
        
        if (args.length == 1)
        {
            int duration = ((Integer)args[0]).intValue();
            Alert.startVibrate(duration);
        }

        return UNDEFINED;
    }
}

Create a library XML file

The XML file must be packaged with the source files in the JAR file used by your BlackBerry WebWorks application. You must place the library.xml file in the extension folder's root. For this example, ensure that you compress all of the source files and XML file together in the SampleExtension.jar file.
  1. Create a file named library.xml.
  2. Define the XML version and encoding.
    <?xml version="1.0" encoding="utf-8"?>
  3. Correlate the feature ID with the internal class name of this JavaScript extension and assign your extension a version.
    <library>
        <extension>
            <entryClass>sample.SampleExtension</entryClass>
        </extension>
        <features>
            <feature id="sample.alert" version="1.0.0">My sample alert JavaScript extension</feature>
        </features>
    </library>

Use precompiled classes in an extension

Your JavaScript extension can reference a compiled .jar containing .class files. This enables you to distribute BlackBerry WebWorks extensions without releasing the full Java source. It also allows extensions to use external code or libraries where the source may not be made available.

  1. Compile .java files using the following syntax:
    javac -source 1.3 -target 1.3 -deprecation -classpath <path to net_rim_api.jar> <path to folder containing .java files>
    net_rim_api.jar is in the lib folder in the BlackBerry WebWorks installation folder.
  2. Put the compiled .class files into a .jar file and put the .jar file in the same folder as the library.xml file.
  3. Run the preverify.exe command on the .jar file that contains the compiled classes and make sure there are no errors:
    preverify.exe -classpath <path to net_rim_api.jar> compiled_classes.jar
  4. Add the preverified .jar file to the root of the extension .jar file (for example, MyExtension.jar). Your extension folder structure should be similar to the following:
    library.xml
    MyPackage/MyExtension.java
    MyPackage/MyFunction.java
    MyPackage/MyNamespace.java
    compiled_classes.jar
  5. Add an entry for <dependencies> in the library.xml file:
    <?xml version="1.0" encoding="utf-8"?>
    <library isWhitelist="true">
       <extension  id="Screen">
          <entryClass>something.push.ScreenExtensionInterface</entryClass>
       </extension>
       <dependencies>
          <jar path="compiled_classes.jar" />
       </dependencies>
    </library>
    
  6. Add the extension to the BlackBerry WebWorks .zip file (for example, MyWidget.zip) and compile the application. Your application archive structure should be similar to the following:
    config.xml
    index.html
    ext/MyExtension.jar

Last modified: 2013-08-14