Showing posts with label apache. Show all posts
Showing posts with label apache. Show all posts

Thursday, February 6, 2014

Anna Has Been Pulled From the Play Store

Back in September of 2012 I posted up my sample app called Anna which highlighted the power of doing speech recognition on mobile devices using PhoneGap. Today I've had to pull the app from the Play Store because of this infringement notice from Wolfram Alpha.



I don't have the strength, time nor money to fight this so I just going to rolled over pulled the app. I attempted to discuss it with Wolfram Alpha but they insisted I 1) pay for an commercial deployment license, 2) remove the Wolfram Alpha functionality or 3) pull the app. I can't afford the rates they charge for a commercial deployment license. Still they can't do anything about the source code for the app which is still available at: https://github.com/macdonst/anna

I'm not even mad, just a bit puzzled as there is no way my sample app is in any way a threat to the Wolfram Alpha app in the Play Store. I guess they don't want to have a precedent where they don't aggressively enforce their terms of service.

It's rather silly as I don't even ship an API key with the app. If you want to use Anna you have to sign up with Wolfram Alpha so they won't be getting the, albeit small, exposure that my app provides. Also, I doubt I'll ever recommend them to any of my developer friends ever again.

Thursday, July 25, 2013

PhoneGap Day US 2013 Recap

Why, weren't you there? Seriously, what's stopped you? This conference is so great and so cheap that if you are anywhere near Portland, Oregon you need to go. Even if you aren't near Portland you need to convince your boss to send you to the conference.

What's the number one reason to attend PhoneGap Day? Timing, no wait the community. The community really comes out for this conference. I can't think of another conference I've attended where you can meet so many committers. If you were there you could have met all those people you see fixing bugs on JIRA and checking code into GIT.

Beyond the committers there were lots of folks who are building real applications with PhoneGap and they are there for you to talk with, network and generally pick their brains.

There were a lot of great presentations this year but if I was going to single out three they'd be Andy Trice's PhoneGap+Hardware, Michael Brooks super slick PhoneGap Command Line demo/presentation (I only wish I was that smooth) and finally Lyza Danger Gardner's deck on PhoneGap Self-Defense for Web Devs. That one was jam packed with things web devs should know before diving into PhoneGap.

I was sweating my talk a bit before heading up on stage. I was about to give a speech recognition demo on a stage in front of 250 people. There were so many things that could have gone wrong like the (network, crowd volume) and one thing did. For some reason my MBP would not mirror the displays so either I could see the presentation or the audience could. Luckily, as a former boy scout, I was prepared. I was hosting my presentation on Dropbox so I was able to slide over to Tommy-Carlos Williams laptop to do my demo without holding up the show. Thanks again Tommy!

Sacrificing my laptop to the demo gods seemed to appease them and the rest of my presentation went off pretty well with only one unintentionally funny moment. People seemed to have liked it which I was happy about. You can download a PDF version of the presentation but it plays much better as a live demo.

All of these presentation videos will be available soon. In fact when mine is up I'll be posting it here. As well I'm lagging behind posting my source code but I'm kinda busy with some other commitments I'll talk about on a later date.

Beyond catching up with all of the other PhoneGap committers it was a great conference for meeting folks I internet knew, In Real Life. Besides the afore mentioned Tommy-Carlos Williams who shocked me by not having an Australian accent, he is USA born, I got to meet my co-worker Marcel Kinard for the first time. Both Marcel and I work at IBM where he is managing IBM's contributions to the PhoneGap/Cordova code base. Finally I got to know Jim Cowart of Icenium pretty well over the conference. Jim's done a great write up of the conference himself.

Honestly, I will carry to my grave the memory of the taste of Griddled Bacon Wrapped Date with warm honey from Tora Bravo. Jim, Marcel, Burin and I went there after the first day of the conference and we were all blown away with how good the food was. I guess it is not a secret but Portland is a great city for foodies.

Finally I will leave you with this over the shoulder video of me playing Galaga at Ground Kontrol the amazing barcade (bar + arcade) courtesy of Jim.

Wednesday, July 3, 2013

Backup, Remove and Restore your Contacts using PhoneGap

