Adding a Custom Plug-in to the Android Hybrid Web Container

Add a PhoneGap plug-in to the Hybrid Web Container.

  1. In Eclipse, open the HybridWebContainer project.
  2. Open the plugins.xml file, which is located in res/xml.
  3. Add your custom plug-in, for example:
    <plugin name="DirectoryListPlugin" value="com.sybase.hwc.DirectoryListPlugin" />
  4. Add plug-in images to the HybridWebContainer project.
    The plug-in used in this example does not include images, but they are allowed in plug-ins. Images for plug-ins are usually stored in a location similar to: ...\<projectFolder>\assets\www\<nameOfPlugin>\, where <projectFolder> is the root folder of the project, and <nameOfPlugin> is the name of the plug-in you are adding.
  5. Add your Java source file that implements the custom plugin, for example, DirectoryListPlugin.java.
    This example PhoneGap plugin lists all files on the SDCard of the device.
    /**
     * Example of Android PhoneGap Plugin
     */
    package com.sybase.hwc;
    
    import java.io.File;
    
    import org.json.JSONArray;
    import org.json.JSONException;
    import org.json.JSONObject;
    
    import android.util.Log;
    
    import com.phonegap.api.Plugin;
    import com.phonegap.api.PluginResult;
    import com.phonegap.api.PluginResult.Status;
    
    /**
     * PhoneGap plugin which can be involved in following manner from javascript
     * <p>
     * result example - {"filename":"/sdcard","isdir":true,"children":[{"filename":"a.txt","isdir":false},{..}]}
     * </p>
     * <pre>
     * {@code
     * successCallback = function(result){
     *     //result is a json
     *  
     * }
     * failureCallback = function(error){
     *     //error is error message
     * }
     *	
     * window.plugins.DirectoryListing.list("/sdcard",
     *			                            successCallback
     *			                            failureCallback);
     *		                               
     * }
     * </pre>
     * @author Rohit Ghatol
     * 
     */
    public class DirectoryListPlugin extends Plugin {
    
    	/** List Action */
    	public static final String ACTION="list";
    	
    	/*
    	 * (non-Javadoc)
    	 * 
    	 * @see com.phonegap.api.Plugin#execute(java.lang.String,
    	 * org.json.JSONArray, java.lang.String)
    	 */
    	@Override
    	public PluginResult execute(String action, JSONArray data, String callbackId) {
    		Log.d("DirectoryListPlugin", "Plugin Called");
    		PluginResult result = null;
    		if (ACTION.equals(action)) {
    			try {
    
    				String fileName = data.getString(0);
    				JSONObject fileInfo = getDirectoryListing(new File(fileName));
    				Log
    						.d("DirectoryListPlugin", "Returning "
    								+ fileInfo.toString());
    				result = new PluginResult(Status.OK, fileInfo);
    			} catch (JSONException jsonEx) {
    				Log.d("DirectoryListPlugin", "Got JSON Exception "
    						+ jsonEx.getMessage());
    				result = new PluginResult(Status.JSON_EXCEPTION);
    			}
    		} else {
    			result = new PluginResult(Status.INVALID_ACTION);
    			Log.d("DirectoryListPlugin", "Invalid action : "+action+" passed");
    		}
    		return result;
    	}
    
    	/**
    	 * Gets the Directory listing for file, in JSON format
    	 * @param file The file for which we want to do directory listing
    	 * @return JSONObject representation of directory list. e.g {"filename":"/sdcard","isdir":true,"children":[{"filename":"a.txt","isdir":false},{..}]}
    	 * @throws JSONException
    	 */
    	private JSONObject getDirectoryListing(File file)
    			throws JSONException {
    		JSONObject fileInfo = new JSONObject();
    		fileInfo.put("filename", file.getName());
    		fileInfo.put("isdir", file.isDirectory());
    
    		if (file.isDirectory()) {
    			JSONArray children = new JSONArray();
    			fileInfo.put("children", children);
    			if (null != file.listFiles()) {
    				for (File child : file.listFiles()) {
    					children.put(getDirectoryListing(child));
    				}
    			}
    		}
    
    		return fileInfo;
    	}
    }
    
  6. Save the file.
    These are all the changes needed for the Hybrid Web Container; you can now build it and install it on the device. What the plug-in actually does is implemented in the Java file in the execute function. The rest of this example explains how to test and use the PhoneGap plug-in.
  7. Test the plug-in:
    1. Create a new Mobile Workflow application:
      1. Select File > New > Mobile Application Project.
      2. In Project name, enter PhonegapTest.
      3. Click Finish.
    2. Right-click the PhonegapTest project folder and select New > Mobile Workflow Forms Editor.
    3. Click Next.
    4. Select Can be started, on demand, from the client and click Finish.
    5. Add an HtmlView control to the start screen of the Mobile Workflow application.
      For this example, the HtmlView control key's name is "key2." This is the key name you will use in the custom.js file for the customAfterWorkflowLoad() function.
    6. Run the Mobile Workflow Package Generation wizard to create the Generated Workflow directory structure Generated Workflow\PhonegapTest\ html\js.
    7. Add your JavaScript implementation to the generated js folder, for example, directorylisting.js,, and paste in this code:
      /**
       *  
       * @return Instance of DirectoryListing
       */
      var DirectoryListing = function() { 
      
      }
      
      /**
       * @param directory The directory for which we want the listing
       * @param successCallback The callback which will be called when directory listing is successful
       * @param failureCallback The callback which will be called when directory listing encouters an error
       */
      DirectoryListing.prototype.list = function(directory,successCallback, failureCallback) {
      	
          return PhoneGap.exec(successCallback,    //Callback which will be called when directory listing is successful
          					failureCallback,     //Callback which will be called when directory listing encounters an error
          					'DirectoryListPlugin',  //Telling PhoneGap that we want to run "DirectoryListing" Plugin
          					'list',              //Telling the plugin, which action we want to perform
          					[directory]);        //Passing a list of arguments to the plugin, in this case this is the directory path
      };
      
      /**
       * <ul>
       * <li>Register the Directory Listing Javascript plugin.</li>
       * <li>Also register native call which will be called when this plugin runs</li>
       * </ul>
       */
      PhoneGap.addConstructor(function() {
      	//Register the javascript plugin with PhoneGap
      	PhoneGap.addPlugin('directorylisting', new DirectoryListing());
      });
      
      This code has a wrapper for the PhoneGap plug-in execution call, and adds the custom plug-in to the list of known PhoneGap plug-ins.
    8. Open the custom.js file for editing and add this code, which makes use of the plug-in, to the customAfterWorkflowLoad() function:
      var directoryListingFunction = function()
      {
      	
      		var dl = new DirectoryListing();
      		
      		function onSuccess(r)
      		{
      			var replace = document.getElementById('key2');
      			if(replace)
      			{
      				var theHtml = "<html><head><title>A Title</title></head><body>Top level contents of sd card:<br/>";
      				if(r.children)
      				{
      					var index = 0;
      					for(index = 0; index <= r.children.length;index++)
      					{
      						if(r.children[index]){
      							theHtml += r.children[index].filename + "<br/>";
      						}
      					}
      				}
      				else
      				{
      					alert("No r.children!!");
      				}
      				theHtml +="</body></html>";
      				replace.innerHTML = theHtml;
      			}
      		}
      		
      		function onError(e)
      		{
      			alert( "Error: " + e );
      		}
      		
      		var result = dl.list( "/sdcard", onSuccess, onError );
      		
      	}
      	
      	directoryListingFunction();
      
    9. Generate the Mobile Workflow Package again.
    10. Assign the Mobile Workflow to a device that has the modified Hybrid Web Container (that was built after steps 1 through 4).
    11. On the device, run the Mobile Workflow application. You may want to add some files to the SD card so you get non-trivial results. The Mobile Workflow application should look something like the following (depending on what you put on the SD card):