How to detect shake motion in Android – part I
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!
“(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.
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
Thanks! Scalar velocity that is
Thanks! I will have the 2nd part of the article written, when I have time
nice and simple approach…Plan to implement in my codebase…Thanks
Vikrant
really looking forward part II, how do you implement shake directions?
i will write a blog when i have more time next month…
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?