A couple of people have had questions on how to do this recently so I thought I would do a write up on it. As well, it illustrates how you avoid using loops with asynchronous code. Although for an even better explanation of that topic you'll want to read Item 64: Use Recursion for Asynchronous Loops from David Herman's book, Effective JavaScript. Chapter 7 on Concurrency is worth the purchase price of the book but I digress...

First a warning. Try all the code out on an emulator first. The methods below will completely wipe the contacts from your device so you'll want to make sure the backup step works first before continuing. You've been warned!

Anyway, if you want to backup the contacts on your device to a file you'd use the following process:
  1. Find all the contacts
  2. Request a file system object
  3. Create a FileEntry object
  4. Create a FileWriter
  5. Write the JSON data to file
The code in which to accomplish those tasks is as follows: Once you see the "backup complete" message in the console you'll have a file called "contacts.bak" in the root directory of your file system. For Android users that will probably be /sdcard and for iOS, etc. it would be in the applications sandbox. If you take a look at the file you will see something like this: If you are seeing what looks like your complete contact database in text format then you are ready to proceed.

Next we will delete all the contacts on the device. The steps are:
  1. Find all the contacts
  2. Recurse through the contacts deleting one at a time.
The code looks like:

This might look a little bit weird at first glance but trust me it'll make sense. You'll notice in deleteAllTheContacts the first thing we do is to create a local function called deleteContacts. This is the method that will actually remove the contacts from the device. Then after the definition of deleteContacts we call navigator.contacts.find(). This call will get an array of all the contacts on the device and call it's success function which is deleteContacts.

Now in deleteContacts we do a check to see if the length of the contacts array is zero. If it is zero then we are done, there are no more contacts left to be deleted. If the contact array length is greater than zero we have more work to do. We'll pop the next Contact object off of the contacts array, which reduces the size of the array by one and we'll call the remove method of the Contact object. The success call back for remove method is the deleteContacts method. Keep reading this paragraph until all of your contacts have been deleted. Boom recursion.

But wait, you are wondering how could this possibly work. Your thinking I've got 7 quintillion contacts and there is no way the call stack can support that many recursive calls. Ah, but you are forgetting that asynchronous calls return immediately so they never eat up the call stack. If you tried doing this with a for loop you would blow up the call stack causing your program to crash if you had enough contacts and even if you didn't kill your app how would you know when all of those async calls to remove were complete without doing a lot of JavaScript gymnastics. Just use the recursion approach.

Finally you'll want to be able to restore the contacts you've previously saved to file. I've broken it down into two separate methods to make it easier to read:
  1. Request local file system
  2. Get the FileEntry
  3. Request the File object
  4. Read the data and parse it to JSON
  5. Recurse through all the contacts and save them to the device

This is pretty much just unrolling the two previous steps of backing up and deleting the contacts. If you've gotten this far you should be able to understand what is going on. Although there are two lines I want to draw your attention to:
contactData.id = null;
contactData.rawId = null;
What I'm doing here is removing the unique ID's from the contact. If you skip this step you will signal the API that you are attempting to modify an existing contact and the save will most probably fail. Hopefully this helps a bunch of folks.

Thursday, June 13, 2013

My PhoneGap Presentation to Ottawa JS

So on Wednesday night I did my Introduction to PhoneGap/Apache Cordova (GitHub repo) presentation for Ottawa JS at the beautiful Shopify lounge. I've given this presentation a ton of times so I decided to give it a twist this time around.

The first thing I did was convert my old slide deck into a reveal.js presentation. Then I popped all the assets into a PhoneGap iPad project to see how it looked. Well, reveal.js looks and works great on an iPad.

At this point I started to get fancy. When I got to the part of the presentation where I would usually switch from the presentation software to Eclipse/Xcode to show the code and emulator I decided to call out to PhoneGap to take a picture instead. All I needed to do was include cordova.js in the app and make a call to Camera.getPicture and the results were:


this is my view from the stage


the view from the audience

And Darren took a picture of me taking the picture, while the picture I was taking was being put up on the big screen which is also in this picture. So I was able to do a presentation on PhoneGap in a PhoneGap app calling the PhoneGap API. It got meta pretty damn quick!





Sunday, June 2, 2013

