Search code examples
androidaccelerometer

Detect Shake for 8 Sec


I am using Accelerometer for the purpose of shake detection but i want if a user will shake their devices for 8 Sec then the resulting method will be triggered. With my current code a can able to detect the shake but i want a 8sec timer too. My Current Code is

public class AccelerometerManager {
    private static Context aContext=null;

    /** Accuracy configuration */
    private static float threshold  = 15.0f;
    private static int interval     = 200;

    private static Sensor sensor;
    private static SensorManager sensorManager;
    // you could use an OrientationListener array instead
    // if you plans to use more than one listener
    private static AccelerometerListener listener;

    /** indicates whether or not Accelerometer Sensor is supported */
    private static Boolean supported;
    /** indicates whether or not Accelerometer Sensor is running */
    private static boolean running = false;

    /**
     * Returns true if the manager is listening to orientation changes
     */
    public static boolean isListening() {
        return running;
    }

    /**
     * Unregisters listeners
     */
    public static void stopListening() {
        running = false;
        try {
            if (sensorManager != null && sensorEventListener != null) {
                sensorManager.unregisterListener(sensorEventListener);
            }
        } catch (Exception e) {}
    }

    /**
     * Returns true if at least one Accelerometer sensor is available
     */
    public static boolean isSupported(Context context) {
        aContext = context;
        if (supported == null) {
            if (aContext != null) {


                sensorManager = (SensorManager) aContext.
                        getSystemService(Context.SENSOR_SERVICE);

                // Get all sensors in device
                List<Sensor> sensors = sensorManager.getSensorList(
                        Sensor.TYPE_ACCELEROMETER);

                supported = new Boolean(sensors.size() > 0);



            } else {
                supported = Boolean.FALSE;
            }
        }
        return supported;
    }

    /**
     * Configure the listener for shaking
     * @param threshold
     *             minimum acceleration variation for considering shaking
     * @param interval
     *             minimum interval between to shake events
     */
    public static void configure(int threshold, int interval) {
        AccelerometerManager.threshold = threshold;
        AccelerometerManager.interval = interval;
    }

    /**
     * Registers a listener and start listening
     * @param accelerometerListener
     *             callback for accelerometer events
     */
    public static void startListening( AccelerometerListener accelerometerListener )
    {

        sensorManager = (SensorManager) aContext.
                getSystemService(Context.SENSOR_SERVICE);

        // Take all sensors in device
        List<Sensor> sensors = sensorManager.getSensorList(
                Sensor.TYPE_ACCELEROMETER);

        if (sensors.size() > 0) {

            sensor = sensors.get(0);

            // Register Accelerometer Listener
            running = sensorManager.registerListener(
                    sensorEventListener, sensor,
                    SensorManager.SENSOR_DELAY_GAME);

            listener = accelerometerListener;
        }


    }

    /**
     * Configures threshold and interval
     * And registers a listener and start listening
     * @param accelerometerListener
     *             callback for accelerometer events
     * @param threshold
     *             minimum acceleration variation for considering shaking
     * @param interval
     *             minimum interval between to shake events
     */
    public static void startListening(
            AccelerometerListener accelerometerListener,
            int threshold, int interval) {
        configure(threshold, interval);
        startListening(accelerometerListener);
    }

    /**
     * The listener that listen to events from the accelerometer listener
     */
    private static SensorEventListener sensorEventListener =
            new SensorEventListener() {

                private long now = 0;
                private long timeDiff = 0;
                private long lastUpdate = 0;
                private long lastShake = 0;

                private float x = 0;
                private float y = 0;
                private float z = 0;
                private float lastX = 0;
                private float lastY = 0;
                private float lastZ = 0;
                private float force = 0;

                public void onAccuracyChanged(Sensor sensor, int accuracy) {}

                public void onSensorChanged(SensorEvent event) {
                    // use the event timestamp as reference
                    // so the manager precision won't depends
                    // on the AccelerometerListener implementation
                    // processing time
                    now = event.timestamp;

                    x = event.values[0];
                    y = event.values[1];
                    z = event.values[2];

                    // if not interesting in shake events
                    // just remove the whole if then else block
                    if (lastUpdate == 0) {
                        lastUpdate = now;
                        lastShake = now;
                        lastX = x;
                        lastY = y;
                        lastZ = z;
                        Toast.makeText(aContext,"No Motion detected",
                                Toast.LENGTH_SHORT).show();

                    } else {
                        timeDiff = now - lastUpdate;

                        if (timeDiff > 0) {

                    /*force = Math.abs(x + y + z - lastX - lastY - lastZ)
                                / timeDiff;*/
                            force = Math.abs(x + y + z - lastX - lastY - lastZ);

                            if (Float.compare(force, threshold) >0 ) {

                                if (now - lastShake >= 8000000000l) {

                                    // trigger shake event
                                    listener.onShake(force);
                                }
                                else
                                {
                                    Toast.makeText(aContext,"No Motion detected",
                                            Toast.LENGTH_SHORT).show();

                                }
                                lastShake = now;
                            }
                            lastX = x;
                            lastY = y;
                            lastZ = z;
                            lastUpdate = now;
                        }
                        else
                        {
                            Toast.makeText(aContext,"No Motion detected", Toast.LENGTH_SHORT).show();

                        }
                    }
                    // trigger change event
                    listener.onAccelerationChanged(x, y, z);
                }

            };

}

