For all my talk and
activities around Windows Phone 7 I'm aware I've shown very little about what I've been working on. Here's where I start to address this.
As you may have guessed by the title of this post, I've been looking at adding Windows Phone 7 support to
PhoneGap.
For those of you who aren't familiar with PhoneGap it is "an open source development framework for building cross-platform mobile apps". It works by enabling apllicaitons written using the universal languages of HTML, JavaScript & CSS and compiling them into native apps for each supported platform.
I first used PhoneGap early last year when I needed to produce some proof-of-concept apps for the iPhone and I didn't fancy spending the time moving code to objective-C which I already had in JavaScript. (For the project in question it just wasn't worth the effort.) In the intervening time I've kept an eye on the PhoneGap project but not done much with it. I looked at its Windows Mobile support but didn't feel particularly motivated to do much with it. With the release of WP7 I found new interest in the project and am keen that apps developed for other devices/platforms can (where possible) be migrated to WP7 also. I have therefore written some code to try and implement this.
For those that are interested, the code can be found at
http://github.com/mrlacey/phonegap-wp7. I know that others have started some work on this also. (Most notably at
http://github.com/filmaj/phonegap-winphone.) I thought I would share what I've been doing to help the project. I'd already got further than the version by filmaj when I became aware of and have solved some issues they haven't dealt with yet.
So what is implemented?
In theory the easiest way to show what is implmented is show some test results. So here we are:
It passes 76 of 98 tests. Not bad. (Even if I say so myself).
As it's a shorter list, the tests that fail are the ones which relate to: HTML5 Storage, Contacts, File IO, Maps and methods which require objects being passed in their callback functions.
Some of these could possibly be implemented (File IO and possibly maps) but others just can't, due to limitations of the web browser control and the available APIs. Due to the way that interop with the browser control is implemented it's only possible to pass strings between the JavaScript and the C# code, it's not possible to pass objects to callback functions directly. In my code I have other functions which act as a wrapper to the callback functions so that they are passed appropriate objects but the automated tests don't pick this up.
It's probably a good time to point out that all I've done has only been tested in the Beta emulator. (I'd love to have a real device to test this on. Hint, hint!) Because some functionality requires can't be tested in the emulator, some of it is untested (e.g.
navigator.notification.vibrate()) while other code always returns the same default values in the emulator.
How much functionality is implemented?
The following functionality is documented as supported across all platforms which PhoneGap supports:
Accelerometer: GetCurrentAccelleration is implemented but the watcher functions are not as these cannot be tested in the emulator.
Camera: getPicture is implemented but currently doesn't work properly as tombstoning of the app currently means that we lose all javascript references and so we don't have access to the callback.
Supporting tombstoning is the biggest issue with the current code. This could probably be worked around by storing all relevant callback details natively so they could be kept in state across deactivation/activation but I'd like to get some feedback on what I've done so far before spending more time on this.
Device: All features are implemented in JS, but limitations of the WP7 API currently mean that not all details are populated. It should be possible to get theses details with the release version of the API.
Events: deviceReady is not implemented as I have been unable to find a way to create events in the browser. It seems this can't be done, so I have implemented the PhoneGap.available property as a test for confirming loading.
Geolocation: getCurrentPosition is implemented (but returning a hardcoded vallue in the emulator). The watcher functions are not implemented as these cannot be tested in the emulator.
Network: this is implemented
Notification: this is fully implemented.
Additionally, the following other features are also implemented:
DebugConsole: log, warn and error methods
Orientation: getCurrentLocation and the watcher functions (as these can be tested in the emulator)
SMS: Send - triggers the compose functionality
Telephony: Call - triggers the request to make a call
To enable demonstration and testing of the implemented functionality I've created a simple app which demonstrates all the implemented features.
What else?
Other points of note in the code:
- While it's possible to load a file included in the project (in the webbrowsercontrol) any files loaded this way can't reference other files (JS, CSS, image or ohter HTML files) A partial work around is to try and merge all content into a single file but this can't deal with images. The browser doesn't currenlty support the data protocol but will in the next version (according to an email I've had from the team) so we would have to live without images if we went that route. The alternative is to load all content into Isolated Storage and view it from there. This is what I've done. Also rather than specify all the files to load manually (I couldn't find a way to query these from the XAP) I'm using a T4 template to generate the list of files to load.
- I'm using a command pattern to handle the different feature implementations. I'm using an abstract base class (PhoneGapCommand) for the commands and two optional interfaces to manage the variations in types of command (IAsyncCommand & IWatcherCommand). This works pretty well but feels like it could be better. I'm keen to discuss/explore alternatives to this.
- I've implemented a custom back stack to support navigation between pages. This recreates the behaviour you'd see elsewhere if navigating between XAML pages or html pages in IE.
- Because of the time it can take to load all the files to Isolated Storage and to prevent the webbrowser control being shown before the content has all loaded correctly I've had to implement my own version of the splash screen image. To use this the image must be set to a resource. In my code I have renamed the sample image to make this more obvious.
What next?
Ideally I'd like to contribute this code to the core project but I guess that will depend on what else others have done in terms of WP7 support.
There is also the key issue of how to work with (not around) the application model and how it affects javascript which really needs addressing before this could be considered publicly usable.
Please feel free to leave any feedback in the comments below, or in the discussion I'm about to start in the
Google Group.