Why Don't My Plugins Work in PhoneGap Android 2.7?

Well it's pretty simple, the Plugin class which has been deprecated for awhile has been removed from the package and should be replaced with CordovaPlugin.

I'm going to go through the steps needed to upgrade your old style plugins to the new style. For this example I'm going to use the Google Analytics plugin.

The first thing you will notice in 2.7.0+ is that the GoogleAnalyticsTracker class now has 4 errors in Eclipse. To get rid of them you would change:


import org.apache.cordova.api.Plugin;

into:

import org.apache.cordova.api.CordovaPlugin;

and:

public class GoogleAnalyticsTracker extends Plugin {

to:

public class GoogleAnalyticsTracker extends CordovaPlugin {

and now you'll notice you only have one error left in the file and that has to do with the execute method. You'll need to change the method signature from:

public PluginResult execute(String action, JSONArray data, String callbackId) {

to:

public boolean execute(String action, JSONArray data, CallbackContext callbackContext) {

then you need to add a new import line at the top of the Java file:


import org.apache.cordova.api.CallbackContext;

and we still have one error which is now the line in which we are returning the PluginResult. That's because the method now expect a boolean to be the return value. To fix this issue you would replace:

return result;

with:

callbackContext.sendPluginResult(result);
return true;

Finally our Java code is free of error messages. Whew, were done but what's with the change to the execute method? Well let's just say there have been improvements in the way the Plugins are handled internally. What you need to know is that when you want to send a result back to the JavaScript side you now have a choice of three methods:

1) callbackContext.sendPluginResult(...)

Use this if you have constructed your own PluginResult and you want to send it to the JavaScript side.

2) callbackContext.error(int | String | JSONObject) 

Skip creating a PluginResult and just invoke the error callback on the JavaScript side sending back an int, a String or a JSONObject as the method payload.

3) callbackContext.success(empty | int | String | JSONObject | JSONArray)

Again, just skip creating the PluginResult and invoke the success callback on the JavaScript side sending back an int, a String, JSONObject or JSONArray as the method payload. If you don't provide any payload the method on the JS side will be executed with no payload.

So that should get you unstuck if you have a Plugin that no longer works for you as of PhoneGap 2.7.0. You should also check out my posts on the GalleryPlugin as shows how to write a Plugin using the new API for JS and Java.

IMPORTANT UPDATE!!!

We've heard your screams of pain and we are putting the Plugin class back for PhoneGap 2.8.1. Go read Joe Bowser's post. The class is back in 2.8.1 and will be in 2.9.0 then gone for good in the 3.0.0 stream!





Monday, May 13, 2013

The Ottawa City Councillor PhoneGap app

So a couple of friends of mine wanted to learn more about programming mobile applications so we decided to get together and create an application for the Apps4Ottawa competition.

We settled on creating an application that would enable folks from Ottawa to learn more about and connect with their city councillors. Sadly, I didn't even know who my city councillor was until I started working on this app.

It uses the open data Ottawa to get the city councillor information and it the Open North API to do reverse geocoding to turn your GPS co-ordinates into the correct ward.

Currently the app is available on the Google Play store and we are going through the process of getting approval for the app on the Apple store.

PhoneGap was definitely the way to go with this project. We developed pretty much in Android then when we were ready to release a version of the app we just compiled it in Xcode and it just worked. The only thing we changed were the break points for the CSS media queries to deal with the different iPhone screen sizes. Support for Windows 8 and BlackBerry 10 are also coming as we have time.

I'm going to write up a post later in the week to talk about some of the micro libraries we used in order to accelerate development.

Please give the app a try and let me know what you think of it and what can be done better. If you are so inclined we wouldn't mind a vote or two in the app in the Apps4Ottawa competition.

Monday, March 4, 2013

PhoneGap Bluetooth Plugin Updated

So the Bluetooth plugin was horribly out of date so I took some time to update it to work with PhoneGap 2.2.0 and higher. As well as the usual updates to the JS and Java code I fixed an instance in the "listDevices" call which would block code execution for 10 seconds while it scanned for devices.

Anyway, if you need Bluetooth functionality the plugin provides the following method:

