Android:Shake Detector太敏感了

时间:2013-02-14 15:49:29

标签: android android-sensors

我正试图检测一下摇晃 - 我正在使用以下代码, 它工作得非常好,但在某些设备中(例如Galaxy note 2)它会很快检测到震动(在某些情况下 - 当我只是按住手机时)

main.java:

ShakeListener mShaker = new ShakeListener(this);
     mShaker.setOnShakeListener(new ShakeListener.OnShakeListener () {
         public void onShake()
         {
        // Some code...
         }
     });
}

ShakeListener.java:

package com.my.app;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.widget.Toast;
import android.content.Context;
import java.lang.UnsupportedOperationException;

public class ShakeListener implements SensorEventListener
{
      private static final int FORCE_THRESHOLD = 700;
      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 = 5;

      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 = false;
        try {
        supported = mSensorMgr.registerListener(this, mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_GAME);
        } catch (Exception e) {Toast.makeText(mContext, "Shaking not supported", Toast.LENGTH_LONG).show();}

        if ((!supported)&&(mSensorMgr != null)) mSensorMgr.unregisterListener(this);
      }

      public void pause() {
        if (mSensorMgr != null) {
          mSensorMgr.unregisterListener(this);
          mSensorMgr = null;
        }
      }

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

      public void onSensorChanged(SensorEvent event)
      {
        if (event.sensor.getType() != Sensor.TYPE_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(event.values[0] + event.values[1] + event.values[2] - 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 = event.values[0];
          mLastY = event.values[1];
          mLastZ = event.values[2];
        }
      }
}

4 个答案:

答案 0 :(得分:7)

使用更高的抖动次数检查加速度。看看这段代码对我有用。

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

            if (mAccel > 8) {
                 Toast.makeText(getApplicationContext(),
             "You have shaken your phone", Toast.LENGTH_SHORT).show();
            }

        }

        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            Log.i("Sensor", "mAccel" + mAccel);
        }
    };

答案 1 :(得分:0)

从较低的灵敏度开始,但如果超过某个初始阈值持续较长时间,则逐渐增加灵敏度。这类似于人类的感知。

答案 2 :(得分:0)

试试这个......让我知道..

public class ShakeListener implements SensorEventListener {
    private String TAG = ShakeListener.class.getSimpleName();
    private static final int FORCE_THRESHOLD = 800;
    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 = 5;

    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) {

        Log.d(TAG,"ShakeListener invoked---->");
        mContext = context;
        resume();
    }

    public void setOnShakeListener(OnShakeListener listener) {
        Log.d(TAG,"ShakeListener setOnShakeListener invoked---->");
        mShakeListener = listener;
    }

    public void resume() {
        mSensorMgr = (SensorManager) mContext
                .getSystemService(Context.SENSOR_SERVICE);
        if (mSensorMgr == null) {
            throw new UnsupportedOperationException("Sensors not supported");
        }
        boolean supported = false;
        try {
            supported = mSensorMgr.registerListener(this,
                    mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
                    SensorManager.SENSOR_DELAY_GAME);
        } catch (Exception e) {
            Toast.makeText(mContext, "Shaking not supported", Toast.LENGTH_LONG)
                    .show();
        }

        if ((!supported) && (mSensorMgr != null))
            mSensorMgr.unregisterListener(this);
    }

    public void pause() {
        if (mSensorMgr != null) {

            mSensorMgr.unregisterListener(this);
            mSensorMgr = null;
        }
    }

    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() != Sensor.TYPE_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(event.values[SensorManager.DATA_X]
                    + event.values[SensorManager.DATA_Y]
                    + event.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;
                     Log.d(TAG,"ShakeListener mShakeListener---->"+mShakeListener);
                    if (mShakeListener != null) {
                        mShakeListener.onShake();
                    }
                }
                mLastForce = now;
            }
            mLastTime = now;
            mLastX = event.values[SensorManager.DATA_X];
            mLastY = event.values[SensorManager.DATA_Y];
            mLastZ = event.values[SensorManager.DATA_Z];
        }
    }
}

答案 3 :(得分:0)

这对我很好:

public class ShakeEventListener implements SensorEventListener {
public final static int SHAKE_LIMIT = 15;
public final static int LITTLE_SHAKE_LIMIT = 5;

private SensorManager mSensorManager;
private float mAccel = 0.00f;
private float mAccelCurrent = SensorManager.GRAVITY_EARTH;
private float mAccelLast = SensorManager.GRAVITY_EARTH;

private ShakeListener listener;

public interface ShakeListener {
    public void onShake();
    public void onLittleShake();
}

public ShakeEventListener(ShakeListener l) {
    Activity a = (Activity) l;
    mSensorManager = (SensorManager) a.getSystemService(Context.SENSOR_SERVICE);
    listener = l;
    registerListener();
}

public ShakeEventListener(Activity a, ShakeListener l) {
    mSensorManager = (SensorManager) a.getSystemService(Context.SENSOR_SERVICE);
    listener = l;
    registerListener();
}

public void registerListener() {
    mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
}

public void unregisterListener() {
    mSensorManager.unregisterListener(this);
}

public void onSensorChanged(SensorEvent se) {
    float x = se.values[0];
    float y = se.values[1];
    float z = se.values[2];
    mAccelLast = mAccelCurrent;
    mAccelCurrent = (float) FloatMath.sqrt(x*x + y*y + z*z);
    float delta = mAccelCurrent - mAccelLast;
    mAccel = mAccel * 0.9f + delta;
    if(mAccel > SHAKE_LIMIT)
        listener.onShake();
    else if(mAccel > LITTLE_SHAKE_LIMIT)
        listener.onLittleShake();
}

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

Reference