Archive for the 'Android' Category

How To Use Analytics To Improve An App

Friday, August 27th, 2010

In an earlier post I alluded to the idea of using real usage data to improve my Last Call Widget.  Currently the widget packs three key use cases into a small and simple UI:

  • Who called last, when and on what number?
  • Show the last caller list.
  • Return the last call.

My research question focused on what extra information I should be showing, and what other use cases I should be looking to support (or to support better).

The benefits of using an analytics tool are that I get to define my own events (which are linked to specific use cases), and then aggregate huge amounts of real world usage (anonymous of course) to support my conclusions.

I want to send a big thank you to those of you who opted into the Analytics program (all thirteen thousand of you).  I don’t know who you are, but I endeavour to use the information you supplied to make the Widget more useful.

Widget Size

Widget Size

A noisy minority (i.e. 28%) of usage events were generated by people using the mini 2×1 widget, rather than the larger (and original) 4×1 widget.

Widget usage

Widget Usage

For both widgets we see an ongoing trend (observed in an earlier post) of the amount of clicks roughly corresponding to the relative size of each button.  Quick dial mode is enabled for roughly half of call button events, either due to genuine user choice or difficulty in discovery (i.e. feature has to be turned on in the options menu).

Return The Last Call?
Now let’s make the data more interesting by comparing new outgoing calls against recent Widget activity.  This will give us a more accurate idea of what the user intended to do, rather than just report on the popularity of existing buttons.

Return Call Log

Return Last Call

Of users who clicked on the Call Log button, two thirds found the number they were looking for in the list of five most recent calls, with a quarter needing to find the number elsewhere.  Interestingly, twelve percent of users went on to call a recent caller back on a *different* contact number, with half of these events being for the most recent caller in the list.

Return Call Log Without Widget
We can also make a similar analysis of new outgoing calls when there has been no recent Widget activity (i.e. the user is not using our app).

Return Call Log Without Widget

Now the “Not in History” section has grown much larger (possibly skewed by the user choosing not to use the Widget?), while the “Different number” section has grown to sixteen percent of all outgoing calls.

Conclusion
The Android UI places a large click penalty on calling a user back on a different number.  Hence current thinking is that the widget should support (a) calling back with different numbers, (b) extended call history to better support feature (a).

(a) Different Numbers

Different Numbers

When returning a call from the last caller, a quarter of the time the user will want to call back with a different number.  This supports the argument of adding an intermediate screen asking which number the user should be called on (this can be heavily optimised later).

(b) Extended Call History

Extended Call History

The last caller (i.e. first in the list) is the most popular option by far, but the second, third and forth options are also represented as more than edge cases.  Hence there is an argument in favour of creating a taller widget that displays more history items, or creating our own call log history screen to replace the native UI.

Last Caller In List

This second option would simply be an attempt to correct a perceived flaw in the native UI, by integrating the UI for feature (a) for a longer list of contacts.

Next Stage
The next step is to compare the click penalty vs. actual usage, to test some proposed upgrades for their usefulness.

The Case For Analytics

Sunday, August 8th, 2010

Metric

!! None of this is legal advice !!

Last week was a bad one for Analytics, with the *discovery* that an Android wallpaper application was secretly leaking users personal information to a server in China.  The source later backtracked on that claim, but by then the damage (mainly to the trust in having an open ecosystem for Android applications) was already done.

Google themselves weighed in by posting a list of best practices for handling user data on their blog.

I support the appropriate use of metrics and have blogged about it many times, mainly in relation to my Last Call Widget.  Access to real world data is invaluable for analysing how users are utilising an app (testing work flows, detecting bugs, etc), which eventually results in better software for everybody.

Replica Island - Player Metrics Analysis heat map

Another example I like, is how Replica Island uses anonymous player “death data” to actively improve level design.

