Guest post by Jonathan Lui – our summer intern whose been helping us build some cool demos.

In this blog we’ll explain how to integrate a cordova plugin into your Oracle MAF application, specifically we are going to look at an example of integrating a calendar plugin for the Android platform. 

We’ll be using an Anroid Calendar Plugin that you can get here: https://github.com/tenforwardconsulting/Phonegap-Calendar-Plugin-android

 Here is what it is going to look like at the end:


AMX page with button to add event


event in the calendar

There are some steps you need to do first to enable your MAF application to use a Cordova plugin here are the steps: 

0. Create 5 directories – see the list in the table here

Next you’ll need to provide a JAR file containing the cordova plugin. If you have a plugin without a JAR,  you can create the JAR with the following steps:

1. Create a directory for your cordova plugin – we’ll use C:\Users\joe\Documents\CalendarPlugin in our example.

2. Create the library project in your new cordova plugin directory by running the following command:

 <android_sdk_root>/tools/android create lib-project –target "android-15" –name  <LibraryName> –package <PackageID> –path <cordova_plugin_path>

     windows example:

    a) Navigate to C:\Users\joe\Android\android-sdk\tools in command prompt

    b) Type:

    android create lib-project –target “android-15” —name” CalendarPlugin –package “com.tenforwardconsulting.phonegap.plugins.CalendarPlugin” –path “C:\Users\joe\Documents\CalendarPlugin”

    • name – LibraryName – this can be pretty much anything; it is just the name of your project
    • package – PackageID – if your plugin contains resources, then PackageID should match the application_package entry in the plugin’s build.properties file. If your plugin does not contain such resources, this just has to follow Java package naming conventions, i.e. com.yourcompany.yourproject.
 3. Copy source files from the plugin to your new library project. This is dependent on the structure of your plugin, but generally you will see one or more .java source files in the plugin folder; copy these over to the src subdirectory of your library project, making sure to maintain the directory structure.
 In some cases, you will also see a res subfolder in the plugin. All of these files will likewise need to be copied into the res subfolder of your library project. If your plugin contains Android resources, you must also ensure that the plugin does not declare any resources with the same IDs as those used by the the MAF application. Generally speaking, the most common case of this will be the app_name resource of strings.xml.

In our sample you’ll copy the CalendarPlugin.java file. 

4. Add Cordova as a dependency of this new library project. If you don’t have the cordova jar file on your machine you can download it from the apache cordova install page (You need the 2.2.0 version).

 copy <cordova_root>/lib/android/cordova-2.2.0.jar <CordovaPluginLibrary>/libs

windows example:

  From the command prompt type “copy C:\Users\joe\Documents\phonegap-phonegap-8a3aa47\lib\android\cordova-2.2.0.jar CalendarPlugin\libs”

5. Build the plugin library using Ant (download it or use the one from the JDeveloper install)

<ant_root>/bin/ant clean release

Windows Example:

a) Navigate to your plugin folder (e.g. C:\Users\joe\Documents\CalendarPlugin”)

b) Run the following command “C:\Users\joe\Documents\apache-ant-1.9.4\bin\ant clean release”

6. Confirm that there is a classes.jar file in the bin subdirectory of your library project.

7. Copy the classes.jar file to the plugin library directory you created in step 1 (application workspace directory\ApplicationController\src\plugins\Plugin Name\Platform\bin)

Now you’ve built your Cordova plugin project and created the binary for MAF.

Using your Cordova Plugin

In order to use the Cordova Plugin you just added you need to add a reference to the javascript in each of the features that will be using the plugin.

1. Open the maf-application.xml overview editor and choose the Cordova Plugins Page. The maf-application.xml page can be found at Application Resources–> Descriptors –> ADF META-INF.

2. Click add to complete the Insert Plugin Dialog. For the Calendar Plugin app referenced above you would use the following:

Fully Qualified Name: CalendarPlugin

Platform: Android

Fully Qualified Name: CalendarPlugin

Implementation Class: com.tenforwardconsulting.phonegap.plugins.CalendarPlugin

3. Add the reference to the javascript file in each of the features by opening maf-feature.xml. Click the feature and the "content" tab. Under the "Includes" click the green "+" button to add the javascript file.

4. Create a Managed Bean that will handle the backend logic that will call the cordova plugin. In order to call the javascript functions you will need to use "AdfmfContainerUtilities.invokeContainerJavaScriptFunction(

featureid, methodname, new Object[] { params… });".

5. To make calls to the actual functions you need to use <amx:verbatim> in your amx page.


