Edit 11/08/2010 - I was inaccurate when I stated that the NRCS WAI has only a SOAP/RPC access - it has GET and POST as well. I'm currently revising my Android app to parse the WAI XML.
First things first: it’s aboot time. I’ve spent enough time dinking around with Android that this post should’ve occurred a long time ago. So, here it is, enjoy.
Recently, I developed an Android application to access the USDA NRCS’s public Where Am I? (WAI) service. The WAI service provides land-related information from a geospatial location within the United States. This took about the equivalent of a weekend (16 hours or so), but it was spread out over about a week, so I'm still calling this an "App a Weekend" entry. Deal with it. There are a few gotchas and points along the way that are worth noting as I developed this application.
The Where Am I? service provides information for a geospatial point on the map: Congressional District Code, ID, Name, Congressperson’s name, Hydrologic Unit Code, Major Land Resource Area, City, State, Zip, and Tribal Land ID/Name, among other information. The service drills through multiple layers of geospatial data and gives back an attribute list. Useful for some purposes when doing land-based assessment as a lot of NRCS applications may do, what with them being the Natural Resources Conservation Service.
The idea for the WAI Android application came from my work inventorying potentially enterprise-ready existing shareable services at the NRCS, which ones are being shared, and which ones were intended to be shared. Additionally, some discussions with developers at the USDA about mobile access to NRCS data services needed some level of pragmatic understanding. Why not write an Android app and exercise the API just enough to make a semi-useful app and exercise the end-to-end Android dev process?

