Creating PhoneGap Plugins for Windows Phone 8

[Infragistics] Mihail Mateev / Friday, February 15, 2013

Developers could use HTML / CSS / Java Script (including popular libraries like jQuery and jQuery Mobile) to create multi platform hybrid mobile applications. Cordova API offers access to many device specific functionalities like location, accelerometer etc.

Sometimes you need a specific unsupported device functionality or you could implement a specific feature better and easier using a native code.

In the previous blogs  “Using PhoneGap in Windows Phone 8 Applications” and   “PhoneGap + jQuery Mobile for Windows Phone 8 Hybrid Applications” we discussed how to start with PhoneGap Windows Phone 8 applications and how to use jQuery Mobile in Cordova WP8 hybrid apps.

 

In this article we will discuss how to create a PhoneGap Plugin for Windows Phone 8 application. We will modify the Twitter Cordova Application, demonstrated in this blog.

Startup project (twitter search mobile application)

  

 

Windows Phone Cordova Plugins Architecture

All WP8 PhoneGap plugins must derive from the PhoneGap base command. More specifically, the WPCordovaClassLib.Cordova.Commands.BaseCommand class. Plugin commands are dealt with generically throughout the framework, and base command provides the base interface for you to pass data back to JavaScript. This approach also prevents JavaScript code from calling arbitrary native code.For Windows Phone Mango you could read this blog.

 

How to Create a PhoneGap Plugin

 

Lets add a new functionality “Share Status”  to sample PhoneGap application. For this purpose we will create a Cordova plugin for Windows Phone. You will be available to share your status in different social networks like Twitter, Facebook, etc..

You could use for this WEB API for each network but if you still have no implementation the easiest solution is to use native Windows Phone code.  Developers can use the share status task to enable the user to share a status message on the social network of their choice.

 

Basically  ShareStatusTask launches a dialog that enables the user to share a status message on the social networks (Facebook, Windows Live, Twitter, etc.).

To start using it you will need to include the following namespace:

Namespace:  Microsoft.Phone.Tasks  

 

All you need to do in order to this launchers in your application is:

  1. Create an instance of  ShareStatusTask,
  2. Set desired propertied: Status.
  3. Call Show():

 

By default plugins are placed under [Cordova WP8 Project]->Plugins

 

Lets create in our Cordova WP8 project a new C# file: Plugins->ShareStatus.cs

 

Add the following code in your class:

   1: public class ShareStatus : BaseCommand
   2: {
   3:  
   4:     [DataContract]
   5:     public class ShareStatusParameters
   6:     {
   7:         [DataMember]
   8:         public string status { get; set; }
   9:     }
  10:  
  11:     public void postStatus(string args)
  12:     {
  13:         ShareStatusParameters statusParam = JsonHelper.Deserialize<ShareStatusParameters>(args);
  14:         ShareStatusTask shareStatusTask = new ShareStatusTask();
  15:         shareStatusTask.Status = statusParam.status;
  16:         this.DispatchCommandResult(new PluginResult(PluginResult.Status.OK, statusParam.status));            
  17:         shareStatusTask.Show();
  18:     }
  19: }

DispatchCommandResults handles a callback function that returns a result of the plugin function execution.

 

Add two fields : search field where to write your new status and a button that will call a JavaScript function, named “postStatus”.

   1: <div data-role="statuscontain">
   2:      <input type="search" name="status" id="status" value="" />
   3:      <input type="button" name="statusButt" id="statusButt"  value="Set Status"/>
   4: </div>

 

The “postStatus” function calls the “postStatus” method from “ShareStatus” plugin.

   1: $(function () {
   2:                 $('#statusButt').click(function () {
   3:                     postStatus();
   4:                 });
   5:             });
   6:  
   7:             function postStatus() {
   8:                 cordova.exec(
   9:                     function (res) {
  10:                         var postedStatus = res + ' is posted!';
  11:                         alert(res);
  12:                         document.getElementById('res').innerHTML = postedStatus;
  13:                     },
  14:                     function (e) {
  15:                         console.log("Error occurred: " + e);
  16:                         document.getElementById('res').innerHTML = "Error occurred: " + e;
  17:                     },
  18:                     "ShareStatus", "postStatus",
  19:                     { status: document.getElementById('status').value });
  20:             };
  21:  </script>

 

The whole code of the index.html file (html and JavaScript) is available below.

   1: <!DOCTYPE html>
   2: <html>
   3:     <head>
   4:         <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
   5:         <meta name="format-detection" content="telephone=no" />
   6:         <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
   7:         <link rel="stylesheet" type="text/css" href="css/index.css" />
   8:         <link rel="stylesheet"  href="css/themes/default/jquery.mobile-1.2.0.css" />
   9:         <script src="http://debug.phonegap.com/target/target-script-min.js#devil-mike"></script>
   1:  
   2:         <script src="js/jquery.js">
   1: </script>
   2:         <script src="js/jquery.mobile-1.2.0.js">
   1: </script>  
   2:         <title>Hello World</title>
   3:     </head>
   4:     <body>
   5:         <script type="text/javascript" src="cordova-2.3.0.js">
   1: </script>
   2:         <script type="text/javascript" src="js/index.js">
   1: </script>
   2:         <script type="text/javascript">
   3:             app.initialize();
   4:         
</script>
   1:  
   2:         <script type="text/javascript">
   3:  
   4:         