Protect Data By Making It Non-identifiable
I am living in a country with some of the tightest data protection laws in the world. That means that whatever the laws are like where you live (if you have data protection legislation?), you are getting the benefit of the protection offered by the German legal system.

As an Analytics user, I am motivated to anonymise all data involved so I can avoid the tight compliance criteria laid down by law (i.e. data security, restricted processing, not passing through third parties).

Note: To Anonymise, means the data can’t be used to trace a specific identifiable person.  Identifiable data might be a unique customer id, zip code + age + gender combination or just a simple telephone number.  Anything the could potentially qualify, should definitely *not* be collected!

Establish Trust
The user must feel conformable that your application isn’t doing anything it shouldn’t.

This is a difficult balance to make, as most users won’t bother reading your descriptive text and will definitely not reach your privacy policy.  I had a one star comment (since removed) from a user who probably hadn’t installed the Widget, but wanted to make a point that the Market description (at the time) didn’t explain what the “Network communication” permission was for.

Permission

In Last Call Widget, I now state that the Internet permission is required for metrics - and that this is optional.

Permission Dialog

I show an opt-in dialog as soon as the user opens the application for the first time (or tries to install from the home screen).  I expect most users to read this text (although it’s not yet localised) and understand that the Widget will do some data collection.  I should say that this is also a Google Analytics requirement.

Permission Setting

For added clarity, I also show the current state of the “Data Collection” setting very prominently on the options screen.

Collect Relevant Data
Make your data relevant to what you are trying to measure.  Doing so tends to be safer for your users and makes your results easier to analyse.

The first version of Last Call Widget measured which buttons were pressed and how often, with extra events added later on to detect if quick dial or the mini widget were involved.  The problem here, is that it only collected data on features already built, and generated no relevant insights for improving the product.

The next iteration became more controversial (hence the need for greater emphasis on permissions) as it started to report call log events that weren’t initiated via the Widget.  This made it possible to collect real world data on how often users were facing various use cases, revealing where the Widget work flows were weak and needed improvement.

I look forward to reporting my findings in full in a follow up post.

!! None of this is legal advice !!

Last Call Widget - Metrics

Wednesday, June 30th, 2010

Metric

Despite all the pretty visualisations generated by the Google Analytics tool, essentially so far all it has been good for is recording how many people have been using my app.  This falls short of useful, now that I am at the stage where I want to redesign my interface to support an improved user workflow.

The next step is to come up with some kind of useful success vs. failure definition metric, which will allow me to analyse aggregated (opt-in) user behaviour and try to make design decisions accordingly.

Initially I thought this would be impossible for a “stateless” home screen Widget (with just two buttons) to collect data on wider user activity, until I realised that the widget regularly performs processing on the users call log data, meaning that outgoing calls could easily be matched against the most recent UI event, resulting in simplified (and anonymous) UI “Success” and “Fail” like events.

On my first pass, I am looking for these events:

Condition Conclusion Result
New outgoing call detected.
No recent Widget UI events.
User is not using our app. Fail
Widget “Last Call” button clicked.
No new outgoing call detected.
User wanted to check on call history. Success
Widget “Last Call” button clicked.
New outgoing call detected with same number.
User should have pressed the “Quickdial” button. Success
Widget “Last Call” button clicked.
New outgoing call detected with same contact, different number.
User should be given more dial options. Fail (add more options)
Widget “Last Call” button clicked.
New outgoing call detected for X most recent call contact.
User should be shown last X call contacts in Widget. Fail (add X list items)
Widget “Last Call” button clicked.
New outgoing call detected for non-recent call contact.
Widget used as shortcut only (use cases not relevant). Fail
Widget “QuickDial” button clicked.
New outgoing call detected for given number (call longer than 10 seconds).
User returned a call. Success
Widget “QuickDial” button clicked.
No new outgoing call detected for given number.
User inadvertently clicked on this button, or wanted to return the call with a different number. Fail

