Over the last couple of weeks I've used Twitter to ask for user recommendations on Hungarian, Recipe, and World Cup apps. It seemed unfair to keep the results to myself.
I also recently had the pleasure of working with a Apps for Good, a program from CDI Europe that teaches young people how to create apps that change the world - a philosophy I could not possibly agree with more. The class I was involved with recently graduated, and published 3 new apps to the Android Market in the process.
So, for your enjoyment (and with limited commentary) here are some of the apps I've been checking out recently.
Apps for Good
Stop and Search: Really useful reference app that walks you through your rights and obligations when you're stopped by the police in the UK. Bonus points for providing a mechanism for rating and mapping the experience, as well as viewing a map of other reported stops.
StudioPhly: For aspiring musicians, this app will let you find a local recording studio with the gear you need.
StudentVoice: Lets prospective students find out more about the prospective Universities.
Some Hungarian Apps
Ball Madness (by A-Droid): A satisfyingly difficult bouncing ball puzzle game. Recommended despite my difficulty in getting past level 3 :(
VibraSeq (by A-Droid): Love this. A sequencer to create complex device vibration patterns. But wait! You can export the recorded vibration patters for use in 3rd party apps that support them.
Names (by Elek, Márton): Simple widget that tells you what Hungarian name day it is. Bonus points for searching your contacts and triggering notifications to remind you of anyone's name day.
GPS Status (by EclipSim): There's a few apps out there that will show you the position, strength, and details from the GPS - but from what I've seen this is the best of them. Nice UI, lots of information, perfect for the data obsessives amongst us.
Recipe Apps
Cooking Capsules (by Smart Capsules): Recipes + shopping list + video of the recipe being made. An ADC1 winner, it's an oldie but a very goodie.
Epicurious (by Condé Nast Digital): This seemed a popular choice, and with 28,000 recipes I can see why.
World Cup Apps
Goal.com Mobile (by Handmark): Live scores, breaking news, good stuff.
World Cup News Pro (by Mippin): All the World Cup news for all the teams you follow, presented in Mippin's familiar flip-card UI.
Sun Football (by News International): Live scores, highlight videos, and world cup news from The Sun newspaper.
I had the honour of presenting the first Android session of Google I/O 2010, and it was clear very early on that Android was going to be a popular topic.
The room started filling about half-way through the day one keynote. By the time David Glazer was wrapping up, there were no empty seats. By the time I got started there were around 1,000 people packed into the 700 seat session room and the fire marshal had shut (and guarded!) the doors to stop anyone else from joining us.
A Beginner's Guide to Android
I was supposed to present "A Beginner's Guide to Android". I chose to interpret this title liberally, and quickly segued into "Android Best Practices for Beginners".
Regular readers should recognize many of these tips as being remarkably similar to the suggestions I make during my Android App Surgeries.
Standing Room Only SOLD OUT!
The door guards never left. With people setting up camp once they found a seat, there were times when speakers found it difficult to gain entrance. With people locked out of each session, it's great that the video and slides for all the Android I/O sessions are now available.
There's some interesting discussion on Moderator, Buzz, Twitter, and in the comments of my last post asking you guys to tell me what you mean when you say "fragmentation".
My theory (stolen shamelessly from Dan Morrill) is that the term has been overloaded to the point of uselessness. The aim of my previous post is to unwrap the (genuine) concerns hidden within this term to allow us to discuss them without dissolving into an argument over the semantic meaning of one word.
I'm going to let the discussion continue for a while but I'll definitely respond to some of the most prominent / popular(?) issues soon. In the meantime I wanted to highlight some tweets I got from NinjaCyborg on Twitter.
He raises some interesting points, which I'll respond to, but I wouldn't have considered any of them to be good examples of fragmentation. For the most part you could happily substitute "openness" or "annoying" depending on your point of view:
Fragmentation is launching apps that only run on the new OS release when the previous one barely had a 6 month lifecycle.
Fragmentation is allowing licensees to ship hardware that isn't powerful enough to run your OS and makes web apps crawl
Fragmentation is changing the browser location API in between 1.6 and 2.0
Fragmentation is not including basic APIs for things like Bluetooth OBEX so we have to hit the hardware. OBEX is a basic, fundamental part of Bluetooth. Not complying with the standards == fragmentation
Fragmentation is pretending most Android users are on 2.1+ when there are still phones being sold on 1.5 and 1.6 with no upgrade
Fragmentation is letting your licensees choose whether to have browser chrome or fullscreen browsing
That doesn't make his questions any less valid, but it does demonstrate just how overloaded the term "fragmentation" is.
[To make keeping track easier, comments for this post are closed. Please use Moderator or the comments from the previous blog post to continue the discussion]
Dan Morrill, Google open source & compatibility program manager extraordinaire, wrote a great post on compatibility on the Android Developer Blog yesterday. It explains - in some detail - why device and platform variety is a good thing for developers, and what the Android team are doing to make sure it stays that way.
Within the post, Dan makes what some might consider a bold claim:
Because [fragmentation] means everything, it actually means nothing, so the term is useless. Stories on “fragmentation” are dramatic and they drive traffic to pundits’ blogs, but they have little to do with reality. “Fragmentation” is a bogeyman, a red herring, a story you tell to frighten junior developers. Yawn.
If that pull quote makes you angry, I strongly suggest you go ahead and read the full article. Seriously. I'll wait.
By reading it you'll learn all about the Compatibility Definition Document [PDF] and how the Android Market and Compatibility Test Suite are used to ensure that the apps you write will work consistently across all compatible devices.
As an apps developer, Dan addresses my concerns completely. As long as there's a process in place to ensure I only need to write one app, launch it in one place, and know that it will behave as expected on any device for which it's available, I'm happy.
Judging from some of the abuse I get when I link to the updated platform distribution graph, or urge developers to start using new APIs when we release a new SDK, it seems some people have Strong Opinions on the matter. So, if having read Dan's explanation, you're still angry (or angrier still), I'd be interested in finding out why.
As Dan says, fragmentation has been used as a catch-all for "things that are different", making it impossible to have a meaningful conversation around any of the individual topics. I've created this Moderator page to find out what YOU think is a "fragmentation" problem on Android -- and more importantly why you think this does / could cause issues for developers -- hopefully while avoiding an argument over what "fragmentation" is or isn't.
I've spent the last couple of weeks preparing for, rehearsing, and presenting at Google I/O. As a result, I skipped last week's App Surgery.
I'm going to ease back into things this week by taking a look at a very simple app: Simple GPS Info. It's a simple app that displays some additional information from the GPS - including the relative position of the satellites being used to triangulate your position, and the latest GPS fix accuracy.
Once you've been found, the app then lets you share that location.
Next week I'd like to tackle something a little juicier, so be sure to nominate your own app, or vote for something substantive on the Moderator site.
User Experience
The primary user experience for Simple GPS requires no user interaction. You launch the app, wait for it to get a GPS fix, and then observe the results. With limited user interaction it's particularly important that you find effective ways to engage the user and keep their attention.
GPS Status starts off well by keeping things simple. The screen is (relatively) uncluttered with the data displayed clearly and intuitively without any unnecessary distraction.
Generally speaking, there's too much blank space. The text could be bigger, as could the compass dial - there's no reason a third of the screen should always be blank. With no user interaction the data is the only thing engaging the user, so it needs to really stand out.
On the plus side, the latitude, longitude, and accuracy return values are all of predictable fixed length, so it should be easy to optimize the UI to make the data as visible as possible.
There are some specific UI choices that I think detract from the apps usability:
The app has hidden the standard title bar, and replaced it with a custom version. Generally users prefer familiarity, so given that the replacement bar offers no additional functionality I would avoid replacing it.
Getting a GPS position fix can often take longer than your screen timeout, and with no user interaction you risk the device going on standby before your location is found. It's worth considering asking the Window Manager to hold a WakeLock until the first GPS position is found. Thereafter it would be a useful menu option for people who want to monitor changes.
It would also be good to know how far along we are at getting a lock. Perhaps show an overall signal strength that gives and indication of how many more satellites are needed before a result will be available?
Scientifically speaking, precision and accuracy are different things, GPS result quality is usually related as a measure of accuracy.
Landscape mode has been disabled. As an alternative, I'd consider creating a different layout optimized for landscape orientation.
The one area of interaction is around sharing your current position. It's a pretty good idea, but the implementation could do with some more polish:
The share button looks out of place. I'd consider moving it into an Activity menu rather than cluttering the screen.
If you try to share a position before a GPS lock has been found, the toast displayed has a number of spelling and grammatical errors that make the app look significantly less polished.
Using a URL shortener adds a dependence on an Internet connection that isn't strictly needed. Currently the app fails if no Internet connection is found - perhaps a better alternative would be to fallback to the full-length URL?
The shared position page is hosted on a private domain. This is great for allowing customization of the data being shared, but it might put some heavy load on your servers! I'd consider making the sharing data more generic. Using the Google Static Maps API you can create a pretty good custom map-based landing page.
Android Features
I briefly considered suggesting a Live Wallpaper or Widget, but the power implications of such a thing would quickly make it untenable.
Instead, I'd like to suggest use of the Reverse Geocoding Maps API. Using this API you could find the street address of your current location, adding additional context (and engagement) to the app, as well as additional information to "share".
Stability / Performance / Risk
Stability-wise -- no crashes, no failures.
I did notice one possible issue. If you launch the app with the GPS disabled, it prompts you to allow it to force it back on.
It's bad form to modify settings like this directly. It would be better if it displayed a message (similar to Market with background data disabled) suggesting that you can't use the app without GPS and offering a link to the appropriate settings page.
If you say yes, then exit the application and disable the GPS, reentering the app doesn't prompt you to re-enable the GPS.
Get Your App Reviewed!
If you'd like to see your app reviewed, you can self-nominate at the moderator site. You can also go there to vote for which app you'd like to see reviewed.
In another life, a touch over 4 years ago, a job opening on the Google jobs site caused me to speculate on the imminent arrival of GoogleTV - a cooperation between Google and hardware manufacturers that would bring the power of Google search to your TV viewing experience.
A regular TV that I can write code for? That sends me to my happy place.
Let me start of by saying that I'm not a part of the GoogleTV team. I don't have any insights into their plans beyond what they talked about during the day 2 I/O keynote.
The focus of that keynote was GoogleTV as a platform for the web - letting you consume web video, use apps, and surf websites on your TV. Obviously that will be cool, but web on TV isn't what excites me.
What is? Android. Being able to write apps is what got me interested in computers to begin with. I didn't own a smartphone until Android provided a free / open opportunity to write apps for mobiles. Now GoogleTV promises to deliver a platform me to to code for my TV.
GoogleTV is an opportunity to develop apps on one of the most widely used content consumption platforms on the planet.
Over the last few years we've seen apps transform mobile phones into platforms for innovation - dramatically changing the way people use their phones. GoogleTV could do the same thing for the television.
During the keynote we saw an app that added real-time translated subtitles. Seriously. How cool is that?
Imagine the opportunities that gives you as a developer, particularly when combined with Cloud to Device Messaging? Shazam listening to your movie (in the background) to compile a soundtrack. A click of the remote can add the ingredients from a cooking show straight to your Ocado basket. Pandora (or Spotify) can let your TV play a collaborative playlist.
That's not to mention the immersive experience for apps that already exist for Android. News, shopping, music, picture galleries, restaurant guides - and perhaps most importantly - games.
I particularly like the idea of using my GoogleTV in combination with my Android handset.
In my experience, watching TV is communal. Rest assured, the first time someone interrupts my movie by loading Shazam or switches the playoffs into picture-in-picture to check the box score on the browser they will experience my displeasure by way of a shoe to the side of the head.
That's where C2DM and background services come in. Apps can run silently in the background, waiting for me to "pull" (or push) information from / to the TV to / from my Android device.
It's up to us to create innovative experiences that make people change the way they experience TV.
Just as great apps and mobile websites have driven a transition towards internet connected smartphones – a different brand of apps and TV websites can drive users towards internet connected smart TVs.
So I have two questions:
What's more exciting for you: Web on TV or Android apps for TV?
What apps (web or Android) are you going to create?
A couple of weeks ago I published my first Android App Surgery, a technical review of MySettings from JQSoft. One of my UX suggestions was that they drop the "Exit" menu item. This turned out to be more controversial than I expected and soon dominated the discussion in the comments.
So, when should your app include an exit button?
The Short Answer
Never.
The Long Answer
Your app doesn't need an exit button. It really doesn't. Arguments to the contrary can generally be summarized as:
Users expect it.
It's a way to let users say "stop doing everything and stop consuming juice".
Do Users Really Want It?
Let me posit this assertion: no they don't.
Of the apps that ship with the device (Gmail, Contacts, Maps, Gallery, etc.) exactly none of them include an exit button, and most users are comfortable with that. Nonetheless many developers are adamant, "I added it after users demanded it!".
Fair enough, so why do some users demand an exit button? How do they cope with the bundled apps without an exit button? In my experience what they really want is:
An unambiguous way to guarantee that an app will stop consuming resources (battery, CPU cycles, data transfer, etc).
The Goggles Do Nothing!
Many users perceive that an exit button implements this requirement and ask for it to be added. Developers, looking to please their users, obligingly add one. Shortly thereafter they both fail.
In most cases the exit button simply calls Activity.finish. This is exactly equivalent to hitting the back button. Exactly. Services keep running and polling keeps happening. Users may think they've killed the app but they haven't, and soon they'll be even more annoyed.
Exit behavior is now ambiguous. Should your exit button just close the Activity, or should it also stop all associated Services, Receivers, and Alarms? What should back do? What happens if they hit home instead? What happens if your app has a widget? Should the exit button stop that from updating too?
The solution is to make the back button behave as you'd expect the exit button to. Better yet, simply stop consuming resources whenever the app isn't visible.
Users: Consider this. If an app needs an exit button because the back button doesn't properly manage resource use, what do you think the chances are that this exit button will be implemented properly?
Kill Everything When Not in Use
As soon as an app isn't visible its onStop handler is fired, as soon as it's not the foreground Activity onPause is triggered. This happens no matter what the circumstance - including hitting the back or home buttons or selecting a notification.
At this point (ideally within onPause) you should behave as though your user has hit exit. Location and Sensor Listeners should be removed, Services stopped and unbound, and Intent Receivers unregistered.
Once your app moves back to the foreground - triggering onStart and onResume - you hook everything back up.
"Sure," you're thinking, "but what about apps that need to run in the background?"
Foreground Services and Ongoing Notifications
Some applications, such as turn-by-turn navigation and music players, need to run (and use resources like GPS) while invisible. This is generally achieved using a foreground Service. It's also the only reason for creating a foreground Service.
Users should always know if such a Service is running, and be provided with a simple way of unambiguously turning it off when it is. In navigation there's an "exit navigation" menu item. Pausing playback in a music player is enough to kill the playback Service. In both cases ongoing notifications provide a simple shortcut to the app, where you can easily stop the Service.
As far as the user is concerned, if the app isn't visible and there's no notification icon it's not consuming resources. If there's an icon, it's running in the background and I can click the notification to go turn it off.
Background Services and Polling
Some applications (such as News & Weather) need to occasionally run in the background to get updates. Whenever possible use inexact repeating Alarms to schedule your updates, and then kill your service as soon as the update is complete.
This will help with resource use, but is still only half the answer. How can a user demand the app stop using resources completely?
What's the easiest way for me to prevent every app from transferring data?
Settings > Accounts & sync > Background data
Unchecking this should ensure that no app send or receive data while it's not visible. However: This needs to be enforced at an application level - so if this comes as a surprise to you have a fix to implement and an update to go push.
Go ahead, I'll wait.
Offer Users Options
Provided the user is cool with background updates in general, you need to let them adjust the frequency - or disable them - for your app. Be conservative by default. If users aren't getting updates as quickly as they want they'll look for a way to increase the frequency.
Be Adaptive
A Twitter discussion from this post resulted in a suggestion that "Android should offer a way to listen for low battery so that an app can be more conservative with it's use of resources." Register a Broadcast Receiver and thou shalt receive.
You can also monitor for things like connectivity status and type, so you can disable updates when there's no data connection, or modify the frequency based on the connection type.
In each case it's always good practice to offer these tweaks as user configurable options.
Conclusion
If you build an application that's predictable, configurable, and unambiguous your users won't ask for an exit button. The first time they see an unknown background Service that's been running for an hour, or the GPS icon unexpectedly starts flashing, or the device gets hot while in their pocket they're going to get narky.
Next on my hit list: Splash screens, task killers, and modal "loading" dialogs.
Unlike last week's app MySettings, which provided shortcuts to existing functionality, AndCam3d offers something entirely new. Using a SurfaceView to show a live camera preview, it allows you to take multiple photos from different positions - using them to construct 3D images.
There's a particular UX challenge associated with introducing a user to novel functionality while keeping it simple, intuitive, and easy to use.
Unlike traditional software, it's unlikely that your users will know anything about your app beyond the title and the description from the Market. So when introducing a new workflow users need to be able to get started quickly, before they give up and claim it "doesn't work".
AndCam3d does this well by displaying up a set of instructions (with images!) the first time the app is run, an approach similar to that used by Google Goggles. In this instance Dialogs are used, overlaying the instructions over the camera preview. Personally, I feel that Activities might be a better fit, and have these additional observations on the instruction screens:
Having the camera on and displaying a preview in the background while I'm reading the instructions causes the app to take longer to start, and drains battery while I'm reading the instructions.
Using Dialogs over a landscape-only Activity restricts me to reading the instructions in landscape mode.
Consider renaming the "cancel" button to "continue" (or similar). You're dismissing the instructions, not canceling an action.
There are links within the instructions to websites - use Linkify to make them clickable!
In Windows applications an ellipsis (...) at the end of a menu item means "opens a dialog". In mobile apps this isn't a well established metaphor. I'd suggest using an arrow, such as the one used in the system settings to indicate a dialog or new Activity.
I really like the UI for taking photographs.
Having the two stateful eyeball buttons in the bottom left and right corners is an intuitive way to guide user action. I think it could be even better with the following minor tweaks:
When taking my first picture I would have appreciated more guidance. A tutorial like on-screen guide ("click here to take the left-hand picture", "now click here to take the right side", "now click here to compose the stereograph!") - for the first picture only - would have helped me get up to speed more quickly.
The eyeball icons (particularly the hands) aren't high-res enough to look good on the Nexus One.
This app is new, but the basic action (taking a photograph) is familiar. I like the way the new functionality has been incorporated, but I'd love to see some of the UX from standard camera app integrated here. The good news? The camera app is open source, so you can totally steal this stuff:
I'd like to review of each image I create, and an onscreen icon link to the last image I constructed. Clicking it should display the last image so that I can evaluate and manage it. Using the current UI it wasn't obvious to me where my new stereographic image had gone.
Like the camera app, I'd like to see the "Share" and "Send" menu items moved to the (new) image preview Activity. Neither of these verbs make sense without the context of an image.
The "Share" menu item links to a custom "share via Flickr" dialog. I'd love to see share use the standard sharing Intent (annoyingly named Send) based on the last / current image. To include the Flickr sharing, I'd create an Intent Filter to listen for the Send Intent to enable your app to share any image via Flickr, not just the stereograms I create.
Finally, it's great to see the standard Menu system in action, and the Preference Screen too -- especially the use of the standard icons for preferences and help. Without being a pedant, I'd suggest being even more consistent with the system defaults by:
Sticking to greyscale images for menu icons.
Renaming "Preferences" to the more commonly used "Settings".
Android Features
It's a great app, and there are a couple of pretty cool Android features you might want to consider to make it sparkle a little more uniquely.
Live Wallpaper. Why not allow users to set their latest wigglegram as a wallpaper? Live Wallpapers are dynamic, so you could easily create one that would quickly switch between two images to display a wigglegram.
Camera Parameters. Android 2.0 supports modifying camera settings and effects. It would be great if it allowed users to set some camera parameters before taking each picture.
I did notice that on the Nexus One it requests an invalid camera preview size. To avoid potential hardware-related failures, always check to see which preview sizes are valid before setting one.
Get Your App Reviewed!
If you'd like to see your app reviewed, you can self-nominate at the moderator site. You can also go there to vote for which app you'd like to see reviewed.
This post is the first of what will (hopefully) become a regular series of Android App Surgeries. You can vote for which app I should review next, or nominate your own app for review on the Android App Surgery Moderator page.
As an Android Developer Advocate at Google I work with developers, helping them get the most out of Android so they can provide their users with the best experience. An important part of that is using apps, figuring out what they do well, what they could do better, and what could really make them sparkle.
A lot of apps make similar mistakes (and leave out the same functionality). Last Wednesday I wondered aloud on Twitter if sharing my opinion with a wider group might be useful. The response led me to create this moderator page for people to nominate their apps for me to review publicly.
The goal is to highlight Android best practices for you guys to use in your own apps -- more of a code review than a book review (though without seeing any code). I won't be giving ratings out of 5, describing the app in detail, and telling you why you should (or shouldn't) install it. I will be sharing my opinion on how the User Experience (UX) could be improved, which additional Android features could be added, and how stability / performance / battery life could by optimized.
It should go without saying that while I'm a Google employee, the opinions and suggestions made on this site are my own, and don't necessarily reflect the opinion of my employer. Also, they're my opinions - I'd love to see if other Android users agree with my thoughts.
MySettings is a relatively simple app that displays a single screen of shortcuts to some of the most commonly used system settings and toggles.
I’m actually really glad this was one of the most popular nominations last week because it lets me talk about some common UX stuff that I'd like to cover.
User Experience
The overall UX is pretty good - the layout is simple and intuitive, it looks good and works well in both landscape and portrait orientations on both HVGA and WVGA devices. In particular I liked that it featured:
optimized layouts for landscape and portrait views (how-to).
screen size and resolution independence with optimized high-res assets (how-to).
support for trackball navigation (hopefully using StateListDrawables).
A PreferenceScreen to implement "standard" application preference screens.
Like a lot of apps they've implemented some custom UI behaviour.
One of the beauties of Android is the freedom to do whatever you like when it comes to UX, but with freedom comes risks.
The app is presented in a partially transparent floating window. That's pretty unusual and I found it a little off-putting. I've seen this before, but more commonly only when the app is launched from a widget.
The custom menu. Pressing the menu button brings up a menu, but rather than the standard menu mechanism they've implemented a totally custom UI. This introduces some potential UX issues:
It's unexpected and unfamiliar. I know what to expect when I hit menu, a custom menu makes me stop and think about what I'm looking at and how to use it.
It doesn't include the text labels I'm expecting, and it doesn't use the standard icons I'm expecting (particularly for accessing settings).
It doesn't support trackball navigation.
The regular menu is modal, this one isn't.
The menu has an "Exit" Button. Thanks to the Android application lifecycle there's no need for it - pressing "Back" will exit the app just as effectively.
The "About" dialogue doesn't derive from Dialog and pressing back exits the app rather than closing the dialogue. An alternative is to use the AlertDialog and completely replace its UI. It's also good practice to let the Activity handle the Dialog lifecycle.
The standard behavior for a long-press on Android is to display a ContextMenu. In this app a long-press performs an alternative action (opening a contextual settings screen). While useful, overloading an existing UI metaphor is risky.
Enabling or disabling WiFi and Bluetooth doesn't provide any feedback on what's happening. They could use Toasts to provide updates. The system broadcasts Intents that announce changes to both WiFi and Bluetooth device state.
A Live Wallpaper is fully dynamic and interactive, so you could implement the entire UI as one, though with homescreen real-estate being crowded as it is, a widget might be better.
I'd love to see them include a widget that looks just like one of the settings buttons. It could use a configuration Activity that lets users select which of the settings buttons they'd like it to represent. Then you could add multiple, different, settings shortcut buttons to the homescreen.
Stability / Performance / Risks
The app stability is great (I got no crashes) and it's nice to see that no unnecessary Services are being created.
One thing that worried me a little is that the app is directly toggling some system settings. Earlier releases have moved some of these toggles (notably GPS) into the read-only secure settings table. It might be worth confirming the settings are directly modifiable, then falling back to open the right page in the System Settings if they aren't.
Hopefully you guys found that useful
Later this week I'm going to take a look at AndCam3D. If you'd like to see your app reviewed, you can self-nominate at the moderator site. You can also go there to vote for which app you'd like to see reviewed.
If I get enough interest, and have the time, I'll try and do these on a semi-regular basis.
One of the fun things about being a Googler are the opportunities that come along to work on unofficial ad-hoc projects using a bunch of different Google technologies. It’s even better when you get to do it while helping charity. I got the chance to do just that in the lead-up to the 2010 London Marathon.
About a month ago Phong Luu, Jean-Laurent Wotton and I offered to help Stephen Woodford raise some money for NABS. Stephen volunteered to run the marathon, we pitched in by building an application to let people follow his progress.
Why Build New?
Existing tools such as Latitude and MyTracks didn't offer the real-time, high frequency live updates needed to allow anonymous visitors to track a marathon in real time. The goal was to create a simple web app using Street View and Maps that didn't require a login that got updated as Stephen was running.
What We Used
AppEngine was used to create a server to receive position updates during the race.
A purpose-built Android app transmitted updates to the server at a regular interval during the race.
Google Maps and Street View displayed each updated position along the route.
Practical Considerations
Before Stephen took off there were a few practical considerations. In particular I needed to be wary of two things: battery life and data signal availability.
To maintain battery life we made the frequency and minimum distance of our location update requests user configurable. During testing we found that 5 minute intervals over 1km was a good compromise between real-time updates and battery life.
As any Londoner knows, a 3G data signal isn’t something you can take for granted while running (literally) around the city. To account for this I created an upload Service. Each new location was recorded into a Content Provider along with a timestamp. Using a combination of Alarms and Broadcast Receivers, I could then start the update Service at semi-regular intervals - or when a data connection was available - and upload all the pending updates to the server.
The Future
With the 2010 race now over, the team is looking for ways to improve our custom solution to offer a generic tool for future marathons. To do that we'll need to:
Update the Android app and AppEngine server to support tracking multiple runners simultaneously and in different races.
Add compass direction so that Street View shows the direction the runner is facing.
Earlier this year I was lucky enough to be a part of Google London's "Translate for Animals" April Fool's joke.
To avoid confusion it got taken down shortly after April Fool's, but in the short time it was live it had tens of thousands of downloads and over 1,000 comments (averaging 5 stars!).
I've gotten some requests for the app to be made available for people to cruelly torment their kids drunk friends, so I've put the app back on the Market as "Animal Translator". Enjoy!
Yesterday Tim Bray, Google's newest Android Developer Advocate, shared his Content Provider Iterator. Before he shared it with you, he showed it to me to check "is this sick and twisted?". Here (with some additional colour) is what I told him.Let me start with an admission. I have a deep mistrust of metaprogramming tricks in statically-typed systems. I've spent far too much of my working life unpicking frameworks created to simplify complex parts of existing frameworks. Often as not, the class descriptions could be summed up as "I don't understand this way of doing things -- this class makes this framework behave the way I expect."
There's often a good reason the original framework works the way it does. In Android that reason is performance. When developing for servers and PCs simplicity and familiarity is often a good trade-off for a marginal performance hit. In mobile it isn’t.
That said, these sorts of helper classes can improve code readability and cement best practices so I owe it to Tim to justify my unease.
The Problem
First off, let’s look at what we’re trying to solve -- iterating over a Cursor.
Tim’s code lets us do this:
Reader calls = new Reader(Call.class, activity, CallLog.Calls.CONTENT_URI);
for (Call call : calls)
String number = call.getnumber();
The alternative in “normal” Android is this:
Cursor cursor = getContentResolver().query(CallLog.Calls.CONTENT_URI, null, null, null, null);
while (cursor.moveToNext())
String number = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));
cursor.close();
Certainly Tim’s solution is more familiar to those of us who prefer working with Objects to Cursors, and we save a line of code, but what’s the cost?
Allocating memory (and performing garbage collection in a resource constrained environment is expensive. Every time you extract information from a Cursor Using this class, you're creating a new object for each row, and allocating memory to store every column value too.
For every iteration you’re using reflection to create a new instance of your row object. During the construction of every object you use reflection to find a Setter for each column, then again to invoke the Setter for each column.
That’s a lot of reflection and it won’t take long to feel that hit on your performance.
3) Avoid Method Calls
Method calls are (comparatively) expensive - enough so that it's generally considered good practice in Android to avoid using Getters and Setters within a class. After creating objects you need virtual method calls to allocate each of the row values used, and again to extract them.
4) Minimize frequency of object creation
What's neat about this solution is it's dynamicsm, it creates your new objects each time you to iterate over the list without needing to maintain a separate collection.
But there is a risk here. Because it's dynamic, the generic solution doesn't offer a solution for monitoring changes to objects or the addition or removal of rows. To handle this you'd re-iterate over the list whenever the underlying dataset changes - reinforcing the performance issues described above.
5) Static state and thread safety
As written, this code isn’t thread safe, and maintains the current position of the cursor as a state variable. Using the same Reader to iterate over a cursor in two threads will come to grief very quickly indeed!
Conclusion
The Call Log has a half dozen columns and maybe a hundred rows, so you might get away with this. But what happens when you do it over contacts? Or email? Or Ocado’s entire grocery catalogue? It’s a dangerous pattern because its performance cost is dependent entirely on the shape of your dataset.
Imagine the case for a retailer with a database of several thousand products, each with a dozen String-based columns. Say 2,000 products with 12 string rows. That’s using reflection over 50,000 times and creating nearing 30,000 objects. That’s an awful lot of reflection and object creation to save a line of code.
Different platforms require different thinking. In my experience, becoming comfortable with how these systems are designed to be used is vital to understanding the best ways of implementing solutions. To quote an Android engineer on the subject, “I understand that coming from Ruby, one would want objects generated for you, but there is such a huge performance cost on mobile devices that it simply doesn't work.”
Those of you who follow me on Twitter may have noticed an unusual drop in my posting frequency over the last few weeks. I can't divulge details, but my inactivity is a result of having been head-down finishing an exciting new Android project that I've been lucky enough to be involved in with the mobile engineering team here in London.
Between the developer lab world tour and finishing Professional Android 2, I haven't had the chance to focus solely on building an Android app for far too long. It's been great to work as part of the Google team to put together something which (I think) is pretty incredible.
We've spent the last couple of days doing final testing in the English countryside. With that now completed, and the launch imminent, I'm going to stay a few days longer and take a well earned break. All will soon be revealed, but while you wait for the app to be available in the Market I thought you might enjoy some video clips I took during the development and testing process.
(Feel free to guess what you think is going on, but please don't ask me to comment on or confirm speculation. Posting these clips is as far as I'm willing to go!)
I'm Reto Meier, I work for Google as the Tech Lead on the Android Developer Relations team. I'm also the author of Professional Android 4th Edition.
This blog covers technology and programming - particularly Android - but this is my personal blog. The views expressed on these pages are mine alone and not those of my employer.