Friday, November 23, 2012

How to make a well performing live wallpaper for Android.

Along the way of getting myself familiar with the landscape of all the things one needs to become a successful Android developer (and yes, that includes making money with Android - more on that later), I decided to get into a new and fun project: Frozen Window, a live wallpaper for Android. Last year, it was still an original, but then the week I wanted to release, someone else came up with the same idea. With the exact same title. Ah, competition, what would we do without you? And so it happened that I didn't release the wallpaper last year at all.

This year though, I thought it would be nice to have another attempt at a good release. It's almost December again, the source code was still waiting on my disk drive and it didn't make sense to keep it there while I've been spending quite some sleepless nights on it, so I started to shape up things for a release.

Because there still had to be at least one nice, new and original feature in the live wallpaper, I decided to spend some extra time on it by adding support for blurry backgrounds, to make the fake frosted window appear more realistic. But I didn't want to stop there. It had to be dynamic and support custom user images as well. And, oh boy.. did that open up a can of worms...

To sum up, here's a list of issues I got into:
  • Availability of memory on mobile devices is limited.
  • Availability of memory for a background app is even more limited.
  • The user can pick a custom image, including very (I mean, very!) large images. And they need to be blurred as well (being an expensive operation, that's not something you'd like to do for big images on a mobile device).
  • For realtime sharp to blurry images and the other way around, multiple images have to be saved, but the required amount of memory is usually not available.
  • Earlier versions of Android did not quickly release bitmap memory (usually later on, sometimes not at all), making things even harder.
  • Repainting of the wallpaper. Repainting multiple background bitmaps and moving elements is slow!
Luckily, the repainting part was quite easy to solve. The wallpaper used to be very time consuming to (re)draw and stutter a lot, but a temporary screen buffer solved things quickly here. Now, when you switch from one to another home screen, only this temp buffer will be moved around. With this in place, some small animations for droplets or finger painting would become much cheaper and the result would remain silky smooth. Without OpenGL.

As you can probably guess by now, memory was the biggest issue. For preprocessing the blurry image I used an algorithm to apply a separate vertical and horizontal gaussian blur, which looks much better than a simple box blur. A lens blur would have been nicer, but the image needs to be preprocessed each time when the user loads a new image (not when changing weather patterns), so the gaussian blurring made a nice tradeoff. In addition to that, the blurred image can be saved on a lower resolution and stretched when it needs to be drawn, which proofed to be a great optimisation in terms of memory usage while keeping the visual stuff interesting.

Another important thing to optimize is memory usage while running another app in front of the wallpaper. The (scaled) background image and temp buffer aren't visible here, so the use of memory can be largely cut out by temporarily releasing the Bitmap memory altogether. It appears that Android can quickly save Bitmaps to PNG image files within the internal memory (SD card would be slow), thus it became a possibility to do nice things while looking at the wallpaper and still have all memory available for real apps when switching to one of those.

So that would make up for a nicely behaving live wallpaper background, if it wouldn't be for Android to make things a little odd by adding the requirement of strategically recycling Bitmap memory where possible. Otherwise, the wallpaper would usually run out of memory by loading just two screen sized bitmaps.

While browsing the Google Play Store I've seen lots of live wallpapers that didn't do things "right". They did not release memory, or huge background images were used without even attempting to optimize them. Some of them just randomly black out because they're out of memory, others just crash. With this blog post, I'm hoping (even though I'm no expert by any means) to motivate other developers to take a better look at these things. I love the many great live wallpapers the Play Store has to offer, but have seen them many a times getting ruined (and uninstalled) by the memory usage. Dear fellow developers: please do check your memory and please do release as much of it as you can when you don't need to have these allocations. Thank you!

If you're curious to see the result: you can download the live wallpaper for free from the following location:
https://play.google.com/store/apps/details?id=com.stripeymilk.frozenwinlwp

A cookie goes to the person who finds the rather big programming mistake I made and tried to hide ;)

Got any questions on how to optimize your own live wallpaper? Feel free to post!

Sunday, June 19, 2011

How not to develop your games for Android - part 1

Every once in a while you'll get this genious idea for an app or game. And really, in your own mind, the idea usually is a pure stroke of genious. But some times, that's exactly the point where geniality is about to turn into something completely different...

You're starting to think about how you're going to approach the idea in terms of software development. Is this toolkit the right one for your app? Might that toolkit be the perfect match? Should you rather write your app without any toolkit at all? Will it be native? Will it be Java or C++? Will you want it to be available across different platforms?

