Weathrman 2 now available in the Market

Weathrman 2 is out.  This release includes improvements pretty much all over the place, from what we search for on Flickr, how we search for it, which images we choose, what minimum image quality we’re willing to accept, new UI elements to help surface more detailed information, and lots more.

It also takes the text off of the background image, which leaves a prettier desktop, and we improve the image quality while we’re at it.

I look forward to your comments, which you can send using the support form, or on Flickr.

Weathrman 2, and the Pile of Shame

Shadow Complex is done; and while I’m happy that I’ve managed to take another game off of the pile of shame, which is currently shrinking faster than its rate of growth, I feel a bit funny about playing an Orson Scott Card title, given his political slant.  I wish Chair wouldn’t do that; it’s not like that ending was so good that they needed OSC’s involvement - that was one of the worst endings I’ve ever seen in a videogame.

You’re forgiven for thinking that there’s been no progress on Weathrman as of late; in fact, there’s quite a bit going on behind the scenes, including:

  • Translated search terms, to pick up tourist photos.  EFIGS first.
  • Status bar notification while the desktop is visible to provide better UI discoverability
  • UI showing details of the current photo and linking to it on Flickr
  • Some kind of resolution to the updater problem

I still need some kind of resolution to the updater problem, but that might not happen until 3.  At worst, I’ll build an intent that explains the nature of the application and gives the user a one-button way of udpating wallpaper.

But first, I need a haircut.  And to start Darksiders.

Weathrman 1.7: Performance Optimisations

I noted that every now and then, Weathrman would get killed due to not being responsive enough to a change of wallpaper offsets (finger scroll, etc.), and decided to take a walk and look at the performance of what we were doing.

I hit three different kinds of issues:

  • Unnecessary updates.  If the offsets applied were the same as those currently set, I was forcing a redraw when there was nothing to draw.
  • Backing store size.  Evidently, the ‘optimal’ canvas depth is 565; up until now, I’ve been keeping ARGB_8888 canvases around.  Shifting down to RGB_565 results in a massive improvement of the performance loop.
  • Image load.  The flickr image was being loaded in ARGB_8888, even though we were never going to make use of the transparency data in the backing store.  As the rest of the visual change has moved to 565, I do so here, as well.

The net effect is to massively reduce the amount of time we spend rendering, and the size in memory of the backing store.  In addition, we’re less peaky when we load a fresh image from Flickr.

All of this should result in fewer cases where Android decides to eject the live wallpaper due to ANR.

While I was at it, I added a few more tweaks; we now track how long we’ve been asleep for, and on becoming visible, reschedule our background timer.  You should find that the app is much more likely to keep itself current, now, and should begin updating itself within moments of the phone ‘waking up’.

As always, I’m gagging for comments from users, here.  Either leave them here, or mail them using the support tool.  I look forward to hearing from you.

Coming soon...

So, ahead of me lay another weekend, which means I get to write some more code in between bouts of playing Dragon Age and trying to figure out which of the raft of 3D TVs I’m going to buy…

On the cards is:

  • Lots of tests.
    Right now, I’m testing non-android code fairly well, but I’m not currently thrilled with the state of testing of android-level functionality.  To keep things clean, I’ll be isolating android behaviour into provider methods that return the answer I wanted - injecting, for example an @Named(SHOULD_UPDATE) boolean shouldUpdate, for example, which checks preferences and network availability before returning a simple, injected boolean, isolates the android weirdness from the perfectly normal code beneath.
  • History.
    Right now, you only see a new image if Flickr decides there’s something more interesting than what you saw yesterday at the same time in the same place.  Most of us spend a lot of time in the same places, day in, day out - but we always want to see new things.  I’m going to keep a history of stuff I’ve seen recently, and exclude that.  This means that double-tap won’t reload the current image, it’ll choose a new one.

At that point, I think I’ll be ready to re-look at the frontend/backend separation; it may well be time to start looking at a content provider implementation to wrap up the fetching behaviour and history implementation in a nice, neat package.

Weathrman 1.5 hits the Android Market... now

This update is fairly experimental.  One small change - ensuring that we don’t try and fetch data when we haven’t got a connection established - should hopefully improve performance under edge-of-network behaviour.

