Tag Archives: javascript

Silent no more…

3 May

Wow the past few months have been quite a wild ride, and a ton of things have happened!  So much has gone on and I’ve been writing so much software that I haven’t had the time to blog about it.  In the time I’m not writing software, I’d rather spend it with my wife than spend it writing about the software I’d written.

Over the past few months, while the PhoneGap team started a major refactor of their codebase, I spent some time learning more about Objective-C and UIKit, and discovered that writing native software on the iPhone is a heck of a lot easier than I’d previously expected. It shouldn’t have surprised me, because I’ve heard rave reviews from developers I have a great deal of respect for, and it also shouldn’t come as a great shock that Apple treats their developer SDKs with the same degree of polish and attention-to-detail that they do to their hardware. So while I was working with PhoneGap I’d contributed a number of plugins exposing the iPhone’s native UI elements to JavaScript-based apps, I’ll no longer be updating or adding any new plugins.

While my blog was collecting dust, I also finished a PhoneGap-based app, Parking Mobility, and while it was nice to start the project in familiar languages like HTML and JavaScript, a ton of time ended up getting eaten up chasing random bugs, memory leaks, and strange UI behaviours that required odd work-arounds to eliminate.  In the end I discovered I’d spent more time getting the application to market than if I had built it in native code.  Starting this past weekend I’ve begun doing just that, writing the application in UIKit and Objective-C in order to get more performance and a better user-experience out of the app than we have currently.

One of the other big reasons why I haven’t been as chatty on my site as usual is, of course, the launch of the iPad and the iPhone 3.2 SDK.  I decided to hit the ground running with this platform, and used this new SDK as my playground for learning more native development skills.  I developed two applications for the initial launch of the iPad, Boomle and myDrum Pad.

Boomle is an easy-to-play game featuring peaceful sounds, low-touch interaction, and an addictive gameplay.  It was a lot of fun to build, and got me started working with OpenAL, manually drawing displays, and dealing with real-time games.

myDrum Pad in contrast is an interactive drum pad that aims to allow people to tap beats out with a variety of sound packs along to music, or create their own riffs.  It’s still in active development, but this has been a blast.  I’m developing it with CoreData, OpenAL sound playback, multi-touch displays, In-App purchase and asynchronous downloads from Amazon S3.  It’s a highly dynamic UI with a smooth user experience.  It’s also the first iPhone project that I’m directly involving a graphic designer with the whole process, and once we get a beta ready, I’m sure you’ll like the screenshots and demo images we’ll be putting up.

Last, and certainly not least, I’ve changed roles in my day job at Sophos, and am working once again in the Email Security team developing our Email Security Appliance.  I get to play with all sorts of complex problems, web-based administration interfaces, and pretty much every technology under the sun.

Now that these projects have all stabilized, I’ll hopefully be blogging more about Objective-C, Javascript web applications, and technology in general. Plus Summer’s quickly approaching, so hopefully I’ll have some pictures of my motorcycle and any trips my wife and I take this summer up here soon.

Telling your user that a PhoneGap application is busy

26 Oct

Plenty of times in applications, especially on mobile devices, you just need to tell your users to hold their horses and wait while your application processes something in the background.  Maybe you need to query some data from a remote server, save a file to disk, or maybe you just need to do some number crunching.  Whatever the reason, you don’t want your user to think the program has crashed if you don’t give them some sort of visual feedback that you’re busy and they just have to wait a few seconds.

PhoneGap provides a few methods to handle just this task. There’s four methods within the Notification class that are of interest.

  1. navigator.notification.loadingStart()
  2. navigator.notification.loadingStop()
  3. navigator.notification.activityStart()
  4. navigator.notification.activityStop()

Modal loading messages

Modal loading indicator

Modal loading indicator

The easiest approach to take when making your users wait is to show a modal loading dialog, one that doesn’t let the user interact with the application until you’re done.  There’s a lot less for you, as a developer, to manage when the user isn’t allowed to poke around on buttons when you’re updating the display.  Asynchronous operations are a lot simpler when you’re in control.

The loadingStart() and loadingStop() methods do just this.  They put up a modal semi-transparent layer over top of your application, with a “Loading..” spinner message. You simply call the first method when your application is about to do something, and when it finishes you call the second.

Here’s an example of how to use it.  This will load a remote HTML document and place its contents into a node in your PhoneGap application.

Not only does this make it easier to integrate external content into your PhoneGap application, but it guarantees your user is informed that it’s actively working. As a final bonus, if your external web site doesn’t respond, or if the user doesn’t have an Internet connection, the modal loading screen will close after a timeout.

