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 :)

  5. Vikrant
    April 29th, 2010 at 21:16 | #5

    nice and simple approach…Plan to implement in my codebase…Thanks

    Vikrant

  6. beg
    June 4th, 2010 at 06:08 | #6

    really looking forward part II, how do you implement shake directions?

  7. Android Shogun
    June 26th, 2010 at 12:31 | #7

    i will write a blog when i have more time next month…

  8. Thomas
    July 16th, 2010 at 00:21 | #8

    What do you get here?

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

    What does the addition and subtraction of accelerations on different axises mean – I think x, y and z aren’t vectors, are they?

  1. June 29th, 2010 at 07:40 | #1