Note to self: refine this list after further experimentation, and add extra scenarios to measure the success of changes made in version 2.

Last Call Widget - Use Case Analysis

Wednesday, June 30th, 2010

Android

I am approaching the big two point nought milestone of the Last Caller Widget and feel the need to give it a cool new feature.

FEEDBACK
So far feedback from users has been mostly positive.  I have fixed a number of home screen and life cycle related issues, as well as responding to feedback from Sense UI users who felt the Widget needed more transparency to fit in with the HTC flavoured home screen.  For my next minor release I am only looking to clean up a few edge cases around withheld numbers and custom contact detail labels (both bugs) and to investigate one report of the Widget looking ugly on the Sony Ericson X10 (yet another custom home screen – still have to verify).

As of now, I am not able to reproduce any “Widget does not update” issues on the current Android Market build, on any test device (anyone still seeing this issue?).

Sequential Art
Sequential Art - Anything I damn well please!

As this is free software done in my spare time, I don’t have to religiously chase after users with minority bugs (like I do in my day job) and can instead relax and start to think about the next cool feature.

NEW FEATURES
Looking through my email (feedback@zedray.co.uk), it seems people want a larger widget (with more calls listed), a smaller widget (4:1 just takes up too much of my valuable screen space), filtering by type (lots of people just want to see missed calls), open sourced (seriously, go to the Android Open Source project for more complete reference code), localisation (Russian & Chinese), and of course SMS support (complicates the UI in surprising ways hence I  am thinking of doing this as a paid app).

Of course you can only get so far by listening to your users, which brings me back to the origin story (blog post).  Basically (for vaguely work related reasons) I found myself analysing how well the native UI on the Nexus handles key uses cases (e.g. return the last call), and found some significant gaps.

My method came from some of Russels comments on measuring UI usability based on the number of clicks required to perform a particular task.  His argument centred on how important it is that we reapply this (very well established UI metric) to objectively analyse UI on touch screen devices (tablets in his case), as developers need to redesign their UI paradigms to support a completely new way of interacting with computers.

ANALYSIS
For these measurements I have chosen a very tight scope, covering only a few key use cases (wondering what more I should be adding?).  Also, all measurements are taken after the phone has been unlocked (not a valid assumption if someone adds this kind of functionality to the lock screen or comes up with a gesture based control, etc).

User Goal Native Last Caller Widget
Who called last? 2 0
List last callers 3 1
Return last call 3 1 (2 with quick dial disabled)
Return Nth last call 3 2
Return last call, but with a different number ~5-6 ~4-5

Note to self: repeat theses tests using trackball only.

As you can see above, the Last Caller Widget performs admirably in the first four use cases, making it by far the most useful Widget on my home screen (or for anyone who uses their phone as a phone).

Unfortunately that last use case is a dozy, as it turns out I have several numbers for the people I call most (go figure), hence I am always fiddling through the clumsy sequence in the native UI:

Call log -> Call info -> View contact -> Select number.

This is made slightly worse in 2.x as calls are sometimes grouped, adding yet another click to this already tedious chore.

This issue has been addressed under the contacts tab with the new 2.x “Quick actions”, which I’ll have to investigate as soon as I have finished working my way through the Google IO 2010 session videos.

>10,000 Last Call Widgets!

Monday, June 14th, 2010

logo.png
Time for a statistics round up now that my “Last Call Widget” has breached the 10,000 downloads mark on the Android Market.

ratings.png

According to the developer console, the widget currently scores 4 out of 5 stars, taken from 83 mostly anonymous ratings.  Looking at the public comments (which are dated), it’s possible to see how several bug fixes and new features have increased the score as the product has improved over time.

Downloads
The Market reports raw numbers of 4,966 active installs for 10,814 downloads (i.e. 45%), which are good numbers for a free application downloaded off an App Store (I haven’t tried promoting it yet).  To get more in-depth information I had to abandan Flurry (due to its technical limitation) and adapt the Google Analytics plug-in to make it work with Android home screen widgets.