Asynchronous loading messages

Asyncronous activity loading indicator

Asyncronous activity loading indicator

Sometimes you want to tell your user that the application is busy, but you still want to continue using the app anyway.  If your app doesn’t turn off the top statusbar (where the time, reception, and battery status is displayed), you can control the busy indicator from within PhoneGap.  Just like the above example, you just have to call the appropriate PhoneGap JavaScript methods.  In this case, just update the above example with these messages:

navigator.notification.activityStart();
// Do something that might take a while...
navigator.notification.activityStop();

How to use the native Alert dialog in PhoneGap

19 Oct

PhoneGap's custom alert notification is nicely customizable

PhoneGap's custom alert notification is nicely customizable

An important part to any application is issuing a simple alert to your user. Whether it’s to tell them about an error that just occurred, or if you need to ask them a simple question, giving a message to your user is about the most basic part of any app.

Sadly, when you try to rely on the ever faithful “alert()” function in JavaScript inside a PhoneGap application, you’ll notice the alert box it shows is titled with a very unprofessional “index.html” across the top. Not only does it make it obvious that the app they’re interacting with is actually HTML-based, but you can’t convey the importance of one message or another with a title. Most people only ever read the title anyway, so in order to provide this capability to your application, PhoneGap has an answer for this problem.

Inside PhoneGap there’s a class called “Notification” which is used for, well, sending notifications to your user. And, by calling:

navigator.notification.alert(
  message,
  title,
  buttons...,
  options);

Everything, except for the message, is optional. The more arguments you provide, the more you can customize the alert box. For instance, if you don’t supply a button label, one single “OK” button will be created. Want to ask a Yes/No question? Simply pass two labels for their respective button names.

Like other functions in PhoneGap, the alert notification can be passed an “options” object that allows you to give it more information, such as an onClick callback.

That example shows how to ask your user what to do in the event of an Internet connection problem.  You’ll notice that I’ve decided to pass two button labels.  In the onClick callback function I supplied in my options argument, I’m checking the “buttonIndex” variable it passes.  This tells your function which button was pressed.  If you want more than 2 buttons, just list multiple labels and it will show as many as can fit on the screen.

A very simple function, but invaluable as a developer resource.  And, more importantly, a very easy and professional way to get feedback from your user.

Device.saveScreenshot added to PhoneGap

18 Oct

One of the integral features of the next application I’m releasing (I’ll write a post about it soon, honest) is the capability of saving a copy of the user’s work in my app to their Photo Library. For a while now I’ve been wanting to be able to save screenshots from within PhoneGap for two main reasons:

  1. Be able to export the user’s work and allow them to email it, import it into other applications, etc.
  2. Save a screenshot to their splash-screen image, that way when the application restarts it shows their previous state while they wait (for example, the Notes application on the iPhone).

I’ve implemented #1 right now, meaning with a simple non-blocking call you can save the current view to the photo library. In the future I’ll add another three options: Save to the default splash-screen image, save to a file, and save and upload to a remote location.

Check out the check-in I’ve made and if you have any comments, please let me know!

How to use the ActionSheet in PhoneGap

16 Oct

The ActionSheet is a handy control on the iPhone, and is a very intuitive way of getting a multiple-choice answer from a user in a modal but unobtrusive way.

Using it in PhoneGap makes interacting with your user easy, while keeping the display responsive. And as an added bonus, you don’t need to update any HTML or CSS to get the buttons to look right. The native iPhone codebase handles it for you.

So the question is, how do you use it effectively? As most Web2.0-style developers are aware, the only sensible way to develop flexible applications that don’t bog down the browser is to make your applications behave asynchronously, and make use of callback functions to get feedback from external systems (HTTP requests, users, etc). The ActionSheet on PhoneGap is no different.

The ActionSheet is grouped into the PhoneGap “Dialog” class, and is called like so:

dialog.openButtonDialog(title, buttons..., options);

The title property lets you specify the label to show at the top of the ActionSheet. If you don’t want a title, then simply pass in a null value.

The list of buttons is specified as a series of objects, which I’ll describe below.

Finally, the options let you customize how the ActionSheet is displayed (via the “style” property) and lets you set an onClick handler for the entire ActionSheet.

The example above illustrates several options of the ActionSheet PhoneGap control.

  1. On a per-button basis you can specify your own onClick callback which will be run when that button is pressed.
  2. A global onClick handler can be specified in the openButtonDialog options argument, which will get called no matter what button is pressed.
  3. You can choose what the appearance of the dialog should be (currently only “opaque” and “translucent” are supported)
  4. A button requires a label property, but you can optionally specify a “type” property (can be “normal”, “cancel” or “destroy”).

