Integrating Cordova Plugin with Oracle MAF - Android Calendar Plugin

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>

Comments:

Thanks for the post but I need to ask some questions
01.When I downloaded calendar plugin to put it in the 5 directories “bin,libs,res,assets,js” I just found CalendarPlugin.java , calendar.js files in the plugin directory and I don’t know if these tow files enough.

02.I don’t know how to Build the plugin library using Ant.

Is there an example, as this would be easier to understand

Posted by guest on August 05, 2014 at 01:46 AM PDT #

Hi guest,

01. With this specific example the CalendarPlugin.java and calendar.js files are the only two files needed. The calendar.js file will go into the "application workspace directory\ViewController\public_html\plugins\Plugin Name\Platform\js" directory. The CalendarPlugin.java will be required to create the classes.jar file that will be used in project's bin directory.

02. Do you have Ant installed? Write down the location of your Ant\bin directory. For example, it may be located at "C:\Program Files\apache-ant-1.9.4\bin". Navigate to your project library from the command prompt and run the following command: "<your Ant\bin directory>\ant clean release".

If the CalendarPlugin library was located at "C:\Users\joe\Documents\CalendarPlugin" I would use the command prompt to navigate to that directory. Next I would type "C:\Program Files\apache-ant-1.9.4\bin\ant clean release" to build the project.

I hope this helps!

Posted by guest on August 05, 2014 at 10:17 AM PDT #

Thanks for the post but while running the command

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

I am getting Error: Argument 'android-17' is not recognized.

Can you kindly help me in that

Posted by guest on August 11, 2014 at 12:46 AM PDT #

Hi Shay,

Can u plz provide the source application for above post.

We are implementing the same scenario, But unable to see the calendar component on screen. It will be great if u can provide us the code base.

Thanks
Nitesh

Posted by guest on August 13, 2014 at 05:41 AM PDT #

Hi shay

While building the plugin library with ant, build failed since the package name and the class name were same. So I changed the name of the class file(CalendarPlugin.java to CalendarExample.java) and made corresponding changes in the javascript, at this level build was successful.

In maf-application.xml, while adding the cordova plugin
Fully Qualified Name: CalendarExample

Platform: Android

Fully Qualified Name: CalendarExample

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

and continued with the further steps.

While building the application I'm encountering the error:
ClendarEg\.main.android\bin\build-android.xml:38: The following error occurred while executing this line:
ClendarEg\.main.android\bin\build-android.xml:143: <workspace>\ClendarEg\.main.android\build\debug\res\xml\preferences.xml (The system cannot find the file specified)

I request you to help me with this issue
Thanks in advance
Ranjitha

Posted by Ranjitha on August 21, 2014 at 03:29 AM PDT #

Hi Shay & Jonathan,

This seems to be the only article giving any help regarding the MAF integration with Cordova Plugins. We need more info :-)

Above, it is mentioned that we can download Cordova 2.2.0 from the Apache Archive. But unfortunately, I can see only version 2.3.0 onwards in the Archive. Am I missing something?

Posted by Amit Goyal on August 22, 2014 at 08:32 PM PDT #

Amit - you can get 2.2 here - http://phonegap.com/install/

Posted by Shay on August 27, 2014 at 01:29 PM PDT #

Hi Shay,

Followed your blog and was able to add files, but my Cordova Plug-in internally refers to another Android Library Project. While building the binary, I made sure to include the library projects alongside for successful compilation. But I am confused as to which location within the MAF folders should the library projects be copied to.

Should it be added to the Dependent Libraries folder - application workspace directory\ApplicationController\src\plugins\Plugin Name\Platform\libs ?

If so, then should they be copied as is or should it be pre-compiled or put in some other format.

Posted by guest on December 24, 2014 at 05:57 AM PST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

This blog is is dedicated to announcements,tips and tricks and other items related to developing, integrating, securing, and managing mobile applications using Oracle's Mobile Platform. It is created and maintained by the Oracle Mobile product development team.

Archive of past entries

Even More Mobile Development Blogs

Oracle A-Team Site - Mobile Related Entries

Code samples from the Community

Fusion Middleware Blogs

Search

Archives
« May 2015
SunMonTueWedThuFriSat
     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
      
Today