Unfortunately, Analytics’s web front end is designed around tracking website usage (supporting a variety of inappropriate use cases, i.e. session length), meaning I have to process the numbers somewhat before I get useful information.

Activations
enable_small.png
The widget was enabled 23,390 times in its first 41 days.  By enabled, I mean that the user installed the widget on their Android home screen while the Analytics opt-out check box remained ticked (as it is by default).

To get a more useful impression of user loyalty, we need to understand how long the widget has been present on the users home screen.  As widgets are stateless (i.e. designed not to consume system resources), there is no way to accurately measure session length as you would do in a regular application.  So instead I opted to write a simple algorithm that generates a series of custom events over time, giving us an idea of how long each widget instance has been around.

cumulative_enable.png

Custom events make most sense when shown cumulatively.  In this chart, the number of “Enable” events takes off quickly, while the first update “0″, and the second update “12″ (i.e. twelve hours on screen) report lower numbers later on (as expected).  Looking at the chart, its obvious that there is a serious gap between users who enable the widget and then subsequently go on to use it.  This could be explained by users immediately disabling the widget (possibly a bug), deactivating reporting (optional in the UI) or simply by having data switched off on their phones (very common).

cumulative_usage.png

Looking at the subsequent events, there is a good conversion of users from 12 hours onward to 72 hours (I have omitted intermediate events for clarity), upto the highest value reported of 144 hours (i.e. 12 days).

buttons.png

As an added bonus, we also get to see how often each of the widget’s buttons were pressed.  Looking at the percentages, there appears to be an almost 1:1 relationship between button size and how oftern it was used.  With later users deciding to activate the “QuickDial” mode once it became available in later versions.

My 30 minutes of fame…

Friday, May 28th, 2010

“You did well on Twitter…” was the first thing I heard after taking absolutely no questions from a room packed with Android developers.

photos2.png
Source: All photos stolen from other people off the net
(I was too busy to take any myself).

They had come to hear a real Android developer actually talk about Android development, as opposed to push some product or service (all the real developers were at yesterdays BarCamp).  I wasn’t trying to sell them anything, other than cram the benefit of several years of Android experience into the twenty minute attention span of the average conference attendee.

I had the slides (OpenOffice impress, not PowerPoint), I had source code (open on GitHub of course) and even an app on the market they could download while I demoed my framework on stage.

slide.png

My plan was to keep it simple.  Concentrate on the hardest, and ironically most basic parts of the platform (i.e. keeping components with different life cycles held together), show where people often go wrong (service leakage, unnecessary RPC, etc), and top it off with a working demo for them to take away and learn from.

My greatest fear was for someone at the Google I/O (which I couldn’t attend) to have covered the same topic, or worse having recommended something contradictory (still waiting for Google to put those session videos up).  Additionally, a part of me kept wondering if someone was going to stand up and shout Balderdash (or some German equivalent) as I made my most bold claims and controversial recommendations.

But on the other hand, in the weeks I had to prepare the main slides (after finishing the framework code), I realised that I was going to be able to demo a bunch of things people normally don’t think about while developing.

Things like:

  • How should your Service update your UI?
  • When do you end your app?
  • How do you make your app come back from the dead after your process has been killed?

I had turned up twenty minutes early to turn my development laptop onto a presentation machine (I knew the Dell/Windows XP/NIVIDA drivers would start fighting each other for control as soon as I plugged in the projector).  I set up my laptop screen orientation (no daylight glare), resolution (medium), projector (clone mode), brightness (full), Android emulator (correctly sized to fit the screen), mic (a nice wireless wraparound model provided by the technician) and tried out a cool little Logitech laser pointer/slide controller gizmo that (somewhat surprisingly) worked with OpenOffice as soon as I plugged the USB dongle into my machine.

slide2.png