Here are some code samples that you can use to work with our calendar plugin:

Code from the Java Bean we’ll be using through the various pages:

package mobile;


import java.util.Calendar;

import java.util.Date;


import java.util.GregorianCalendar;


import oracle.adfmf.amx.event.ActionEvent;

import oracle.adfmf.framework.api.AdfmfContainerUtilities;

import oracle.adfmf.framework.api.AdfmfJavaUtilities;


public class MyBean {

    private String title;

    private String location;

    private String notes;

    private Date startDate;

    private Date endDate;


    public MyBean() {

        super();

    }


    public void createEvent(ActionEvent actionEvent) {

        AdfmfContainerUtilities.invokeContainerJavaScriptFunction(AdfmfJavaUtilities.getFeatureName(), "calendarEvent", new Object[] {

                                                                  });

    }


    public void createEvent2(ActionEvent actionEvent) {

        Calendar c1 = new GregorianCalendar(2014, 7, 20, 10, 0);

        Calendar c2 = new GregorianCalendar(2014, 7, 20, 11, 0);

        AdfmfContainerUtilities.invokeContainerJavaScriptFunction(AdfmfJavaUtilities.getFeatureName(), "calendarEvent", new Object[] {

                                                                  c1.getTime().toString(), c2.getTime().toString(),

                                                                  "Created from Java", "Java Basement",

                                                                  "This event has been created from a Java bean"

        });

    }


    public void createEvent3(ActionEvent actionEvent) {

        AdfmfContainerUtilities.invokeContainerJavaScriptFunction(AdfmfJavaUtilities.getFeatureName(), "calendarEvent", new Object[] {

                                                                  startDate, endDate, title, location, notes

        });

    }


    public void setTitle(String title) {

        this.title = title;

    }


    public String getTitle() {

        return title;

    }


    public void setLocation(String location) {

        this.location = location;

    }


    public String getLocation() {

        return location;

    }


    public void setNotes(String notes) {

        this.notes = notes;

    }


    public String getNotes() {

        return notes;

    }


    public void setStartDate(Date startDate) {

        this.startDate = startDate;

    }


    public Date getStartDate() {

        return startDate;

    }


    public void setEndDate(Date endDate) {

        this.endDate = endDate;

    }


    public Date getEndDate() {

        return endDate;

    }


}

 Example 1 – Event parameters hard coded into the javascript:

<?xml version="1.0" encoding="UTF-8" ?>

<amx:view xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amx="http://xmlns.oracle.com/adf/mf/amx"

          xmlns:dvtm="http://xmlns.oracle.com/adf/mf/amx/dvt">

    <amx:panelPage id="pp1">

        <amx:verbatim id="v1">

<![CDATA[

<script type="text/javascript" src="js/calendar.js"></script>

<script type="text/javascript">

function calendarEvent()

{

var startDate = new Date("August 20, 2014 10:00:00");

var endDate = new Date("August 20, 2014 11:00:00");

var title = "Hack on Phonegap";

var location = "The Basement";

var notes = "Hacking on open source projects late at night is the best!";

var success = function() { alert("woo hoo!"); };

var error = function(message) { alert("Doh!"); };

window.plugins.calendarPlugin.createEvent(title, location, notes, startDate, endDate, success, error);

}

</script>

]]>

</amx:verbatim>

        <amx:facet name="header">

            <amx:outputText value="Header" id="ot1"/>

        </amx:facet>

        <amx:facet name="secondary">

            <amx:commandButton text="Example 1" id="cb1" actionListener="#{MyBean.createEvent}"/>

        </amx:facet>

    </amx:panelPage>

</amx:view>


 Example 2 – Event parameters hardcoded within the java bean


<?xml version="1.0" encoding="UTF-8" ?>

<amx:view xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amx="http://xmlns.oracle.com/adf/mf/amx"

          xmlns:dvtm="http://xmlns.oracle.com/adf/mf/amx/dvt">

    <amx:panelPage id="pp1">

        <amx:verbatim id="v1">

<![CDATA[

<script type="text/javascript" src="js/calendar.js"></script>

<script type="text/javascript">

function calendarEvent(startDateString, endDateString, title, location, notes)

{

var startDate = new Date(startDateString);

var endDate = new Date(endDateString);

var success = function() { alert("woo hoo!"); };

var error = function(message) { alert("Doh!"); };

window.plugins.calendarPlugin.createEvent(title, location, notes, startDate, endDate, success, error);

}

</script>

]]>