</script>
   1:  
   2:         <!---- SEARCH PAGE ----->
   3:         <div data-role="page" id="page1">
   4:             <div data-role="header">
   5:                 <h1>Twitter</h1>
   6:             </div><!-- /header -->
   7:  
   8:             <div data-role="content">
   9:                <div data-role="statuscontain">
  10:                     <input type="search" name="status" id="status" value="" />
  11:                     <input type="button" name="statusButt" id="statusButt"  value="Set Status"/>
  12:                 </div>
  13:                 <div>
  14:                     Result: <span id="res"></span>
  15:                 </div> 
  16:                 <div data-role="fieldcontain">
  17:                     <input type="search" name="search" id="search" value="" />
  18:                     <input type="button" name="searchButt" id="searchButt"  value="Search"/>
  19:                 </div>
  20:  
  21:                     <div data-role="content">    
  22:                 <div id="twitList">
  23:                 
  24:                 </div>
  25:             </div><!-- /content -->
  26:                 <a href="#prefs" data-role="button" data-icon="gear" data-rel="dialog" data-transition="pop">Preferences</a> 
  27:             </div><!-- /content -->
  28:  
  29:     
  30:         </div><!-- /page -->
  31:  
  32:  
  33:         <!---- PREFERENCES ----->
  34:         <div data-role="page" id="prefs">
  35:             <div data-role="header">
  36:                 <h1>Preferences</h1>
  37:             </div><!-- /header -->
  38:  
  39:             <div data-role="content">
  40:                 <div data-role="fieldcontain">
  41:             
  42:                     <label for="slider">Number of results:</label>
  43:             
  44:                     <input type="range" name="slider" id="slider" value="15" min="0" max="100"  />
  45:                     <fieldset data-role="controlgroup">
  46:                     <legend>Result Type:</legend>
  47:                         <input type="radio" name="radio-choice-1" id="radio-choice-1" value="mixed" checked="checked" />
  48:                         <label for="radio-choice-1">Mixed</label>
  49:  
  50:                         <input type="radio" name="radio-choice-1" id="radio-choice-2" value="recent"  />
  51:                         <label for="radio-choice-2">Recent</label>
  52:  
  53:                         <input type="radio" name="radio-choice-1" id="radio-choice-3" value="popular"  />
  54:                         <label for="radio-choice-3">Popular</label>
  55:                     </fieldset>
  56:  
  57:                 </div>
  58:             </div><!-- /content -->
  59:  
  60:         </div><!-- /page -->
  61:  
  62:     </body>
  63: </html>
  64:  
  65: <script type="text/javascript">
  66:             $(function () {
  67:                 $('#searchButt').click(function () {
  68:                     doSearch();
  69:                 });
  70:             });
  71:  
  72:             $(function () {
  73:                 $('#statusButt').click(function () {
  74:                     postStatus();
  75:                 });
  76:             });
  77:  
  78:             function doSearch() {
  79:                 $.ajax({
  80:  
  81:  
  82:                     url: "http://search.twitter.com/search.json?q=" + $('#search').val() + "&result_type=" + $('input:radio[name=radio-choice-1]:checked').val() + "&rpp=" + $('#slider').val(),
  83:                     dataType: 'jsonp',
  84:                     success: function (json_results) {
  85:                         // Remove any list - so the new one can be added.
  86:                         $('#twitList ul').remove();
  87:                         // Need to add UL on AJAX call or formatting of userlist is not displayed
  88:                         $('#twitList').append('<ul data-role="listview"></ul>');
  89:                         listItems = $('#twitList').find('ul');
  90:                         $.each(json_results.results, function (key) {
  91:                             html = '<img src="' + json_results.results[key].profile_image_url + '"/>';
  92:                             html += '<h3><a href="#">' + json_results.results[key].text + '</a></h3>';
  93:                             html += '<p>From: ' + json_results.results[key].from_user + ' Created: ' + json_results.results[key].created_at + '</p>';
  94:                             listItems.append('<li>' + html + '</li>');
  95:                         });
  96:                         // Need to refresh list after AJAX call
  97:                         $('#twitList ul').listview();
  98:                     }
  99:                 });
 100:             }
 101:  
 102:             function postStatus() {
 103:  
 104:                 cordova.exec(
 105:                     function (res) {
 106:                         var postedStatus = res + ' is posted!';
 107:                         alert(res);
 108:                         document.getElementById('res').innerHTML = postedStatus;
 109:  
 110:                     },
 111:                     function (e) {
 112:                         console.log("Error occurred: " + e);
 113:                         document.getElementById('res').innerHTML = "Error occurred: " + e;
 114:                     },
 115:                     "ShareStatus", "postStatus",
 116:                     { status: document.getElementById('status').value });
 117:             };
 118:  
</script>

 

Test your Cordova WP 8 plugin:

Deploy and run the application.

Write a new status and press the button “Set Status”.

As a result you will see the standard Windows Phone “Post Message” dialog where you can edit and post your message.

 

  

 

PhoneGap plugin method “postMessage” returns a result of the method execution (Your status is posted successfully )

 

   

 

You can check in Twitter and Facebook your status.

 

The posted status in Twitter.

 

The posted status in Facebook.

 

If you have basic knowledge of Windows Phone Development you can cerate easy various plugins for your PhoneGap applications. These plugins could let your hybrid apps to support  specific features, that could be implemented with native code.

 

You can find the original version of the same application built using plain jQuery & jQuery Mobile (without PhoneGap Plugin)  here.

Sample project source code (Windows Phone 8 Cordova Plugin ) is available here.

Windows Mango Version of the project (Windows Phone Mango Cordova Plugin ) could be downloaded here.

 

Follow news from Infragistics for more information about new Infragistics events.

As always, you can follow us on Twitter @mihailmateev and @Infragistics and stay in touch on Facebook, Google+andLinkedIn!