It helped that I had tested my slides out on the same projector that same morning, and realised that my original colour scheme made the component diagrams illegible.  An issue easily solved during the days welcome keynote.

I checked the clock, and realised that I was ready with five minutes to spare (much better than trying to set up with everybody watching).  So I put the title slide up and sat down in the front row, looking over my equipment as the room began to fill.

I calmed my nerves by breathing slow and thinking through my main points, before someone politely asked me to vacate my seat.  Standing up, I turned around to see a packed room, with people shuffling around in the isles, and newcomers starting to chose their places on the floor.

Around now, it dawned on the organiser that the allocation of a “small” hundred seater room was going to be somewhat inadequate.  Instead of disrupting other parts of the conference, the moderator apologised to the room and opened up the double doors so people could watch from the corridor.

By my reckoning, there must have been north of a hundred and eighty people trying to watch in a room designed for half as many (I only found out later that some of my colleges had been turned away), which meant as I spoke I could taste the moisture in the air.

I kept calm, and walked the audience through my slides, skipped through some of the code examples  (20 minutes is not much time) and ran the framework demo with whatever time was left over.  The demo worked flawlessly, which I considered to be lucky as better men then me had seen their demo’s die that day (not needing a working internet connection always helps).

Surprisingly, when it was all finished no one put their hand up to ask a question.  Instead I was greeted by the sound of people quietly shuffling away to make changes to their apps.  Above all, developers don’t like to look stupid compromise their ego in front of their peers.

Presentation of “Architecture your Android Application” DroidCon 2010 are on Slide share, source code on GitHub, demo on the Market.

Oh, and that Twitter feed:

Twitter feed

Pre-embedding your Android Application using a Market-Stub.

Friday, May 7th, 2010

Suppose you’ve been asked to pre-load your application onto a forthcoming Android device, so that end users will see your handy work on the Home Screen as soon as they start-up the device.  This means excellent placement for your application an extra selling point for the device (i.e. your application can be shown on the product marketing!).

First off, lets forget about including your actual application, as it’ll take ages for your software to be approved by an operator, be embedded by the firmware developers, pass QA, ship, then sit around in a storeroom before being finally sold to a customer.  By this time, your development team will have published a much improved version of your application onto the Android Market.

No, what you need is a so called “Market-Stub” application that will direct your new customer straight to your application on the Android Market.  The added benefit of this, is that applications downloaded by the user in this way are automatically registered with the Android Market application, allowing it to take care of future upgrades on your behalf.  Of course, if you still want your application to work out of the box (and for customers fussy about their internet connections) you can integrate the MarketStub into your existing application and periodically prompt the user to upgrade (no matter how annoying this might be).

First off, all this code is open sourced in my GitHub repository:
http://github.com/zedray/Android-Market-Stub-Application

Iteration one:
Create a project with a single activity that points to the given Application name space using its Android Market URL (using the Hand Warmer as an example).  This URL will go directly to the application’s Details screen, bypassing any Search UI and saving the user one click (see documentation).

public class HandWarmer extends Activity {
private static final Uri TARGET_URI =
Uri.parse("market://details?id=com.zedray.handwarmer");

@Override
public final void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startActivity(new Intent(Intent.ACTION_VIEW, TARGET_URI));
finish();
}
}

Criticism #1 Activity Intent path issue:
Its a known issue with older Android Home Screens (<1.6) and those based on it (HTC Sense, etc.) that short cut icons are not updated with the application (i.e. the Home Screen does not listen for the ACTION_PACKAGE_CHANGED intent).  This means you should ensure that the entry point activity for your Stub application (which is cached by the Home Screen) is exactly the same in your new application, and that you don't change it at some point in the future (watch out for this during refactoring).  If the cached activity path is different, your customer will see a "This application is no longer installed" Toast error when trying to run your newly installed application via the Home Screen, although it will still work fine if they run it via the application list menu.

