Here is my implementation of shake detection for android.
/* The following code was written by Matthew Wiggins * and is released under the APACHE 2.0 license * * http://www.apache.org/licenses/LICENSE-2.0 */ package com.hlidskialf.android.hardware; import android.hardware.SensorListener; import android.hardware.SensorManager; import android.content.Context; import java.lang.UnsupportedOperationException; public class ShakeListener implements SensorListener { private static final int FORCE_THRESHOLD = 350; private static final int TIME_THRESHOLD = 100; private static final int SHAKE_TIMEOUT = 500; private static final int SHAKE_DURATION = 1000; private static final int SHAKE_COUNT = 3; private SensorManager mSensorMgr; private float mLastX=-1.0f, mLastY=-1.0f, mLastZ=-1.0f; private long mLastTime; private OnShakeListener mShakeListener; private Context mContext; private int mShakeCount = 0; private long mLastShake; private long mLastForce; public interface OnShakeListener { public void onShake(); } public ShakeListener(Context context) { mContext = context; resume(); } public void setOnShakeListener(OnShakeListener listener) { mShakeListener = listener; } public void resume() { mSensorMgr = (SensorManager)mContext.getSystemService(Context.SENSOR_SERVICE); if (mSensorMgr == null) { throw new UnsupportedOperationException("Sensors not supported"); } boolean supported = mSensorMgr.registerListener(this, SensorManager.SENSOR_ACCELEROMETER, SensorManager.SENSOR_DELAY_GAME); if (!supported) { mSensorMgr.unregisterListener(this, SensorManager.SENSOR_ACCELEROMETER); throw new UnsupportedOperationException("Accelerometer not supported"); } } public void pause() { if (mSensorMgr != null) { mSensorMgr.unregisterListener(this, SensorManager.SENSOR_ACCELEROMETER); mSensorMgr = null; } } public void onAccuracyChanged(int sensor, int accuracy) { } public void onSensorChanged(int sensor, float[] values) { if (sensor != SensorManager.SENSOR_ACCELEROMETER) return; long now = System.currentTimeMillis(); if ((now - mLastForce) > SHAKE_TIMEOUT) { mShakeCount = 0; } if ((now - mLastTime) > TIME_THRESHOLD) { long diff = now - mLastTime; float speed = Math.abs(values[SensorManager.DATA_X] + values[SensorManager.DATA_Y] + values[SensorManager.DATA_Z] - mLastX - mLastY - mLastZ) / diff * 10000; if (speed > FORCE_THRESHOLD) { if ((++mShakeCount >= SHAKE_COUNT) && (now - mLastShake > SHAKE_DURATION)) { mLastShake = now; mShakeCount = 0; if (mShakeListener != null) { mShakeListener.onShake(); } } mLastForce = now; } mLastTime = now; mLastX = values[SensorManager.DATA_X]; mLastY = values[SensorManager.DATA_Y]; mLastZ = values[SensorManager.DATA_Z]; } } }
A simple testbed activity
public class ShakeListenerTestActivity extends Activity { private ShakeListener mShaker; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final Vibrator vibe = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE); mShaker = new ShakeListener(this); mShaker.setOnShakeListener(new ShakeListener.OnShakeListener () { public void onShake() { vibe.vibrate(100); new AlertDialog.Builder(Testy.this) .setPositiveButton(android.R.string.ok, null) .setMessage("Shooken!") .show(); } }); } @Override public void onResume() { mShaker.resume(); super.onResume(); } @Override public void onPause() { mShaker.pause(); super.onPause(); } }