The callback functions are simply called with two arguments, the index of the button being clicked, and the label of the button the user clicked on.  So if it’s easier for you to work with array indexes, or with text labels, you can easily find out which button was pressed and when.

So go ahead and try out the ActionSheet control.  Either you can use my latest release in my branch of PhoneGap, or you can use these more advanced features once my changes have been merged in with the official branch.

PhoneGap officially permitted on the App Store

7 Oct

Its been a while since I’ve made an update to my blog, and I figured it’s far overdue for a new post. My life over the past little while has been divided up into 4 chunks: my family, my work, my weekend consulting, and my own personal application development. Somewhere around the second half of that list is sprinkled a bit of PhoneGap development.

PhoneGap vs Apple, resolved

First, I’d like to announce that I’ve made headway with my interactions with Apple. They were convinced by my argument that PhoneGap-based apps, just like any other apps developed by users who have access to a rich API, should be judged by their own merits and not prejudged based on what tools were used to built them. This is fantastic news, and means that apps submitted to the App Store will not be rejected solely because they’re built on PhoneGap. Now, if the application is buggy or if a developer tries to do something underhanded with it (for instance, changing the behavior of the app after Apple approves it) that is still cause for a rejection or worse consequences, but the same goes for any application released to the App Store.

Apple did have some requests though. To ensure that apps are released with a “Known Good” version of PhoneGap that they can trust as not having a fundamentally bad design, they wanted to have a version number that would be considered stable and acceptable. Additionally, they would like to have some way of easily identifying the version of PhoneGap used, so they can easily check that little box that says “Don’t reject it just because of its framework.”

I had a meeting with the good folks at Nitobi over a few beer, and ended up updating the version number to 0.8.0, and added a version tag that is added at build-time to the compiled iPhone application bundle. This will make it quicker for Apple to approve your apps, as well as remove any guesswork on their end about whether or not to trust your application.

The catch…

As with all good things in life, there is a catch. Since Apple doesn’t have any idea what version of PhoneGap any apps already submitted to the App Store for approval may be running on – and as a result has no idea whether it’s a safe version of PhoneGap or not – they’ll have to reject all the PhoneGap applications in their queue, and kindly request that you resubmit your apps once you’ve updated to the newer version of PhoneGap.

I want to stress that they’re rejecting these apps only to ensure they’re running the first Apple-approved PhoneGap version, and not for any other reason. Once you update and re-submit your apps, they’ll reenter the queue and will be reviewed just like any other iPhone application. This doesn’t mean they won’t reject your app for some other reason, but at least PhoneGap won’t be a blocker anymore.

I have some additional announcements and general thoughts on PhoneGap and my use of it to post, but since this news is so big, and since I’ve been too busy lately to update my blog in a while, I thought I’d open with this post first.  I’ll hopefully resume my regular blog posting soon, so please check back later.

Update: For more information about the origins of my conversations with Apple, see my posts titled Updates on Apple / PhoneGap and Open letter to Apple iPhone Developer Support.

Updates on Apple / PhoneGap

22 Jun

Things have been busy over the past few days, which is the reason why I haven’t had a chance to post about this until now. But for the PhoneGap community, I have some good news and some bad news.  First, the good news: I got a phone call from the Apple app reviewer that was reviewing my test app.  And before I go any further, I want to say a few things.

When I crafted my original letter to Apple, I was very cautious how I wrote it, because I don’t want to give anyone the wrong impression. I don’t have any problems with Apple or the fact that they have an app review process. I actually think the strict regulations Apple has with its review process is a good thing for users. If left to their own devices, app developers would release anything and everything whether it had merit or not, in the hopes of earning even a tiny bit of a buck.

That’s not to say that I have nothing but a big warm and fuzzy feeling for the review process, just that it’s like going to the dentist. It’s painful, but you’ll thank them later in life when your teeth would otherwise be falling out – or, in the case of the App Store review process, when the app store would otherwise be overrun with endless seas of buggy and non-functional crap.

Most developers out there seem to vilify the app reviewers, making them out to be legions of sadistic bureaucrats who like nothing more than to waste developer’s time. I’ve never been comfortable with that, because people simply don’t work that way. The app reviewers don’t have an easy job.  They’re not developers, they don’t know how to write apps, they just review them to ensure they meet the guidelines Apple sets forth.

