Android Graphics and Animation Part III – Handling the Accelerometer

September 19th, 2011 by Keith Peters

It’s been a while, but we finally come to part 3 of this series.

In part 1 we learned the basics of setting up an Android project in Eclipse and drawing to the canvas.

In part 2 we covered animation and threading.

In this episode, we will look at handling the accelerometer, allowing you to control the animation by tilting your Android device.

Set up

We’ll continue on with the same project we created last time, which had a circle moving from left to right across the screen. Since we’ll be allowing the user to tilt the phone in any direction, we want to disable the auto-rotation feature that will change the orientation when the phone is tilted. This is done in the Android manifest xml file. We want to add the following line to the activity tag:

This will force the device to remain in portrait orientation no matter how it is tilted. The whole manifest will now look like this:

Listening for Accelerometer Events

The next thing we want to do is listen for accelerometer events, which will occur whenver the device is tilted. In reality, it’s not like you will only get events when the device is moving. You will get a steady stream of accelerometer events even if the device is sitting by itself on a table. But different types of applications may need to get these events more or less often. For example, a game may need to be very responsive and be very up to date on the events coming in, whereas in another type of application, it may not be so vital and you can opt to get the events less often to save on processing. Android allows you to listen for these events using the following values to control how often you will get them:

These are all static values on the SensorManager class. We’ll see how they are used in a moment.

First we’ll go into our AnimView class which starts out like this right now:

In addition to implementing the SurfaceHolder.Callback interface, we now want to implement the android.hardware.SensorEventListener interface. So import that interface and add it to the class signature:

This, of course, will cause the compiler to complain that you have not implemented the required methods of that interface. Triggering a quick fix will add the following method stubs:

Before we do anything with these, we need to write the code that listens for the sensor events. We’ll do that right in the constructor.

First we get an instance of the SensorManager class. This is done by calling the getSystemService on the context that is passed into the view’s constructor. We tell it which service we want: the Context.SENSOR_SERVICE.

Once we have the SensorManager, we need to check if there is indeed an accelerometer on this device. If so, we get the first available one. I’m not sure if any existing device has more than one accelerometer, but the api leaves that possibility open.

Finally, we register this class as a listener to the accelerometer, passing in the sensor delay you need, as covered earlier. At this point, we should start receiving events in the two methods we just added.

All we are interested in now is the onSensorChanged method, which will give us the data on how the device is currently oriented. As you can see, this method gets passed an instance of SensorEvent. This object has a property called values, which is a simple array of floats. For accelerometer events, the tilt on the x, y and z axes are represented by the first 3 elements of the array. i.e.:

event.values[0] is the degree of tilt on the x axis
event.values[1] is the degree of tilt on the y axis
event.values[2] is the degree of tilt on the z axis

All of these values will be in the range of -9.81 to +9.81. For a thorough explanation of why these values are used, see the SensorEvent class documentation here:

http://developer.android.com/reference/android/hardware/SensorEvent.html

For our purposes, we only care about the x and y axes. We’ll pass those values to the AnimThread class with a method called setTilt. This method doesn’t exist yet, but we’ll create it soon.

Note that the method will probably be called before and/or after the thread is created, so we’ll test to make sure it exists before calling any methods on it. For this simple demo, we won’t do any high or low pass filtering as described in the SensorEvent documentation, but if you wanted to do so, this would be a good place to do it.

Handling the Tilt Values

Now we need to create the setTilt method in AnimThread, but first let’s create a few properties there. We’ll need something to hold the raw tilt values, and some properties to hold the current position and velocity of the ball. The top of that class should now look like this:

Now we can create the setTilt method, which will be pretty simple:

Now all we have to do is make use of those values. The strategy is to add the tilt values (or at least a part of them) to the velocity values, then add the velocity to the position values, and finally draw the circle at the final x, y point. Here’s the run method in full:

We’re now at a point where you can test the app. Hold the phone flat when you start it. The ball should “roll” in the direction you tilt the phone. Of course, it will roll out of sight if you’re not careful, so we need to fix that next.

Handling Screen Edges – Bouncing

The following stuff I’ve covered in a number of books and tutorials on my personal site, www.bit-101.com, so I’m not going to belabor the point. We’re just going to see if the ball has gone past any edge of the screen and if so, place it on the edge and reverse the velocity on that axis. Here’s the final AnimThread class in full:

Now as you tilt the device, the ball will bounce off the edges of the screen, with just a little less force than it hit.

Summary

We now have a working, accelerometer-based interactive animation. This isn’t meant to be a perfect example in terms of best practices. I’d probalby pull out a lot of hard coded values into variables, extract some of the code into separate methods, etc. I’d also get a time delta between updates so that devices running at different speeds would run the animation at the same rate. Perhaps I’ll be able to cover some of that in a future tutorial. But this gives you a good idea of the structure and what happens where and how to get started.

8 Responses to “Android Graphics and Animation Part III – Handling the Accelerometer”

  1. android Says:

    Usually I do not learn article on blogs, but I wish to say that this write-up very pressured me to take a look at and do so! Your writing style has been amazed me. Thank you, quite nice article.

  2. Solai Luke Says:

    This is a really interesting post! Appreciate your this! With all the best Luke aka couchgool.

  3. Wahid Says:

    This is so good article ive ever read. Made me actually open up eclipse and write all.

    Keep it up!

    idea: Keep explaining each code what it does. :D

    Thanks
    Wahid

  4. click Says:

    Just to let you know your blog appears a little bit unusual in Firefox on my pc using Linux .

  5. Muhammad Ahmed Says:

    Great article, I am keenly waiting for your article on animation speed on different devices and how to control it. I have some sense of it but not quite as much , so would love your article on that..

    Thanks once again
    Muhammad Ahmed ,
    Pakistan

  6. Shalon Rallis Says:

    Amazing work. As Michael in the comment above says this is really art that needs to be framed and exhibeted in spacious gallery. Hope to see this work in Germany once.

  7. Otilia Holding Says:

    Canvas prints are great for matching room interiors with customized artwork.

  8. Megan Labrune Says:

    WOW! Thank you so much for including my little knockoff RH nightstands, Kate! I’m in great company! :)

Leave a Reply