How to detect shake motion on Android phone

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;
	    }
	}
    }
}

 
Add a comment

Comments (22)

  1. Alex, January 13, 2012
    SensorListener is now deprecated. This is the equivalent code using "implements SensorEventListener" [code] protected void onCreate(Bundle savedInstanceState) { ...... // start motion detection sensorMgr=(SensorManager) getSystemService(SENSOR_SERVICE); sensorMgr.registerListener(this, sensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL); } public void onAccuracyChanged(Sensor s, int arg1) { // TODO Auto-generated method stub } @Override public void onSensorChanged(SensorEvent event) { if (event.sensor.getType()==Sensor.TYPE_ACCELEROMETER){ long curTime = System.currentTimeMillis(); // only allow one update every 100ms. if ((curTime - lastUpdate) > 100) { long diffTime = (curTime - lastUpdate); lastUpdate = curTime; x = event.values[0]; y = event.values[1]; z = event.values[2]; 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; } } } @Override protected void onPause() { if (sensorMgr != null) { sensorMgr.unregisterListener(this); sensorMgr = null; } super.onPause(); } [/code] Reply
  2. Sam, December 20, 2011
    Thanks a lot! It Works perfectly to detect states like moving or still! Reply
  3. Raffaele De Falco, August 22, 2011
    I am developing a motion-detection and shake-detection app for my university project. Besides the original target of the application, I am splitting the library part (responsible for motion and shake detection) from the app. The code is free, available on SourceForge with the project name "BenderCatch". Documentation I am producing will be ready around mid-september. It uses a more precise way to detect shake: watches BOTH the force-difference (as described in this article) AND the oscillations present in X and Y axis when you perform a shake. It can even make a sound (or vibrate) on each oscillation of the shake. Feel free to ask me more by e-mail at raffaele [at] terzigno [dot] com Reply
  4. Emin, August 14, 2011
    We want to catch telephone movement in space, x, y, z coordinates. Is sensors.java right for implementing this? We run/debug, but could not test via telephone. Both version is 1.6. At any try, we could success, no debugging occured, could not see that it falled into OnCreate method. Steps we followed: . SDK downloaded Google USB Driver and we see in available packages . We updated USB driver for LG optimus 540 with Google USB driver. . we run SDK . we debug code . we run (adb.exe devices) command Thanks in advance, Regards. Reply
  5. Matt, July 13, 2011
    Thanks. The is-shaking code was exactly what i needed! :) Reply
  6. rohan, June 10, 2011
    Just a correction. The interface SensorListener is deprecated and is no longer in use. Rather than that SensorEventListener is used. Reply
  7. Srishti, June 9, 2011
    The link mentioned above has been changed to : http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/os/Sensors.html Reply
  8. mike, March 26, 2011
    thanks this is great! most people shake in the x-y direction, so you might want to make the z axis much more sensitive than the others ;) works perfectly though !! :) Reply
  9. Dexter LaBora, January 6, 2011
    Disregard my previous question... the & gt in the code was intended to be a > sign but was mangled. Cheers. Reply
  10. Dexter LaBora, January 5, 2011
    Where did you define the variable gt ? What is this exactly? if ((curTime - lastUpdate) > 100) { Thanks for the info Reply
  11. Dj, January 26, 2010
    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. Reply
  12. Matthias, May 10, 2009
    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/ Reply
  13. yinrow, May 7, 2009
    I think the sliding movement is detected by the sensor. Try increase the shake sensitivity threshold to see if that makes a difference. Reply
  14. Matthias, May 4, 2009
    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? Reply
  15. kristen, April 15, 2009
    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. Reply

Add a comment

Top
(it will not be shared)