Latest Tweets

 

Yoke Sign In

I finally found a little time to do some Android coding. The result is a new sign-in flow for Yoke:

Here I’m trying to make it as simple as possible for users to establish an identity with an application. The activity is part of a generic Android library I’ve developed that matches an app’s look using style declarations to override the default appearance.

There’s also a nice technique in use here: The explanatory text is in a ScrollView. To bottom align it when the text doesn’t fill the view I combine the attribute android:fillViewport with a vertical LinearLayout (to hold the text) that contains a trivial zero-height View of weight 1. The result is that, when the text is smaller than the ScrollView, the trivial View soaks-up all of the empty space, pushing the text downwards, and when the text is larger than the ScrollView, the trivial View get squeezed to nothing.

The Google favicon is a placeholder — does anyone know of an approved icon I can use?

Introducing Yoke

I’ve been working on a project called Yoke. It’s a server application for enhancing mobile applications and it’s accompanied by an Android library that takes most of the effort out of using Yoke in Android applications.

Photo credit: Cgoodwin

I started working on Yoke because there were a number of features that I really wanted to add to my Android applications for which I lacked a good approach. My key problem was:

How to make user generated content shareable?

Mobile devices typically have spotty internet connections, so if you want to make the user generated content accessible in a reliable way it needs to be copied to a server. And unless you want to prevent users from editing their content after they have shared it, you need a way to update content that’s already been uploaded. And since it would be quite annoying for a user to request these updates manually, it needs to be done automatically on their behalf (without failing “annoyingly” if the network fails). And since users might use the application on more than one device it’s necessary to synchronize the user content between all devices and the server, in both directions. Using the application across multiple devices in this way further implies that each user needs some form of identity within the application.

Then there’s the actual user mechanics of sharing to consider. Although sharing within an application can be as simple as making content visible to all the other users, the reality is that, for even mildly popular applications, the volume of content generated requires indexing and sorting to make it navigable. And because user generated content naturally varies in quality you need a mechanism for surfacing the best content. Approaching this (as I have) by allowing users to ‘like’ or ‘favorite’ the content of other users involves many other considerations: how to cope with flurries of ‘likes’ on extremely popular content, how to provide a stable ordering for browsing by popularity when it is constantly fluctuating, how to accommodate content that isn’t public, etc.

Simple sounding problems can hide a lot of complexity. Yoke is my attempt to write a reusable platform that does only as much as I need to let users share content via my mobile applications. I just want to give them an easy way to:

  • establish their identity;
  • store their data;
  • share the content they create;
  • and find the content others create;

in a way that doesn’t constrain the applications I can write.

I think I’m almost there now, Metaglow has been my testbed which I’m looking forward to releasing soon, after that I’m going to try and find time to write a few posts about what I learned by implementing Yoke.

An accessibility mistake in Metaglow

I take accessibility very seriously, so I’m really glad that new guidance on accessibility on Android has been made available to developers.

One of the problems with designing accessible applications is that it’s very easy to overlook the needs of users when you don’t share those needs. This is compounded when users have diverse needs which is the case when considering accessibility; the blind or partially sighted have completely different needs from the deaf or those who are hard of hearing.

It also doesn’t help when you make mistakes like this (from my Metaglow app). This all looks okay on the surface (but not especially great): simple layout, Dpad navigable, labelled buttons.

Until I considered the implications of my general design for this activity:

Which I belatedly realized leaves no way of navigating to the tabs at the bottom of the screen, except by touch: with focus falling naturally on the first element in the grid, the user can never move down far enough to reach the tabs because the list of favorites is effectively infinite for UI purposes.

Fixing that mistake involves too much re-work for the first release, so I’ll have to stick with the misdesign for now. Here’s a tip: don’t combine heavily populated AdapterViews with bottom-tabbed activities.

Another Metaglow icon effort

Since two people have made the same comment, I have to take it seriously, but I’m still having difficulty seeing the similarity to M&Ms. Yes, it’s an M in a circle - but so is the sign for the Paris Metro.

M&M'S.
Concept for the Metaglow feature graphic in the Android market.

Concept for the Metaglow feature graphic in the Android market.

Am feeling all coded-out at the moment, so I’m trying to stay productive with a bit of icon design. I’m not content with either of the possible designs I have at the moment.

Thankfully, I’m a much better programmer than I am a designer.

Am feeling all coded-out at the moment, so I’m trying to stay productive with a bit of icon design. I’m not content with either of the possible designs I have at the moment.

