package org.linnaeus; import android.content.Context; import android.hardware.*; import java.util.ArrayList; /** * Created by IntelliJ IDEA. * User: Immortality * Date: 30.10.2010 * Time: 16:36:31 */ public final class ShakeManager implements SensorEventListener { private static final int FORCE_THRESHOLD = 1000; 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 Context _context; private SensorManager _sensorMgr; private long _lastUpdate = -1; private float _last_x, _last_y, _last_z; private int _shakeCount = 0; private long _lastShake; private long _lastForce; private ArrayList<ShakeEventListener> _listeners; public ShakeManager(Context context) { _context = context; _listeners = new ArrayList<ShakeEventListener>(); initSensorManager(); } private void initSensorManager(){ _sensorMgr = (SensorManager) _context.getSystemService(Context.SENSOR_SERVICE); boolean accelerometerSupported = _sensorMgr.registerListener(this, _sensorMgr.getDefaultSensor(SensorManager.SENSOR_ACCELEROMETER), SensorManager.SENSOR_DELAY_GAME); if (!accelerometerSupported) { // Non accelerometer on this device. _sensorMgr.unregisterListener(this); } } public void addListener(ShakeEventListener listener){ _listeners.add(listener); } public void onPause() { if (_sensorMgr != null) { _sensorMgr.unregisterListener(this, _sensorMgr.getDefaultSensor(SensorManager.SENSOR_ACCELEROMETER)); _sensorMgr = null; } } public void onResume(){ initSensorManager(); } @Override public void onSensorChanged(SensorEvent event) { Sensor mySensor = event.sensor; if (mySensor.getType() == SensorManager.SENSOR_ACCELEROMETER) { long curTime = System.currentTimeMillis(); if ((curTime - _lastForce) > SHAKE_TIMEOUT) { _shakeCount = 0; } // Only allow one update every 100ms. if ((curTime - _lastUpdate) > TIME_THRESHOLD) { long diffTime = (curTime - _lastUpdate); _lastUpdate = curTime; float x = event.values[SensorManager.DATA_X]; float y = event.values[SensorManager.DATA_Y]; float z = event.values[SensorManager.DATA_Z]; float speed = Math.abs(x + y + z - _last_x - _last_y - _last_z)/ diffTime * 10000; if (speed > FORCE_THRESHOLD) { if ((++_shakeCount >= SHAKE_COUNT) && (curTime - _lastShake > SHAKE_DURATION)) { _lastShake = curTime; _shakeCount = 0; if (_sensorMgr != null) { for(ShakeEventListener listener : _listeners) { listener.onShakeEvent(); } } } _lastForce = curTime; } _lastForce = curTime; _last_x = x; _last_y = y; _last_z = z; } } } @Override public void onAccuracyChanged(Sensor sensor, int i) { } public interface ShakeEventListener { public void onShakeEvent(); } }