  • listDevices
  • isBTEnabled
  • enableBT
  • disableBT
  • pairBT
  • unPairBT
  • listBoundDevices
  • stopDiscovering
  • isBound
Enjoy!

Update: Oh by the Hoary Hosts of Hogarth! I should mention that I didn't originate this plugin, I just saw the need for it to be updated. All credit should go the original authors: Daniel Tizón, Idoia Olalde and Iñigo González

Thursday, February 28, 2013

What's New in PhoneGap Android 2.5.0

Well PhoneGap Android 2.5.0 is out! There isn't much to get excited about on Android in this release as it is mostly bug fixes. Check out the full list of commits in the CHANGELOG. Fixes include:

  • Fixing a null pointer exception when the user clicks the back button while the app is starting.
  • Enabling the application cache.
  • New configuration parameter "disallowOverscroll" to remove that blue glow when you try to scroll past the top/bottom of the screen.
  • Enabled geolocation in the InAppBrowser.

However, something I can get excited about is that in the past month we've seen 8 new committers to the Android project. Yup, 8 new coders contributed their time to cordova-android which I think is a great sign of the health of the project.

Monday, February 18, 2013

PhoneGap Android XhrFileReader

The FileReader API works great as long as the file you want to read is on the device's file system. However if you want to read a file you've packed in the Android assets folder you would need to use XHR to read the file. I'm providing an interface that follows the same API as the regular FileReader. Of course the XhrFileReader is not limited to only reading files from the assets folder, it can also read files from the file system and over HTTP.

Adding the plugin to your project 

To install the plugin, move XhrFileReader.js to your project's www folder and include a reference to it in your html files.

Using the plugin 

To instantiate a new reader use the folling code:
var reader = cordova.require("cordova/plugin/xhrfilereader"); 
Setup your event handlers:
// called once the reader begins
reader.onloadstart = function() {
    console.log("load start");
};
// called when the file has been completely read
reader.onloadend = function(evt) {
    console.log("File read");
    console.log(evt.target.result);
}; 
Unfortunately, you will only get an error on files read over HTTP. When you specify a file:// path the request status is always 0. There is no way to tell between a successful read or an error. So if you specify a file that does not exist like "file:///does.not.exist.txt" you will get an empty evt.target.result in your onloadend handler.
// called if the reader encounters an error
reader.onerror = function(error) {
    console.log("Error: " + error.code);
}; 
Progress events are fired but are not very useful as they don't contain partial results.
// called while the file is being read
reader.onprogress = function(evt) {
    console.log("progress");
}; 
Finally call your read method, for instance:
reader.readAsText("http://www.google.com"); reader.readAsText("file:///android_asset/www/config.json"); reader.readAsText("file:///sdcard/error.log");
and that's about it. Obviously, this plugin is most useful when you need to read a text file from the assets folder.

Thursday, February 14, 2013

What's New in PhoneGap Android 2.4.0

Well PhoneGap 2.4.0 has been released. So here are couple of the new things you can look forward to:

1. Support Reading Slices of Text Files.

The File object now has a slice method. Suppose the file we're reading contains the text:

"All that is gold does not glitter, not all those who wander are lost." 

Then...