Those are the questions that need to be answered on the very first day. For myself, I think cross platform compatibility is quite important because it's a lot easier to use one common code base for multiple platforms. When you fix a bug here on Android, it should often get automatically fixed on iOS as well. Or whatever other system you'd like to write your app for. It can bring down the burden on the indie developer or a small team of developers, which is a great feat if you don't have an unlimited amount of time to spare.

As for native apps, I think the general idea behind it is clear; native can equal less bloat, thus it should be faster and everyone could be happy when they use your app. Right?

..well, not necessarily so much!

I wanted to make my app available on multiple platforms. This includes (obviously) Android, iOS, and maybe even WP7 if the guys and gals from Redmond were to allow for ordinary 3rd party developers to use C/C++. But as with WP7, each of these platforms comes with its own set of limitations.

When starting development on "Turn" I was looking for a way to get my feet wet in multiple areas: markets and app stores, game development and how to get great ratings by delivering (I hope!) on quality.

Luckily, the first person ever to rate my little app gave me all out of the full five stars (actually, it used to be four, but after fixing a little annoyance it suddenly turned into five stars :)). Woah! Now that's how you can truly movitate a developer to keep bringing on the good stuff, thank you so much!

More people started to download the game and more people added five star ratings. One day, I woke up to check out the ratings again. After a bunch of full five star ratings, the worst thing happened: someone rated my game with only one star, without leaving any email, tweet or comment in the Market at all. Oh my.. how was I supposed to figure out why this person did that? Really, it's quite hard to predict why someone would think an app is worth one star when there's not a message coming along with it. I know, it can be a matter of taste and perhaps he or she just did not like the app, but I'm working hard to get my apps as stable and as nice looking as possible within the design. Is it really worth one star, even when a person just doesn't appreciate what it looks like but didn't see it crash or anything?

Then, I started to look into how well my app performed on a multitude of devices. I mean, it did absolutely great on my HTC Desire, but who knows it could run very slowly on other devices. This is where I figured that some devices out there are cheap. Not only are they cheap, they're missing out on a number of very useful features as well. What came most as a shock, is that some recent devices are sold without the ability to render using the hardware, falling back to software rendering. As some of you might already know, software rendering can make things very slow, so there's probably the reason why I got my one star rating. Of course, that's still an educational guess, but I'm hoping it is.

In the end there are two reasons why this could ever happen:

  1. You're using OpenGL ES to render the graphics and specified GLES 1.0 as the minimum requirement. Bad choice. Really bad. It appears that some devices are using a software renderer called PixelFlinger, which doesn't seem to have have any 1.1 or 2.0 features and renders slowly using the cpu instead of the gpu. If PixelFlinger is there, performance is going to be very bad.
  2. You're not (re)drawing only the updated parts of the screen with either OpenGL or the Android Canvas, making the device draw lots more than what would be necessary. Unfortunately, if you're going for cross platform compatibility, it's not possible to use Canvas here because it's not available through the NDK (on Android 2.0, 2.1 & 2.2). Drawing inside selective areas with OpenGL is not a usable option either, because there are so many Android devices out there with different implementations of OpenGL ES. On top of that, Android 2.2 and lower versions do not have support for everything needed to get things working the right way. I'll write more about that in another blog item, as it can become quite a complex issue to tackle.

In the end, if you're going for cross platform compatibility and would like to use OpenGL ES for your app; think again. It might be a better choice to use the native Canvas API instead when you'd like your app to run on as many Android devices as possible.

If you're on a reasonably fast device (that's almost any device out there, with the exception of a few), you might want to check out the result: Turn.

The long road of becoming an Android 'Top Developer'

Hello there! Nearly no mortal on the interwebs knows my work, but that's about to change pretty soon. I'm here with only two goals: to bring more high quality apps to the Android Market and to earn this nice "Top Developer" badge.

To reach those goals, I'll be spending lots of time in front of the notebook, working hard on research, coding, gfx / ui design and marketing. All of that as a single indie developer.

I started out by making my own clone of snake (Yeah, I can hear you sigh right there. Another one? ;) ). The snakes are mostly just for testing the waters though. Eventually I'm going to get at the more original ideas. There's lots of 'em in my notebook for sure and I'm really curious to find out what people think of it!

You can find my current apps at the following url: https://market.android.com/developer?pub=Stripeymilk

Let's get thing started!

ps. Please don't mind the pink colors on this blog. It's the closest to what I'm currently having in mind for the actual design, but it's obviously not going to stay this way :)