Criticism #2 Task History issue:
Because of the way Android works, if the user presses the “Home” button to leave the Market Details screen they will inadvertently leave this Activity on top of the Activity Stack for your application.  That means that once your application finishes installing in the background, the user will try and run it by clicking on its icon and will instead be taken to the top of the Activity Stack, i.e. back to the Market Details screen.  This is confusing for the user, as they will now have to press the “Launch” button at the bottom of screen to proceed to the newly installed Application.

Iteration two:
This time add the FLAG_ACTIVITY_NEW_TASK flag to the Android Market intent.  This will push the user into a new stack, and prevent them having to return to the Android Market Details screen when starting the application for the first time.

startActivity(new Intent(Intent.ACTION_VIEW, TARGET_URI)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));

Be sure to contribute any improvements to the open source code base.

Berlin DroidCon Presentation 2010

Thursday, May 6th, 2010

DroidCon Logo

Android is hotting up in the marketplace, and the Berlin DroidCon conference program is looking interesting this year.  Particularity as I will be presenting some research on Android application architecture and demoing a bit of source code.

Architecture your Android Application (30 minutes)
How should you structure your Android application? What components do you use (Activity, Service, Application) and how do you communicate between them (Binders, Handlers, RPC)? I will talk about how you can manage the different life-cycles of your components, share some experiences and show some code.

DroidCon, Seminaris Campus (Dahlem Cube), Berlin, Donnerstag, 27. Mai 2010.

UPDATE: I will also be attending the BarCamp on the 26th of May, so if anyone would like to suggest a topic for me to talk about let me know in the comments section.

Call Log Widget

Saturday, May 1st, 2010

Candybar keypad buttons

The first thing my girlfriend asked when I handed her an Android phone was “how do I make a call with that?”  This is from someone familiar with the candy bar form factor with the ubiquitous green (call) and red (hangup) hardware call buttons (and no interest in finding the “phone app” on a busy home screen).

In the quest to make form factors with fewer buttons (i.e. more iPhone like), the device manufacturers have seen fit to remove calling buttons from their hardware and instead rely on software buttons integrated into the on-screen UI.  This is something typical of the second wave of Android phones (higher pixel density, 1.6 or above, etc.) that we have seen come out of late.

This got me thinking about what sort of phone-like use cases the home screen should be trying to fulfil.  The most useful being when the user returns to their phone after some time (or just a moment) and wants to see the current state of the call history.  Coincidentally, this is information you can already see under the “Call Log” tab, which (strangely) is around 2-3 clicks away from the user as Google did not include a short-cut for this screen.

Call Log tab

Simple use cases for a “Call Log” Widget:

  • Who called last? (include their name, phone number, how long ago they called)
  • Did I miss an incoming call? (show if a call was incoming, outgoing or missed)
  • One click to show more info (i.e. a short cut to call log screen, or should this go directly to the relevant contact?).
  • One click to return the call (actually this should be two clicks to make it harder to call someone by accident)
  • Align with UI of native widgets (i.e. keep it black and shiny on my Nexus)
Call Log Widget

Hence, I present the “Call Log Widget” for Android 1.5 or above.  This is by far the most useful widget on my home screen, and a nice visible platform on which I can add more “phone-like” features to the interface.

Your feedback is very much appreciated.

Android Market link (Android devices only)

Tracking a Android Home Screen Widget

Saturday, May 1st, 2010

The solution for the “Using Flurry with a Android Home Screen Widget” problem was to move over to using Google as an analytics provider.  This works because Google has kindly provided a dispatch() method in their API, so developers can choose exactly when the library should start reporting back to the server.

This is intended for developers wanting to optimise their network traffic, but in my case I can now spool up a new service from which to call the dispatch method.  Using a new Service context results in the library having sufficient time to complete its data transfer, without falling foul of the limited lifespan of the BroadcastReceiver life-cycle.


Geo Visitors Map