Home > Android, Mobile, iPhone > How to detect shake motion in Android – part I

How to detect shake motion in Android – part I

April 17th, 2009

Gesture/Motion-based detection is fast becoming an integral part of many mobile applications.

One neat usage of it is to shake to erease.  The first one I’ve encountered is SketchUp from the early days of jailbreak iPhone.  Then there are shake to delete done-items on your todo/shopping list, etc.

There are many approaches to detect shake motion, one is from ClingMarks.  Basically it calculates the total delta (changes) in all 3 axises: x, y and z between the current even time and the previous one, and divide by the time elapsed to find its psudo-velocity.  (I call it psudo because it’s not actually a velocity in any direction; it’s more like a mixed-up velocity from 3 axises).  If this velocity is greater than a pre-defined threshold, it’s been viewed as a shake motion.

From the code point of view, you need to implement the SensorListener:

public class ShakeActivity extends Activity implements SensorListener

You will need to acquire a SensorManager:

sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);

And register this sensor with desired flags:

ensorMgr.registerListener(this,
SensorManager.SENSOR_ACCELEROMETER,
SensorManager.SENSOR_DELAY_GAME);

In your onSensorChange() method, you determine whether it’s a shake or not:

public void onSensorChanged(int sensor, float[] values) {
if (sensor == SensorManager.SENSOR_ACCELEROMETER) {
long curTime = System.currentTimeMillis();
// only allow one update every 100ms.
if ((curTime - lastUpdate) > 100) {
long diffTime = (curTime - lastUpdate);
lastUpdate = curTime;

x = values[SensorManager.DATA_X];
y = values[SensorManager.DATA_Y];
z = values[SensorManager.DATA_Z];

float speed = Math.abs(x+y+z – last_x – last_y – last_z) / diffTime * 10000;

if (speed > SHAKE_THRESHOLD) {
Log.d(”sensor”, “shake detected w/ speed: ” + speed);
Toast.makeText(this, “shake detected w/ speed: ” + speed, Toast.LENGTH_SHORT).show();
}
last_x = x;
last_y = y;
last_z = z;
}
}
}

The shake threshold is defined as:

private static final int SHAKE_THRESHOLD = 800;

This is pretty straightforward. So if your app just simply needs a shake motion detection, w/o needing to know on which direction it’s shaken, this code is good enough. However, there are situations where a non-shake motion would be detected as shake due to the fact that the formula is not actually the correct or should I say a precise formula for determining the shake motion. I call this a coarse-grain approach.

In my next post, I will show you a more fine-grain approach, something I learned from iPhone SDK programming :)

You can download this sample here

Happy Coding!

Android Shogun Android, Mobile, iPhone , , ,

  1. Hans
    May 23rd, 2009 at 04:06 | #1

    “(I call it psuedo because it’s not actually a velocity in any direction; it’s more like a mixed-up velocity from 3 axises).”

    Actually, if you remember your physics course, a real velocity is a vector, with components in all three dimensions. The velocity in only one direction would be more precisely called a “scalar velocity” in that direction, and more worthy of the “pseudo” tag.

  2. May 23rd, 2009 at 11:02 | #2

    Thanks for the info. I am trying to detect the direction, so will extend your approach to measure the difference of the acceleration values. Cheers! Cass

  3. Android Shogun
    June 13th, 2009 at 17:35 | #3

    Thanks! Scalar velocity that is :)

  4. Android Shogun
    June 13th, 2009 at 17:36 | #4

    Thanks! I will have the 2nd part of the article written, when I have time :)

  1. No trackbacks yet.