Semi-Useful Design
My intended design was to have an Android application that not only displayed a map from which the visible latitude and longitude could be obtained but also use the geolocation services of the Android device (GPS, network) to obtain the latitude and longitude. The geospatial coordinates could then be passed to WAI and the WAI attribute results would be displayed. Pretty straighforward.
The Where Am I? Service
The WAI service is written in .NET and exposed as ASMX which provides a WSDL as an API. A few issues with this right off the bat. Android has no native SOAP client to dynamically create a proxy. There is, of course the Apache Axis library, but those are huge, ~8mb, and the proxy client built by Axis is also pretty large. Size is an issue in any mobile app and including libraries not specifcally optimized for the platform's not recommended. There’s an Android implementation of ksoap2, but there were lots of comments of its usability and feasability, so I passed on that one. Additionally, XML parsing is reputed to be quite expensive in Android. Another issue is that the WAI service is hosted behind a port redirector and therefore WSDL for the service indicates its endpoint at port 42500, which is incorrect. This issue causes dynamically generated SOAP proxies to fail. The work around is to manually generate the proxy (using wsdl.exe in .NET for example) and then manually correcting the port. SOAP access to WAI seems less and less likely.
For a mobile device, it really seems like a REST/document style interface with json would be better than an RPC style interface, given the potential size of a proxy client and supporting libraries. Why not write one?
The REST Service for WAI
I wrote a very quick REST service using ASP.NET MVC2 and pushed this app to Azure, http://wai.cloudapp.net
It has a very basic human user interface and some documentation on the single existing REST method. Currently, there's one method on the controller that takes lat and lon value, calls the USDA NRCS SOAP webservice via a manual proxy class, and returns a full set of data attributes as a JsonResult object.
Creating an Azure app from an existing MVC2 app was cake - add a Windows Azure Cloud Service project to the existing solution. Publishing to Azure was surprizingly easy, with one hitch: our worktops are XPSP3 and the latest Azure SDK for VisualStudio 2010 will only work on Vista/7. I published to the cloud using my personal laptop (Windows 7).
It might’ve been slicker to use Google App Engine to host the REST proxy, but the nerd humor of a GOOG app calling MSFT service can't be beat.
Finally, the Android App
With the REST service in place, utilizing in an Android app was a snap. Obtaining a GPS/Network location from the device is well explained in the online SDK. Writing a REST client in Java within a thread is as you’d expect (although this is not the recommended pattern, see this very informative talk from I/O on Developing REST Client Applications; a talk I opted not to attend and am grateful they posted the talk and pdf slides online).
I made a main Activity class that contains the Maps MapView, one for the Aboot and WAI Results dialog boxes, and another for the Preferences (an upcoming enhancement). Two straight Java classes, a REST client to house static methods around issuing an HttpClient GET call, and an interface class for my RestRequestCallback that my main Activity implemented in order to get the info back from the threat that starts the REST call.
I obtained a Google Maps API key in order to utilize the Google Maps API, which is separate from the default Android API. It’s used in order to enable the tile service of the Maps API to function. Also, I had a development (“debug”) key per machine I was developing on (I used both my desktop and laptop to develop the app). This meant i had to keep changing the hash string that enabled the Maps API in the view layout, which wasn’t hard, just slightly inconvenient.
Testing on the emulator's really easy and I'm always impressed with the SDK's qemu running Android. Once started, it's snappy and responsive. The emulator has no GPS, so you've got to push a lat, lon to it via the DDMS emulator interface ui or via telnetting to the emulator and issuing a "geo fix lon, lat" command to simulate a location fix. Incidentally, there's a Galaxy Tab add-on for the SDK so you can skin the emulator to look like the upcoming 7" device, if you're so inclined.
Signing an application is actually really easy from within Eclipse - it’s a menu item added to the right-click context menu by the Android SDK plug-in. It’s not really that hard via the command line, either.
Publishing to the Android Market was also an interesting experience. You upload the apk (compiled Android app) and a few screenshots (optional). Once you do, there’s an entry in the developer listing. And it can’t be removed. Even if you unpublish your app, the app remains in your list (not on the Market, but in your developer dashboard for the Market). I initially compiled my app in a very generic namespace, net.bespokesystems, and then wanted to change it to net.bespokesystems.demo.RestLocation, a much better namespace. Seems like the namespace is the key for the developer dashboard, so no changing that - got to publish a new app. And wouldn’t you know, can’t remove the app from my dashboard. So, although unpublished, there’s an app entry that’s there. At the time, there were no users of the app (I’d installed the apk manually on my Nexus One), but after a few days, oddly, there were! It seems like there must be people who automate installation of apps as they’re published, maybe some feed that I’m unaware of plus a delay in reporting of installations. I’d literally had the poorly-namespaced app published in the Market for less than 20 min. I’ll have to follow up on either on the dev mailing lists or irc channel to determine some of the Market's logistics. One thing I didn't have to do was wait (I'm looking at you Apple App Store).
Using the Google Chart API for QR codes, I created the clever little QR image above that, when scanned with the Barcode Scanner app on your Android phone, directs you to the download for the app on the Market.
There are some interesting bits in the Android app lifecycle - rotating the screen pauses and restarts the app - and as a developer one has to accomodate for saving state. I got a bit into the Preferences API, alternate layouts and screen depths, and making a simple icon.
I hope to place both the Android app and the Azure MVC app in a public repository soon for anyone who wants to see some awesome slapdash code.
A few ideas on future updates:
... for the Android app
- Use a better pattern for accessing REST services
- Allow the user to change the map type, from satellite to road
- Reduce REST query timeout to accomodate for NRCS WAI service response timeouts
- General polish (release notes, proper liste provider for WAI results)
- Better control over GPS/Network/Wifi location behavior
... for the WAI REST service include
- REST methods to allow the request to specify which WAI attributes to return
- Google map for the UI piece
- Reduce timeout to NRCS WAI service and add a single retry to accomodate for the NRCS WAI service’s timeout issues
I ordered my Nexus One in the middle of the press conference, just as the
http://google.com/phone site went live. It arrived quickly, as expected, overnight. From shipping information (01/05 4:11p) to arrival (01/06 1:12p), less than a day (
FedEx 429951121750). The FedEx truck arrives around 1:30p at the local UPS store where I send my delicate goods and was leaving just as I arrived. I saw him put down two items, a flat and a box. That box was mine.
The included apps are great - first the fact that there're included and second because some have additional features from my G1 Android 1.6 versions.
Google Voice, Maps, and Mail are all solid. Google Mail has the ability to handle multiple Google accounts, which is fantastic. Previously, one had to use IMAP on the generic EMail application to connect to Google accounts other than the primary that's needed for the phone. The Google Maps application shows accuracy on the location ("accurate to 5000 meters"). Google Voice can be set up to replace your cell service's voicemail.
The Contacts app is integrated with social media - Facebook, in particular. If you so choose, Contacts will match up Facebook profiles with your Google contacts. You can jump right to a connected contact's Facebook profile and even see an excerpt of their last post. I haven't used the Cliq interface, but this level of integration between different apps is subtle, just useful enough, and not intrusive. Well done.
The Gallery app That's been demoed in the release press conference is also great, what with its connection to Picasaweb and it's ease-of-navigation. There's another app called "Car Home" which has big icons sort of in the style of what you see on car GPS's these days - Voice Search, Navigation, View Map, Contacts, and Search - all geared towards being used while in a vehicle (not driving, of course).
Additionally, there's some haptic feedback when you choose an app - a short buzz before/as the app launches, and that's a nice touch, if you pardon the pun.
The lack of the keyboard was a major concern for me - I've been a keyboard partisan since my Nokia E70 with it's flip out keyboard. Texting, e-mail composition, web browsing, pretty much everything was better with a keyboard. I've used the virtual keyboard on the G1 and found it to be sluggish and slightly inaccurate (not as inaccurate as my iPod Touch's, but still). The virtual keyboard on the Nexus One's still a virtual keyboard, but I've been able to message and compose e-mails on it without too much trouble. My main issue with the virtual keyboard is accuracy and the fact that I have to watch the keyboard to see what I'm typing (and to verify that I pushed the right letter). With a physical keyboard, the layout's familiarity is enhanced by the tactile feedback of the keys themselves. I hear the Droid's keyboard is flat as a Judy Blume character and that'd be pretty disappointing. Of course, new phone means I give it a wide berth. We'll see how it does during the day to day use.
The two touted benefits - speed and graphics - are great and need no mention, really. They're great and it's fantastic to have a first-class device (
tech specs). The speed is a huge improvement from the G1 and allows the device to more or less melt into the background. There's no longer a lot of waiting for things to start up. Other reviews state there's a slight but noticeable delay when flipping between home screens, but it's not really that annoying at all. The graphics, with the dynamic wallpaper flare and the zooming, scroll-wrapping app list, are wonderful and really gives me the comfort that I'm using a device that's been built with the user's pleasure in mind. Neither the Cliq or the Droid, with add-on UI interfaces from Motorola, or the initial G1, really had a feel of continuity to them. Google stepping up and making a set of core apps that work well and are consistent is a major boon. This set of comments is what people focus on when they talk about comparing the Nexus One to the iPhone - the consistency and premium device featureset. From that aspect, it's definitely a really good asset to the device market.
The G1, even with its keyboard, was underpowered and sometimes struggled to run Android and, a year and a half ago, there really weren't a core set of solid Android apps. The Android Market is a phenomenal cornucopia, without a doubt, but without a core set of apps out of the box, it's tough to navigate the wilds of free (and possibly poorly coded) apps when looking for common functions.
Google's added a
bunch of videos on YouTube about the Nexus One features. Take a look.
A further nice touch was a set of mp3's that was included from a bunch of artists, all but one I'd never heard of: 17 Candle, Ali Spagnola, Amanda Blank, Brett Dennen, Jackie Tohn, Lissy Trullie, Marcus Miller, Miike Snow, Mos Def, Really Addictive Sound, White Denim, William Fitzsimmons, Zack Borer.