Solution

  • Try below code for detecting continues shake for 8 second.

    import android.hardware.Sensor;
    import android.hardware.SensorEvent;
    import android.hardware.SensorEventListener;
    import android.hardware.SensorManager;
    
    
    /**
     * Listener that detects shake gesture.
     */
    public class ShakeEventListener implements SensorEventListener {
    
    
      /** Minimum movement force to consider. */
      private static final int MIN_FORCE = 10;
    
      /**
       * Minimum times in a shake gesture that the direction of movement needs to
       * change.
       */
      private static final int MIN_DIRECTION_CHANGE = 3;
    
      /** Maximum pause between movements. */
      private static final int MAX_PAUSE_BETHWEEN_DIRECTION_CHANGE = 1000;
    
      /** Minimum allowed time for shake gesture. */
      private static final int MIN_TOTAL_DURATION_OF_SHAKE = 8000; // 8 seconds
    
      /** Time when the gesture started. */
      private long mFirstDirectionChangeTime = 0;
    
      /** Time when the last movement started. */
      private long mLastDirectionChangeTime;
    
      /** How many movements are considered so far. */
      private int mDirectionChangeCount = 0;
    
      /** The last x position. */
      private float lastX = 0;
    
      /** The last y position. */
      private float lastY = 0;
    
      /** The last z position. */
      private float lastZ = 0;
    
      /** OnShakeListener that is called when shake is detected. */
      private OnShakeListener mShakeListener;
    
      /**
       * Interface for shake gesture.
       */
      public interface OnShakeListener {
    
        /**
         * Called when shake gesture is detected.
         */
        void onShake();
      }
    
      public void setOnShakeListener(OnShakeListener listener) {
        mShakeListener = listener;
      }
    
      @Override
      public void onSensorChanged(SensorEvent se) {
        // get sensor data
        float x = se.values[SensorManager.DATA_X];
        float y = se.values[SensorManager.DATA_Y];
        float z = se.values[SensorManager.DATA_Z];
    
        // calculate movement
        float totalMovement = Math.abs(x + y + z - lastX - lastY - lastZ);
    
        if (totalMovement > MIN_FORCE) {
    
          // get time
          long now = System.currentTimeMillis();
    
          // store first movement time
          if (mFirstDirectionChangeTime == 0) {
            mFirstDirectionChangeTime = now;
            mLastDirectionChangeTime = now;
          }
    
          // check if the last movement was not long ago
          long lastChangeWasAgo = now - mLastDirectionChangeTime;
          if (lastChangeWasAgo < MAX_PAUSE_BETHWEEN_DIRECTION_CHANGE) {
    
            // store movement data
            mLastDirectionChangeTime = now;
            mDirectionChangeCount++;
    
            // store last sensor data 
            lastX = x;
            lastY = y;
            lastZ = z;
    
            // check how many movements are so far
            if (mDirectionChangeCount >= MIN_DIRECTION_CHANGE) {
    
              // check total duration
              long totalDuration = now - mFirstDirectionChangeTime;
              if (totalDuration >= MIN_TOTAL_DURATION_OF_SHAKE) {
                mShakeListener.onShake();
                resetShakeParameters();
              }
            }
    
          } else {
            resetShakeParameters();
          }
        }
      }
    
      /**
       * Resets the shake parameters to their default values.
       */
      private void resetShakeParameters() {
        mFirstDirectionChangeTime = 0;
        mDirectionChangeCount = 0;
        mLastDirectionChangeTime = 0;
        lastX = 0;
        lastY = 0;
        lastZ = 0;
      }
    
      @Override
      public void onAccuracyChanged(Sensor sensor, int accuracy) {
      }
    
    }
    

    Add below code in your activity:

      private SensorManager mSensorManager;
    
      private ShakeEventListener mSensorListener;
    
    
        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mSensorListener = new ShakeEventListener();   
    
        mSensorListener.setOnShakeListener(new ShakeEventListener.OnShakeListener() {
    
          public void onShake() {
            Toast.makeText(this, "Shake detected!", Toast.LENGTH_SHORT).show();
          }
        });
    

    Register for shake listener in onResume method and unregister it in onPause method as below.

      @Override
      protected void onResume() {
        super.onResume();
        mSensorManager.registerListener(mSensorListener,
            mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
            SensorManager.SENSOR_DELAY_UI);
      }
    
      @Override
      protected void onPause() {
        mSensorManager.unregisterListener(mSensorListener);
        super.onPause();
      }