Recently I am very interested in creating a small game for Android. Since every game needs a proper working gameloop and a underlying drawing mechanism I started to look at some examples from the internet. My first attempt in searching a good example lead me to the Android Developers page. There is a good description on how to get started with 2D graphics. I decided to take the threaded aproach as described there. This means that there is a thread that draws everything into the view as fast as possible while not blocking the UI thread.
Some further poking on the Android Developers page lead me to the Lunar Lander example which looked right what I wanted to do. I installed it on my HTC and played around with it a bit when I suddenly received this error message:

What happened? To put it simple, there is a bug in Google’s Lunar Lander example. Let’s look at the implemenation of the thread that draws the game in LunarView.java and how it’s started:
1 2 3 4 | public void surfaceCreated(SurfaceHolder holder) { thread.setRunning(true); thread.start(); } |
The method surfaceCreated() is a callback method from the SurfaceHolder class. It is called whenever the Surface we want to draw on is created, for example when the application starts or when we return from a pause. Respectivly the method surfaceDestroyed() is called whenever the surface is destroyed, for example when the application terminates or another application gets the focus.
1 2 3 4 5 6 7 8 9 10 11 | public void surfaceDestroyed(SurfaceHolder holder) { boolean retry = true; thread.setRunning(false); while (retry) { try { thread.join(); retry = false; } catch (InterruptedException e) { } } } |
In the Lunar Lander implemention the drawing thread is terminated on the first time the surface is destroyed. If we then try to come back to the application, for example with a long click on the home button, the application throws this exception:
java.lang.IllegalThreadStateException: Thread already started.
We reached an illegal state because a thread is only allowed to be started a single time!
To fix this issue I don’t stop the drawing thread in my application if the app looses focus. Instead I just stop drawing and let the thread sleep for a while (and thus save the CPU resources etc). When the app gets focus again, the drawing starts over. In the example below this behaviour is controlled by the paused variable, running is the variable that is set to true when the game starts and is set to false when the app is terminated and the thread really needs to stop:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @Override public void run() { while (running) { while (paused) { try { Thread.sleep(50L); } catch (InterruptedException ignore) { } } Canvas canvas = null; try { canvas = holder.lockCanvas(null); draw(canvas); } finally { if (canvas != null) { holder.unlockCanvasAndPost(canvas); } } } } |
I’ve implemented this gameloop in a small example that displays Conway’s Game of Life:

Of course my implementation has a fixed timestep as suggested by the famous article Fix Your Timestep!
Download my example sourcecode here: android-gameloop-example-v1.zip
App in the Android Market: Gameloop Tutorial










