How to detect shake motion on Android phone

By yinrow | Apr 13, 2009

When I was implementing the shake-to-shuffle feature in Pair-Up game, I googled for a similar code-snippet but didn’t have much luck. Eventually I came across this hidden code in Android Developer Guide which talks about using the phone motion sensor to program:

http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/os/Sensors.html

Alas! It can be done! But I just need a very simple function to detect if there’s a shake action. So my actual code is a lot simpler:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// Need to implement SensorListener
public class ShakeActivity extends Activity implements SensorListener {
    // For shake motion detection.
    private SensorManager sensorMgr;
    private long lastUpdate = -1;
    private float x, y, z;
    private float last_x, last_y, last_z;
    private static final int SHAKE_THRESHOLD = 800;
 
    protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
        ...... // other initializations
	// start motion detection
	sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
	boolean accelSupported = sensorMgr.registerListener(this,
		SensorManager.SENSOR_ACCELEROMETER,
		SensorManager.SENSOR_DELAY_GAME);
 
	if (!accelSupported) {
	    // on accelerometer on this device
	    sensorMgr.unregisterListener(this,
                SensorManager.SENSOR_ACCELEROMETER);
	}
    }
 
    protected void onPause() {
	if (sensorMgr != null) {
	    sensorMgr.unregisterListener(this,
                SensorManager.SENSOR_ACCELEROMETER);
	    sensorMgr = null;
        }
	super.onPause();
    }
 
    public void onAccuracyChanged(int arg0, int arg1) {
	// TODO Auto-generated method stub
    }
 
    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) {
		    // yes, this is a shake action! Do something about it!
		}
		last_x = x;
		last_y = y;
		last_z = z;
	    }
	}
    }
}
6 Comments so far
  1. kristen April 15, 2009 8:43 pm

    Please fix timing oncollege level….not sensitive enough for given time.
    I will give 5 strs if tyou do. Please I love this game…almost.

  2. [...] 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 [...]

  3. Matthias May 4, 2009 11:41 am

    Thankx for sharing this. It works perfectly! The funny thing is that it detects a shake event when I slide out the keyboard. Did you experience the same?

  4. yinrow May 7, 2009 10:41 pm

    I think the sliding movement is detected by the sensor. Try increase the shake sensitivity threshold to see if that makes a difference.

  5. Matthias May 10, 2009 2:29 pm

    Thankx! I’ve optimized the threshold. Now it’s working perfectly. Thankx again. I’ve ported the code to the new SDK Version 1.5 if you’re interested:
    http://snipplr.com/view/14890/handling-shake-events-on-android-15/

  6. Dj January 26, 2010 8:06 am

    Love the game, however it drives me crazy that game doesn’t let me play till I loose. it ends my game with a score. But I never ran out of time. Would like to make MORE high scores.
    Would like to play TILL I RUN OUT OF TIME!!
    Thanks for fixing this anoying problem.

Leave a Comment

If you would like to make a comment, please fill out the form below.

Name (required)

Email (required)

Website

Comments

© 2007 - 2009 ClingMarks