  • f.slice(4, 8) would result in "that" 
  • f.slice(9) would be "is gold does not glitter, not all those who wander are lost." 
  • f.slice(-5, -1) would be "lost"


2. Added input type=file support

Now if you specify an input field of type file you will get a "Choose File" button:


Then when you click the button you will launch an intent that can handle file picking:


Now the value of your input tag will be the file you selected.

3. Additional preferences in config.xml

I completely missed this one so Joe Bowser wrote it up.

Saturday, February 9, 2013

PhoneGap Plugin Updates to TelephoneNumber, IMEI and TTS

I've updated the TelephoneNumber, IMEI and TTS plugins to use the Apache Cordova 2.2.0 API's. That means no more deprecation notices in the Java code and the JavaScript code uses the cordova.require method. However, I'm still slapping the objects into window.plugins so you shouldn't need to change any of your JavaScript code after upgrading.

This completes the upgrade of my plugins that everyone voted on. Next up will be some new work and hopefully I'll be able to get to that WebSpeech shim I've been threatening to do.

Thursday, January 31, 2013

GalleryPlugin

I've updated the GalleryPlugin to the Cordova 2.2.0 API but I've realized that I've never really talked about it. The GalleryPlugin is used when you need to add or remove a file from the Gallery or Music apps. Typical use cases include downloading an image from the internet and wanting it to show up in the Android Gallery app or conversely you delete a file and you don't want the dreaded black rectangle to be left in the Gallery app.


First lets take a look at what the gallery.js file. It's written using the cordova.define template but it still adds itself into window.plugins for those of you using the old style plugins:

Then will move on to the Java code. I've trimmed down code only to show the execute method for brevity.

In order to use this plugin you'll need to include the gallery.js in your HTML as a script tag:

and add a line to res/xml/config.xml to tell the JavaScript side where to find your Java class:

Now you should be able to add and remove images from the gallery. Here is some sample code to get you going:

Monday, January 21, 2013

PhoneGap Plugin Updates

In the past few days I've spent some time upgrading my plugins so they work in PhoneGap/Cordova 2.2.0 or greater without requiring the users to make any changes. I've done the FtpClient and VideoPlayer. Basically I'm removing any deprecation warnings by moving from the org.apache.cordova.api.Plugin class to the org.apache.cordova.api.CordovaPlugin class. Also, I've been moving to the cordova.require way of defining a plugin on the JavaScript side while retaining the old window.plugins object for people who've written their code to use this object.

I'm currently running a poll to see which of my plugins should get upgraded next so go please vote for your favourite:


I'll start picking them off as I have time this week.

Tuesday, December 18, 2012

What's New in PhoneGap Android 2.3.0

Well we've tagged Apache Cordova 2.3.0 release candidate 2 which means that Cordova 2.3.0 will be out soon in source release form which will be followed quickly by the binary PhoneGap 2.3.0 release. Shaz wrote up a post on what's new in iOS so I followed suit to do this one for Android. So without further ado here's what you should expect on Android:

1. InAppBrowser – includes events

More details here. In a nutshell, this has the same functionality as the ChildBrowser, and has events support as well. It supports this simplified spec. Also, the InAppBrowser does not use the app whitelist. Example usage:
2. Device API changes

Minor changes as specified here. For Android, device.name is now deprecated for all platforms. For all platforms, there is a new property called device.model which returns what device.name used to return.

3. Various Bug Fixes
  • Searching for emails in Contacts throws an exception always errors out
  • Create script improvement: Display usage and exit when no arguments given
  • Fixed adding a Photo from a HTTPS address to Contact
  • Fixed NPE in onReceivedError with non local errorUrl
  • Camera.getPicture gives error when get a picture from photo library with spaces in its name on Android is now fixed
  • Online/Offline events now fire on subsequent pages of an app
  • fixing cordova commands for paths with spaces in them
  • FileEntry.moveTo across file systems incorrectly calls the success callback

Thursday, December 6, 2012

How to Get the Device's Phone Number Using PhoneGap Android

I was a bit surprised when three people asked me how to do this in one day. I figured if there was enough interest in it then maybe it deserved a post of it's own. Basically you want to know the primary phone number of the device your app is running on. In order to do that in PhoneGap you will need to write a plugin to access the TelephonyManager service on Android.

As always the code for this plugin is is GitHub at my TelephoneNumberPlugin repo. If you'd rather have a more detailed walk through please read on.
First up let's code our JavaScript interface which we will use to get the telephone number. We'll setup a new interface at "cordova/plugin/telephonenumber" to avoid name collisions. Then the rest is fairly boiler plate code where we declare and error object that we won't even use and finally provide a get method. When you call the get method you should provide a success callback. The success callback will be invoked with a string that will contain the devices phone number. If something goes wrong the failure callback will be invoked.

I've extracted the execute method from TelephoneNumber.java which extends from the new CordovaPlugin interface. The method is fairly self explanatory. If the device has a phone number it will be returned. If not the error call back is invoked with the NO_TELEPHONE_NUMBER error code. If you try to call anything other than "get" on this class you'll get a INVALID_ACTION error.

In order to use this plugin you'll need to include the telephonenumber.js in your HTML as a script tag:

and add a line to res/xml/config.xml to tell the JavaScript side where to find your Java class:

and if you don't already have READ_PHONE_STATE as a permission in your AndroidManifest.xml you will need to add it as well.

Now you should be able to get your devices phone number. Here is some sample code that writes the phone number out to the console:

Wednesday, November 28, 2012

Building a HTML Options Menu for PhoneGap Android

Alright, sorry it took me so long to get back to this but I was busy getting things done for the 2.3.0 release. This is a continuation of my series of posts on menus the previous ones were on Context and Option menus. Also, the code is not perfect there are some things I want to do that will support multiple image sizes and organize the menu in multiple rows but I figured I'd release what I was able to re-create. My original code is somewhere on another laptop. So the new code is now available in this github repo.

Okay, so if you want to use this component you will need to download OptionsMenu.js from the above link, place it in your assets/www folder then add the script tag after cordova.js in your HTML file.

Next you will want to create you menu. For my purposes I've used the settings/help example like the previous two posts on menus. To do it you add some code into your to the method that is listening for the "deviceready" event. Something like this:
and that will produce a menu that looks like this:


But let's dig in a bit of that call to create a new OptionsMenu. The magic is in the JSON object passed to the construction. Obviously the "id" is used to set the ID of the div that will hold the menu items. Then the items array will contain all of the menu items you want to display. Each menu item has three properties, image is a url the icon you want to display in the item, label which is the text which is shown under the image and finally action which is a JavaScript function that is called when the item is tapped.

So that's it, you have a fully functioning HTML/CSS/JS only options menu just by including an additional JavaScript file. Like I said the code is up on github and it is not perfect. Feel free to submit issues as I'm going to pick away at making it more robust after I take a mini vacation.

Update: So I realized the menu really should support multiple rows just like a real Android options menu so I just pushed an update to my code on Github to support it. Instead of an array being sent to the constructor of the OptionsMenu you send a multi-dimensional array like so:

and then it looks like this:


You will also notice the icons are a bit smaller. I'm checking for the size of the screen and adjusting the icon width and height accordingly.

Monday, November 12, 2012

Building a Native Context Menu for PhoneGap Android

So I know I promised that I'd write about a HTML only menu but I thought folks might be interested in native context menus as well. It's not much different than my last blog post on menu's so it should be easy to follow.

So when I talk about a native context menu I mean the menu that clicks when you do a long press on an Android device. Again this is well covered on the Android Developer page. Here is an example of an context menu from the Contacts app:


The first step in creating the menu is to define it in XML. My recommendation is to create a menu folder under the res folder in your Android Eclipse project. Then you create a new File with an XML extension. For this post I'll call mine example.xml. When you're done your res folder should look something like this:


Don't worry about the red X's as we haven't edited the XML file yet so it is going to complain about a premature end of file. For a real good description of what goes into a menu XML file read this. For our purposes I'm just going to give you the XML to paste into the file:

But when you view the file in Eclipse you'll still see errors:


and that is to be expected as we haven't added the two images to the drawables folder nor have we added our two new strings to strings.xml. To fix these issues first download these two images:


and copy them to your projects res/drawable-hdpi folder. When you want to put out a professional application you'll need to provide icons of various sizes but the above is enough for our needs.

To fix the rest of the red X's you'll need to open the res/values/strings.xml and add two new Strings. The first should have the name "settings" and a value of "Settings. The second should have the name"help" and, predictably, the value of "Help". At this point all the red X's from example.xml and from the res folder hierarchy should have disappeared. 


If they haven't, well then you've done something wrong and should probably go back over all the steps to make sure you haven't missed anything.

Okay, so now we've got all the resources in place. Let's go write some actual Java code. Don't worry much of it will be cut and paste. In Eclipse open up your main Java class, you know the one that extends DroidGap.

First you'll need to register the context menu in the onCreate method. Basically, you'll need to add the call to registerForContextMenu to your onCreate method:


Secondly we'll need to tell your application what to do when it detects a long press. You'll need to paste the following code into you main Java class:

You shouldn't need to change anything unless you've called your menu XML file something different than example.xml. If you have you'll need to change R.menu.example into R.menu. where you replace with the name of your file minus the .xml extension.

The last bit of code you need to add is a method that will tell your application what to do when the individual menu items are clicked. Here's some example code:


When you click on the Setting button we'll use an Android intent to load the devices Settings panel. If you click on the Help button then we'll execute some JavaScript code. That's it! You don't need to add anything to your HTML/JS code to get a native Android context menu working with your PhoneGap application. Here is what it would look like:



Please note, I'm just providing a quick example and you are not limited to how you handle the menu button clicks in the least. You may want to handle it in Java and do something that you can't do in JavaScript or you may want to call a JavaScript function on your page to have your UI react in some interesting way.

So, there you go. The process is nearly identical to creating an options menu that I described in my previous post. I promise that in my next post I'll show you how to handle everything in HTML and JavaScript!

Thursday, November 8, 2012

My PhoneGap Plugins Have Moved

If you are looking for any of the plugins that I have contributed to the PhoneGap Plugins repo they have moved into my own repo. Why do you ask? Well you should go read Shaz's blog post as to the why's and wherefore's.

So you can now find my plugins at:

Tuesday, November 6, 2012

Building a Native Menu with PhoneGap Android

So this question has been posed to me quite a few times over the past couple of weeks so I figure this is probably a good idea for a series of blog posts. In this instalment I'll talk about creating a native menu and next time we'll use only HTML.

So when I talk about a native menu I mean an Android options menu and a lot of the information I'm going to give you is covered very well on this Android Developer page but what I'm going to do is help show you where to add the hooks into your PhoneGap application. Here is an example of an options menu from the Contacts app:


The first step in creating the menu is to define it in XML. My recommendation is to create a menu folder under the res folder in your Android Eclipse project. Then you create a new File with an XML extension. For this post I'll call mine example.xml. When your're done your res folder should look something like this:


Don't worry about the red X's as we haven't edited the XML file yet so it is going to complain about a premature end of file. For a real good description of what goes into a menu XML file read this. For our purposes I'm just going to give you the XML to paste into the file:

But when you view the file in Eclipse you'll still see errors:


and that is to be expected as we haven't added the two images to the drawables folder nor have we added our two new strings to strings.xml. To fix these issues first download these two images:


and copy them to your projects res/drawable-hdpi folder. When you want to put out a professional application you'll need to provide icons of various sizes but the above is enough for our needs.

To fix the rest of the red X's you'll need to open the res/values/strings.xml and add two new Strings. The first should have the name "settings" and a value of "Settings. The second should have the name"help" and, predictably, the value of "Help". At this point all the red X's from example.xml and from the res folder hierarchy should have disappeared. 


If they haven't, well then you've done something wrong and should probably go back over all the steps to make sure you haven't missed anything.

Okay, so now we've got all the resources in place. Let's go write some actual Java code. Don't worry much of it will be cut and paste. In Eclipse open up your main Java class, you know the one that extends DroidGap.

First we'll need to tell your application what to do when it detects that the menu button has been pressed. You'll need to paste the following code into you main Java class:

You shouldn't need to change anything unless you've called your menu XML file something different than example.xml. If you have you'll need to change R.menu.example into R.menu. where you replace with the name of your file minus the .xml extension.

The second bit of code you need to add is a method that will tell your application what to do when the individual menu items are clicked. Here's some example code:


When you click on the Setting button we'll use an Android intent to load the devices Settings panel. If you click on the Help button then we'll execute some JavaScript code. That's it! You don't need to add anything to your HTML/JS code to get a native Android options menu working with your PhoneGap application. Here is what it would look like:



Please note, I'm just providing a quick example and you are not limited to how you handle the menu button clicks in the least. You may want to handle it in Java and do something that you can't do in JavaScript or you may want to call a JavaScript function on your page to have your UI react in some interesting way.

In my next post I'll show you the reverse. How to handle everything in HTML and JavaScript!

Tuesday, October 16, 2012

Presenting PhoneGap at Ottawa Web Design, UX Design and Web Development

So if you are one of the few people in Ottawa who haven't heard me do my presentation on PhoneGap I will be doing it one more time this year at the Ottawa Web Design, UX Design and Web Development meetup on November 7th. The meeting will be held at The Code Factory which is at 246 Queen St. Ottawa, ON. Maybe I'll see you there.