Thankfully, I’m a much better programmer than I am a designer.

Metaglow promo image (work in progress)

Metaglow promo image (work in progress)

Google Analytics: Watch out

I’ve been unable to code for the past week, so as I started to ease myself back in today, I took time to investigate a phenomenon I first noticed months back.

Reto Meier has been a strong advocate for the use of analytics, his code and all the available sample code indicate that you call the analytics tracker on the UI thread. But if you use the Google Analytics SDK for Android like this, calling the tracker on the UI thread, it can make your app very unresponsive. I noticed this after adding the library to my Metaglow application, buttons that had felt very snappy immediately felt sluggish, even though I’d taken care to keep the UI thread ‘hygenic’.

Today I sat down and wrote a little stub of code that collects some basic call-time statistics for the GoogleAnalyticsTracker class from version 1.1 of the SDK. I made a few runs on my Nexus One by proceeding to use Metaglow over an extended session. In each run I collected timings for approximately 100 calls to the trackPageView and trackEvent methods.

Of the three runs, these were the most typical numbers (one set slightly was slightly faster, one set was significantly slower):

  • Number of Samples: 102
  • Mean call time: 71.38ms
  • Std. Deviation in call time: 60ms

So, you can expect users to occasionally encounter UI glitches of 1/5th* of a second or more just from queuing an analytics event; and (admittedly I don’t have figures for this) it’s my experience that the pauses are more significant than this; infrequent, but long when they occur; this gives a bad user experience.

It’s documented that the analytics data is queued into batches and dispatched separately from the call that records them, so this behaviour (infrequent but lengthy pauses) can’t be due to network I/O. But it is what we are told to expect when we are performing writes to Flash storage. So I used traceview to peek inside the execution of the analytics code and confirm that this was the cause.

Those green blocks, which are just about visible, are writes inside Sqlite3 and this explains the uneven performance.

Since I want to keep analytics I will probably write my own event queue around the Google analytics tracker, to decouple it from the UI thread. If you use Google analytics and want to give users a smooth experience, you may need to do this work too.


(*) this figure is based on 2 standard deviations above the mean

Creating a colourful glow in Android

In a previous post, I described how I could dynamically generate a continually evolving logo by masking and layering several different bitmaps.

This worked well enough, but failed to look convincing when the rendered texture was light. I overcame this by creating a halo effect, to make brightly textured emblems appear to luminesce. Again, the 2D rendering apis in Android made this very easy.

I start the process with the rendered texture in a Bitmap:

Texture

Using a Canvas over a tiny 3x3 Bitmap I produced a scaled copy of the texture.

Lowres

Using the Bitmap.getPixels() method, I created a SweepGradient through the eight outermost colours.

Sweep

Finally using a black-to-white-to-black RadialGradient applied with a PorterDuff.Mode of MULTIPLY a circular ring is of compatible colours is created:

Ring

This ring can then be overlayed separately onto the existing image, using the useful TransitionDrawable class to smoothly switch halos.

The final effect can be seen in this video

Metaglow early preview release

I’ve just posted a very early preview version of Metaglow - an android application for creating backgrounds. It features the animating emblem that I described in my last post.

Metaglow Screenshot

Anyone who wants to take a look can download it using Betan which is available via the Android Market (just search for Betan). The password is simply metaglow.

This is a very early release, here are some things to watch out for:

  • The application has so far only been tested on my Nexus One.
  • It currently requires Android 2.1 (final application will target 1.5).
  • It won’t work on non-hdpi devices (because I haven’t done the work of producing multiple bitmap resources yet).
  • It’s locked to portrait (because I haven’t done that work yet either).
  • The “Set Wallpaper” feature doesn’t give any visual feedback that it’s doing stuff.
  • You can’t favourite or share designs yet.
  • Any designs you accumulate in your history will be lost under later upgrades.
  • The range of ‘basis functions’ (ie ways it can generate backgrounds) is a bit limited at the moment.
  • I recently added Google Analytics to the app (I’m interested in tracking UI interactions) which seems to have significantly reduced the smoothness of the application (insert sad face), and has even generated a couple of ANRs (hopefully the analytics team have already started using StrictMode and we’ll see some improvements).

There we go, if there’s anyone left who does want a look:

  1. Download Betan
  2. Choose me as the publisher
  3. Supply the password metaglow
  4. Install the application
  5. Wait for something to go wrong

There are more detailed instructions on using Betan if you need them.