So when they reject your app, it’s not because they’re out to get you, they’re just enforcing policy.  If they make some assumption about your app, perhaps you’re not giving enough information to help them along?  There’s a comments field that you can use to help the reviewer of your app do their job, instead of throwing an app over the fence and saying “Here, take that”.  They don’t owe you anything, and are simply making sure that they cover their asses.  Could you imagine how bad it looked on the guy who reviewed the “Shaking Baby” app? I’m not sure if he lost his job, or just got seriously reprimanded, but this is the sort of thing these guys are trying to prevent.  But because of the black-box nature of the whole process, it’s easy to jump to conclusions.

Finally, before I dig into the meat of my conversation with my App Store app reviewer, I want to point out a few things that many developers seem to have forgotten in their haste to get their apps released:

1.    The app store is a voluntary process; you don’t want to play by their rules, you don’t have to.
2.    All developers signed an agreement that states Apple can choose to reject any apps they want based on their own reasons. There’s no human right’s violations committed when Apple decides that your app isn’t fit for the store for some reason.
3.    Apple is a business, whose goals are to advance their stock and market position for their investors. While some of Apple’s decisions may seem confusing from outside the black box, keep in mind that they are prone to keeping secrets until they throw down their big announcements at whatever annual conference they’re attending. So there are sometimes more reasons why they wouldn’t want some feature leveraged by app developers if they plan to do something much the same themselves. Is it fair? No. Is this what they’re doing? I have no idea, this is speculation on my part.

Now that I have that out of the way, I’d like to relate to you my conversation with Steve from the App Store.

(more…)

Build process experiments with PhoneGap

8 Jun

I’ve made some quick updates on the train this morning, and ended up creating a Bourne shell script in the iPhone directory of PhoneGap for renaming a brand-new PhoneGap fork to whatever your project is called. This also works with the previous changes I made to my buildprocess branch, meaning that when you’re done, you shouldn’t have any references to PhoneGap in your code at all. It also makes developing quite a lot easier, since renaming my XCode project file by hand is cumbersome, and needs to be done every time I start a new project.

(more…)

PhoneGap gets a fancy new demo

5 Jun

The PhoneGap demo is really starting to grow beyond the capacity of a single screen since tons of new features are being added all the time.  It’s even showing a few examples of the tab and navigation bar features, but they didn’t really do anything beyond just throwing out alerts and log statements.  I decided to change that to show just what’s possible with a PhoneGap app.

(Forgive me for the ugliness of the video…this is my first upload to YouTube, so I had assumed I could resize the embedded viewer to fit the aspect ratio of the original).

I’m pretty excited about it.  Not only does it give developers a starting place for developing apps, but it allows us to improve the demos to give the user a better experience.  I’d like to show a Canvas graph of the accelerometer values, or even show a rolling ball in a box to see how the accelerometer can influence JavaScript.

Minor PhoneGap Alert updates

27 May

Last night, and on my commute in to work this morning, I made some updates to my UIControls branch on Github, largely around adding callback and event support to the Alert notification code.

I’ve been working on providing more feedback into JavaScript from the commands run inside of Objective-C.  So far PhoneGap has been largely one-way, you push actions into PhoneGap and maybe you get some sort of response out in some general sort of way, but most of it has involved polling mechanisms.  Well the DOM and JavaScript in general has a native facility for dispatching ad-hoc events.  And it’s super easy to call from Objective-C, if only a little bit verbose:
[webView stringByEvaluatingJavaScriptFromString:
@"(function(){ "
"var e = document.createEvent('Events'); "
"e.initEvent('alertClosed', 'false', 'false'); "
"e.buttonIndex = %d; "
"document.dispatchEvent(e); "
"})()",
buttonIndex
];
It looks a little complicated, but it really isn’t.  It’s calling some code in an anonymous function closure so this doesn’t leak any references or variables into the global scope, creates a DOM event, sets it with a custom event name, adds some arbitrary properties to it, and dispatches it against the document element.
This same pattern applies everywhere some event occurs, and something in the JavaScript side of the gap:// barrier might be interested in it.  Listening to this event is as simple as doing:
document.addEventListener(‘alertClosed’, function(e) {
debug.log(“Alert box with button ” + e.buttonIndex);
}, false);
Pretty simple, and super flexible.  If you’re interested in an event, you bind an event listener to it.  If you’re not, you simply ignore it.  I’m pretty excited about this design pattern since it reduces the complexity of having to loop and wait for something that might never happen.
Update: Oh, I almost forgot.  The main reason for doing all this is I added the capability to add a second button to the Alert popup.  So you can do “OK / Cancel”, or whatever else you want.  But doing so necessitated adding callback support so you could tell not only when the user closed the alert, but so you could tell which button they pressed.