</amx:verbatim>

        <amx:facet name="header">

            <amx:outputText value="Header" id="ot1"/>

        </amx:facet>

        <amx:facet name="secondary">

            <amx:commandButton text="Example 2" id="cb1" actionListener="#{MyBean.createEvent2}"/>

        </amx:facet>

    </amx:panelPage>

</amx:view>


 Example 3 – The event parameters are input by the user and stored in page-scope variables, which are read by the JS code


<?xml version="1.0" encoding="UTF-8" ?>

<amx:view xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amx="http://xmlns.oracle.com/adf/mf/amx"

          xmlns:dvtm="http://xmlns.oracle.com/adf/mf/amx/dvt">

    <amx:panelPage id="pp1">

        <amx:verbatim id="v1">

<![CDATA[

<script type="text/javascript" src="js/calendar.js"></script>

<script type="text/javascript">

function calendarEvent()

{

var startDate;

adf.mf.el.getValue("#{pageFlowScope.startDate}",

function(req, res) { startDate = new Date(res[0][‘value’]) },

function() { alert("Failed"); });

var endDate;

adf.mf.el.getValue("#{pageFlowScope.endDate}",

function(req, res) { endDate = new Date(res[0][‘value’]) },

function() { alert("Failed"); });

var title;

adf.mf.el.getValue("#{pageFlowScope.title}",

function(req, res) { title = res[0][‘value’] },

function() { alert("Failed"); });

var location;

adf.mf.el.getValue("#{pageFlowScope.location}",

function(req, res) { location = res[0][‘value’] },

function() { alert("Failed"); });

var notes;

adf.mf.el.getValue("#{pageFlowScope.notes}",

function(req, res) { notes = res[0][‘value’] },

function() { alert("Failed"); });

var success = function() { alert("woo hoo!"); };

var error = function(message) { alert("Doh!"); };

window.plugins.calendarPlugin.createEvent(title, location, notes, startDate, endDate, success, error);

}

</script>

]]>

</amx:verbatim>

        <amx:facet name="header">

            <amx:outputText value="Header" id="ot1"/>

        </amx:facet>

        <amx:facet name="secondary">

            <amx:commandButton text="Example 3" id="cb1" actionListener="#{MyBean.createEvent}"/>

        </amx:facet>

        <amx:inputText label="Title" id="it1" value="#{pageFlowScope.title}"/>

        <amx:inputText label="Location" id="it2" value="#{pageFlowScope.location}"/>

        <amx:inputText label="Notes" id="it3" value="#{pageFlowScope.notes}"/>

        <amx:inputDate label="Start Date" id="id1" value="#{pageFlowScope.startDate}" inputType="datetime"/>

        <amx:inputDate label="End Date" id="id2" value="#{pageFlowScope.endDate}" inputType="datetime"/>

    </amx:panelPage>

</amx:view>


 Example 4 – The event parameters are input by the user and written to the Java bean, which then passes them to the JS function:


<?xml version="1.0" encoding="UTF-8" ?>

<amx:view xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amx="http://xmlns.oracle.com/adf/mf/amx"

          xmlns:dvtm="http://xmlns.oracle.com/adf/mf/amx/dvt">

    <amx:panelPage id="pp1">

        <amx:verbatim id="v1">

<![CDATA[

<script type="text/javascript" src="js/calendar.js"></script>

<script type="text/javascript">

function calendarEvent(startDateString, endDateString, title, location, notes)

{

var startDate = new Date(startDateString);

var endDate = new Date(endDateString);

var success = function() { alert("woo hoo!"); };

var error = function(message) { alert("Doh!"); };

window.plugins.calendarPlugin.createEvent(title, location, notes, startDate, endDate, success, error);

}

</script>

]]>

</amx:verbatim>

        <amx:facet name="header">

            <amx:outputText value="Header" id="ot1"/>

        </amx:facet>

        <amx:facet name="secondary">

            <amx:commandButton text="Example 4" id="cb1" actionListener="#{MyBean.createEvent3}"/>

        </amx:facet>

        <amx:inputText label="Title" id="it1" value="#{MyBean.title}"/>

        <amx:inputText label="Location" id="it2" value="#{MyBean.location}"/>

        <amx:inputText label="Notes" id="it3" value="#{MyBean.notes}"/>

        <amx:inputDate label="Start Date" id="id1" value="#{MyBean.startDate}" inputType="datetime"/>

        <amx:inputDate label="End Date" id="id2" value="#{MyBean.endDate}" inputType="datetime"/>

    </amx:panelPage>

</amx:view>