The other is tougher.  I’m making some changes to the queries we perform against Flickr’s API in the hopes of improving the quality of results, especially under clear conditions.  Some of these are as follows:

  • For queries performed at night, AND() in a set of words that are likely to be associated with night photography.
  • Add a list of “banned” terms, including “naked” and “nude”.  I don’t mind looking at them on the web, but I don’t want someone’s naked butt hanging out of my phone.  Your mileage may vary.
  • Separate daytime descriptions of “clear” from nighttime ones; include in those things you only see during the day/night cycle.  (Nights, for example, might include stars, constellations, or the moon.)

These and other tweaks will hopefully improve the quality of search results returned, and they should feel more relevant; the negative side of this is that it might be much harder to find a well tagged local photo.

If you have good ideas, as always, I’m listening.

Weatherman 1.3 now available in the Android Market

I’m looking forward to getting some feedback.  It’s been… I think I opened the github account on the 28th of December.  I built and threw away a live background that ran cellular automata, which I really, really wanted to do, but Android’s drawing routines just aren’t good enough/fast enough to really allow for that.  (The automata itself was happily running at 15fps, but the UI update was <3.  Boo.

A commit on the 30th of December is really the beginning of this app’s life.  Today’s the 6th.  In that time, I’ve done more obsessing than I care to admit; I’ve had a really good time building this, and while it’s not perfect, I’m a great deal happier with the state of modern Android development than a year ago, and a good chunk of that happiness didn’t actually come until after I pulled Guice in as a dependency.  Shame that didn’t get built into a core part of the API, IMO, but I’m happy now.

I wanted to call this Weathr; that’s certainly the obvious thing.  Weathrman is just a bit too long for my taste.  But someone else appears to have had a similar idea, albeit for the web… it looks dead, but there’s no point risking it, and this does just as good a job.

I’m tracking exceptions and stuff to Analytics; I reeeeally wish there was a built-in exception logging API that pushed stack traces and bug reports back up to the marketplace.  Still, I’m looking forward to seeing how this works in the wild, and whether or not it’s an utterly broken experience in cities less populated than London.  I do my best to find local photos, but it will eventually do global searches…

I remain concerned over a few things.  I’d like to find some way to re-set myself as the active wallpaper if I’m the active live wallpaper and I update the binary.  If you know how to do that, ping me.  I hate the fact that every time I update this thing I have to go back to setting it as the current wallpaper again.

And I really ought to test this on a phone that isn’t a Nexus One.  Should you try this app on something other than an N1, do tell me what the experience was like.  Some things, methinks, won’t make sense - I should probably be more careful than I am, for example, about which image size I choose for download, rather than always assuming that bigger is better.

I look forward to hearing from you.

 

 

 

Guice support for Android = Happy Me.

There are a few things I just can’t live without in projects these days.  These include stuff like Functions, Predicates, filtered and transformed Iterables, the immutable collections implementations, and a raft of other stuff from the Google commons.  If it wasn’t open-source, writing java code these days would feel like working with flint and stone.

Also included in that how-do-people-live-without-this-stuff list is decent dependency injection.

I didn’t notice until I was a long way into the project that Guice now has support for Android.  At the moment, I’m using Guice 2.0 without AOP, Multibindings support, and assisted inject, and quite frankly, the code is almost instantly better for it.  Constructors now only contain what the local object needs to use to do its job, and everything is an awful lot more readable.

It’s also nice not to have to pass around awareness of the fact that Android’s context classes are a pig’s ear of methods.  There’s nothing wrong with using composition instead of inheritance, folks; your application classes shouldn’t need to be a combination of implementations every single interface in the SDK.  That’s not discoverable, that’s just a wall of noise.

Anyways, four hours of un-hardwiring class construction resulted in a much easier second refactoring to start splitting foreground from background services, which took all of an hour and only involved creating a new module for the new service class, and poof!

I still wonder how people get on without DI, and why on earth this isn’t core java yet.  Mind you, I wonder that about Joda, too.  And closures.  And just about any other modern feature that doesn’t make it into the now-overpoliticized trial by fire of the JDK.