views:

1904

answers:

5

I need to add a shake feature that will refresh my Anroid application.

All I find of documentation involves implementing the SensorListener, but Eclipse tells me it's deprecated and suggest SensorEventListener.

Anybody that has a nice guide to how I go about creating this "shake controller"?

+1  A: 

you should subscribe as a SensorEventListener, and get the accelerometer data. once you have it, you should monitor for sudden change in direction (sign) of acceleration on a certain axis. it would be a good indication for the 'shake' movement.

Reflog
+4  A: 

Here's a tutorial for just that. The tutorial also contains this Google forum discussion link with interesting info on this subject.

JRL
Thank for posting the link. I wrote that tutorial over a year ago and still use that code in my game "WordWrench".
snctln
Good post! I love the low-cut filter method. Now I do not need a timer.
hongster
+10  A: 

Here is an example code. Put this into your activity class:

  /* put this into your activity class */
  private SensorManager mSensorManager;
  private float mAccel; // acceleration apart from gravity
  private float mAccelCurrent; // current acceleration including gravity
  private float mAccelLast; // last acceleration including gravity

  private final SensorEventListener mSensorListener = new SensorEventListener() {

    public void onSensorChanged(SensorEvent se) {
      float x = se.values[0];
      float y = se.values[1];
      float z = se.values[2];
      mAccelLast = mAccelCurrent;
      mAccelCurrent = (float) Math.sqrt((double) (x*x + y*y + z*z));
      float delta = mAccelCurrent - mAccelLast;
      mAccel = mAccel * 0.9f + delta; // perform low-cut filter
    }

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

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

  @Override
  protected void onStop() {
    mSensorManager.unregisterListener(mSensorListener);
    super.onStop();
  }

And add this to your onCreate method:

    /* do this in onCreate */
    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    mSensorManager.registerListener(mSensorListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
    mAccel = 0.00f;
    mAccelCurrent = SensorManager.GRAVITY_EARTH;
    mAccelLast = SensorManager.GRAVITY_EARTH;

You can then ask "mAccel" wherever you want in your application for the current acceleration, independent from the axis and cleaned from static acceleration such as gravity. It will be approx. 0 if there is no movement, and, lets say >2 if the device is shaked.

Notes:

The accelometer should be deactivated onStop and activated onResume to save resources (CPU, Battery). The code assumes we are on planet earth ;-) and initializes the acceleration to earth gravity. Otherwise you would get a strong "shake" when the application starts and "hits" the ground from free-fall. However, the code gets used to the gravitation due to the low-cut filter and would work also on other planets or in free space, once it is initialized. (you never know how long your application will be in use...;-)

Thilo Köhler
+1  A: 

Found a example that worked at last: http://android.hlidskialf.com/blog/code/android-shake-detection-listener

Sara
don't forget the VIBRATE permission to make it work: <uses-permission android:name="android.permission.VIBRATE" />
Hubert
A: 

Is a permission necessary to be allowed to connect to Context.SENSOR_SERVICE?

R. Mayo
This is not an answer. You should post this as a new question instead.
Jonas