我需要添加一个摇功能,将刷新我的Android应用程序。

我所找到的所有文档都涉及实现SensorListener,但Eclipse告诉我它已被弃用,并建议使用SensorEventListener。

有人知道如何创建这个震动控制器吗?


当前回答

和我一起工作,很好 参考

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

其他回答

下面是一个示例代码。 把这些放到你的活动课上:

  /* 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 onPause() {
    mSensorManager.unregisterListener(mSensorListener);
    super.onPause();
  }

把这个添加到你的onCreate方法中:

    /* 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;

然后你可以在你的应用程序中任何你想要的地方询问“mAccel”当前加速度,独立于轴,并从静态加速度(如重力)中清除。 大概是。如果没有移动,则为0,如果设备震动,则为>2。

根据评论-测试这一点:

if (mAccel > 12) {
    Toast toast = Toast.makeText(getApplicationContext(), "Device has shaken.", Toast.LENGTH_LONG);
    toast.show();
}

注:

The accelometer should be deactivated onPause 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...;-)

你可能想试试开源tinybus。有了它,震动检测就像这样简单。

public class MainActivity extends Activity {

    private Bus mBus;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...

        // Create a bus and attach it to activity
        mBus = TinyBus.from(this).wire(new ShakeEventWire());
    }

    @Subscribe
    public void onShakeEvent(ShakeEvent event) {
        Toast.makeText(this, "Device has been shaken", 
                Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onStart() {
        super.onStart();
        mBus.register(this);
    }

    @Override
    protected void onStop() {
        mBus.unregister(this);
        super.onStop();
    }
}

它采用地震仪进行振动检测。

我已经尝试了几种实现,但我想分享一下我自己的实现。 它以g力为单位进行阈值计算。这让我们更容易理解发生了什么,同时也设置了一个好的阈值。

它只是记录G力的增加,如果超过阈值就触发侦听器。它不使用任何方向阈值,因为如果你只是想记录一个好的震动,你真的不需要这个。

当然,您需要在Activity中对这个侦听器进行标准的注册和un -注册。

此外,为了检查您需要的阈值,我推荐以下应用程序(我没有以任何方式连接到该应用程序)

    public class UmitoShakeEventListener implements SensorEventListener {

    /**
     * The gforce that is necessary to register as shake. (Must include 1G
     * gravity)
     */
    private final float shakeThresholdInGForce = 2.25F;

    private final float gravityEarth = SensorManager.GRAVITY_EARTH;

    private OnShakeListener listener;

    public void setOnShakeListener(OnShakeListener listener) {
        this.listener = listener;
    }

    public interface OnShakeListener {
        public void onShake();
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // ignore

    }

    @Override
    public void onSensorChanged(SensorEvent event) {

        if (listener != null) {
            float x = event.values[0];
            float y = event.values[1];
            float z = event.values[2];

            float gX = x / gravityEarth;
            float gY = y / gravityEarth;
            float gZ = z / gravityEarth;

            //G-Force will be 1 when there is no movement. (gravity)
            float gForce = FloatMath.sqrt(gX * gX + gY * gY + gZ * gZ); 



            if (gForce > shakeThresholdInGForce) {
                listener.onShake();

            }
        }

    }

}

我写了一个检测垂直和水平震动并显示Toast的小例子。

public class Accelerometerka2Activity extends Activity implements SensorEventListener { 
    private float mLastX, mLastY, mLastZ;
    private boolean mInitialized;
    private SensorManager mSensorManager;
    private Sensor mAccelerometer;
    private final float NOISE = (float) 8.0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mInitialized = false;
        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mSensorManager.registerListener(this, mAccelerometer , SensorManager.SENSOR_DELAY_NORMAL);
    }

    protected void onResume() {
        super.onResume();
        mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
    }

    protected void onPause() {
        super.onPause();
        mSensorManager.unregisterListener(this);
    }


    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // can be safely ignored for this demo
    }


    public void onSensorChanged(SensorEvent event) {
        float x = event.values[0];
        float y = event.values[1];
        float z = event.values[2];
        if (!mInitialized) {
            mLastX = x;
            mLastY = y;
            mLastZ = z;
            mInitialized = true;
        } else {
            float deltaX = Math.abs(mLastX - x);
            float deltaY = Math.abs(mLastY - y);
            float deltaZ = Math.abs(mLastZ - z);
            if (deltaX < NOISE) deltaX = (float)0.0;
            if (deltaY < NOISE) deltaY = (float)0.0;
            if (deltaZ < NOISE) deltaZ = (float)0.0;
            mLastX = x;
            mLastY = y;
            mLastZ = z;
            if (deltaX > deltaY) {
                Toast.makeText(getBaseContext(), "Horizental", Toast.LENGTH_SHORT).show();
            } else if (deltaY > deltaX) {
                Toast.makeText(getBaseContext(), "Vertical", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

我真的很喜欢彼得dk的回答。我自作主张对他的代码做了一些调整。

文件:ShakeDetector.java

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.FloatMath;

public class ShakeDetector implements SensorEventListener {

    // The gForce that is necessary to register as shake. Must be greater than 1G (one earth gravity unit)
    private static final float SHAKE_THRESHOLD_GRAVITY = 2.7F;
    private static final int SHAKE_SLOP_TIME_MS = 500;
    private static final int SHAKE_COUNT_RESET_TIME_MS = 3000;

    private OnShakeListener mListener;
    private long mShakeTimestamp;
    private int mShakeCount;

    public void setOnShakeListener(OnShakeListener listener) {
        this.mListener = listener;
    }

    public interface OnShakeListener {
        public void onShake(int count);
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // ignore
    }

    @Override
    public void onSensorChanged(SensorEvent event) {

        if (mListener != null) {
            float x = event.values[0];
            float y = event.values[1];
            float z = event.values[2];

            float gX = x / SensorManager.GRAVITY_EARTH;
            float gY = y / SensorManager.GRAVITY_EARTH;
            float gZ = z / SensorManager.GRAVITY_EARTH;

            // gForce will be close to 1 when there is no movement.
            float gForce = FloatMath.sqrt(gX * gX + gY * gY + gZ * gZ);

            if (gForce > SHAKE_THRESHOLD_GRAVITY) {
                final long now = System.currentTimeMillis();
                // ignore shake events too close to each other (500ms)
                if (mShakeTimestamp + SHAKE_SLOP_TIME_MS > now ) {
                    return;
                }

                // reset the shake count after 3 seconds of no shakes
                if (mShakeTimestamp + SHAKE_COUNT_RESET_TIME_MS < now ) {
                    mShakeCount = 0;
                }

                mShakeTimestamp = now;
                mShakeCount++;

                mListener.onShake(mShakeCount);
            }
        }
    }
}

另外,不要忘记需要向SensorManager注册一个ShakeDetector实例。

// ShakeDetector initialization
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mShakeDetector = new ShakeDetector();
mShakeDetector.setOnShakeListener(new OnShakeListener() {

    @Override
    public void onShake(int count) {
            handleShakeEvent(count); 
        }
    });

mSensorManager.registerListener(mShakeDetector, mAccelerometer, SensorManager.SENSOR_DELAY_UI);