【问题标题】:Android: Shake Detector too SensitiveAndroid:震动检测器过于敏感
【发布时间】:2013-02-14 15:49:29
【问题描述】:

我正在尝试检测震动 - 我正在使用以下代码, 它工作得非常好,但在某些设备(例如 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];
        }
      }
}

【问题讨论】:

标签: android android-sensors


【解决方案1】:

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

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);
        }
    };

【讨论】:

  • 如果你有灵敏度控制,请解释一下灵敏度控制的值变化是谁
  • 这将检测到任何可能不是震动的突然 SINGLE 运动 - 只需放下手机就会激活它。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    试试这个……然后告诉我……

    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];
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      这很适合我:

      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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-15
        • 2011-07-17
        相关资源
        最近更新 更多