Android Experiments: Hashire Hamusuta post mortem

It all started about 10 days ago, when I first knew about the Android Experiments I/O challenge.

What is Hashire Hamusuta?

Hashire Hamusuta, Japanese for “Run Hamster”, is a game to help people to stay active and my entry for the challenge.

You’re a hamster. It runs when you’re active and it sleeps otherwise. If you walk, run, ride, the app will count your steps and you will earn ⚡.

You can spend ⚡ at the store to buy hamsters to produce more ⚡ in your power plant.

In your power plant you can ping lazy hamsters, those who are not active. You receive a 100 ⚡ bonus if they become active in less than 10 minutes.

There’s also a 10,000 daily steps goal that if you achieve will earn 100 ⚡ for those players who have you in their power plants.

Interface design and illustrations

I wanted for the app to have a playful look and feel, the inspiration was Neko Atsume.

So I asked Giorgia to work on the illustrations. Well, she did a great job, I love those illustrations!

Hamusuta

She perfectly interpreted my idea and after some sketches she was already drawing the hamster animations and all the other elements of the UI.

The first version of the app:

Hashire Hamusuta 1.0

The latest version of the app:

Hashire Hamusuta 2.2

Go and Google App Engine

I wanted to try Google App Engine (again) to host the app server to collect players info, steps measurements, etc.

The platform supports Java, Go, and Python by default, but it also supports custom runtimes.

At first I tried to use Haskell to build a simple Scotty HTTP API, but after almost half a day trying to build and run the container, I gave up.

It should have been as easy as creating a custom Dockerfile, but I got all sort of errors. At the beginning the container was building too slow using the Cloud Container Builder. I was getting a DEADLINE_EXCEEDED error that I resolved by avoiding Cloud Container Builder by setting the use_cloud_build option to false. Then I started getting docker errors that now I don’t even remember. This very bad start, in conjunction with the idea of working on this project in a hackathon mode (more about it later), made me lean toward Go.

Apart from an issue with GOPATH and a problematic interaction between the official Go tools and App Engine SDK’s tools, everything worked like a charm. Deployment of the app is fast and reliable, managing versions is easy, and working with Go is relaxing.

Google Cloud Messaging

Pinging a friend means sending an app notification to his/her device. I also wanted to show the live status of hamsters (running or sleeping) in the power plant activity. To deliver and receive notifications I used Google Cloud Messaging.

To deliver messages from the server I used a patched version of github.com/alexjlockwood/gcm. It was too late when I finally found github.com/google/go-gcm, that I think is a more official and up to date version of the library to interact with GCM.

The server publishes updates on a topic for each player. Clients subscribe to owned players’ channels to get notified when a new event occurs.

To handle notifications client side I followed the example at github.com/googlesamples/google-services and everything went fine.

Getting data from the step sensor

To get user’s activity and the number of steps I started with Fit API, but I didn’t find a way to handle background updates of user’s activity. I need to get those data in background in order to notify the system and other users of current user’s status changes.

I fell back to retrieve raw events from the step counter sensor with a background service inspired by github.com/googlesamples/android-BatchStepSensor. The result is quite reliable on many devices where I tested the app with a couple of exceptions.

Drawable resources for different resolutions

I’m lazy so I was putting every drawable resource in the res/drawable directory. Also because I’m lazy, one day I didn’t want to get up to get the USB cable to test the app on my phone so I started using the emulator and I noticed a lot of OOM errors.

What was leaking memory?

Well, it turns out that loaded drawable resources are stored as bitmaps in memory, so a 100 Kb png image was filling megabytes of memory to be drawn on the screen.

It also turns out that all the drawable resources that you put in the generic res/drawable directory are handled as mdpi resources. Android by default scales the low density drawable version to the target device’s density.

This meant that a 100 Kb 500x500 png image was getting scaled to a 9 Mb 1500x1500 image on a xx-hdpi device (Nexus 5) and the emulator was reserving only 64 Mb of RAM per app process so I was hitting the limit right after a couple of images.

The workaround solution was to create a new res/drawable-xxhdpi directory and copy all the images there. The size was fine because I always tested the app on xx-hdpi devices. Note: I should have done this for all supported devices’ resolutions, but I’ll wait for actual crashes to do it. The lazy way.

What went right

What went wrong

Hackathon mode

What does Hackathon mode mean? Well, I don’t know exactly. It’s an excuse to try new technologies on small/finite projects with a time constraint.

The time constraint part is interesting because it forces you to focus on functional parts of the app to have “something” to test as soon as possible.

An approach that I found useful: start working on the riskiest parts of the hack first. In this project for example I started by building a couple of Android prototypes to test GCM (👍), Fit API (👎), and Haskell on GAE (👎).

Sources

blog comments powered by Disqus