Android:我想动摇它

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

我找到的所有文档都涉及到实现SensorListener,但是Eclipse告诉我已经废弃了,建议使用SensorEventListener。

任何人有一个很好的指导,我怎么去创造这个摇控制器

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

/* 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(); } 

笔记:

加速计应在暂停状态下关闭,并启动onResume以节省资源(CPU,电池)。 该代码假设我们在地球上;-)并初始化加速到地球重力。 否则,当应用程序启动并从自由落体“撞击”地面时,会产生强烈的“震动”。 但是,由于低切滤波器,代码已经习惯了引力,并且在初始化之后也可以在其他行星或自由空间中工作。 (你永远不知道你的应用程序将被使用多久… 😉

这是我的手势检测代码:

 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 = 200; /** Maximum allowed time for shake gesture. */ private static final int MAX_TOTAL_DURATION_OF_SHAKE = 400; /** 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 < MAX_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) { } } 

将此添加到您的活动中:

  private SensorManager mSensorManager; private ShakeEventListener mSensorListener; 

在onCreate()中添加:

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

和:

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

这里还有一个实现,它建立在这里的一些提示以及Android开发者网站的代码上。

MainActivity.java

 public class MainActivity extends Activity { private ShakeDetector mShakeDetector; private SensorManager mSensorManager; private Sensor mAccelerometer; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // ShakeDetector initialization mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); mShakeDetector = new ShakeDetector(new OnShakeListener() { @Override public void onShake() { // Do stuff! } }); } @Override protected void onResume() { super.onResume(); mSensorManager.registerListener(mShakeDetector, mAccelerometer, SensorManager.SENSOR_DELAY_UI); } @Override protected void onPause() { mSensorManager.unregisterListener(mShakeDetector); super.onPause(); } } 

ShakeDetector.java

 package com.example.test; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; public class ShakeDetector implements SensorEventListener { // Minimum acceleration needed to count as a shake movement private static final int MIN_SHAKE_ACCELERATION = 5; // Minimum number of movements to register a shake private static final int MIN_MOVEMENTS = 2; // Maximum time (in milliseconds) for the whole shake to occur private static final int MAX_SHAKE_DURATION = 500; // Arrays to store gravity and linear acceleration values private float[] mGravity = { 0.0f, 0.0f, 0.0f }; private float[] mLinearAcceleration = { 0.0f, 0.0f, 0.0f }; // Indexes for x, y, and z values private static final int X = 0; private static final int Y = 1; private static final int Z = 2; // OnShakeListener that will be notified when the shake is detected private OnShakeListener mShakeListener; // Start time for the shake detection long startTime = 0; // Counter for shake movements int moveCount = 0; // Constructor that sets the shake listener public ShakeDetector(OnShakeListener shakeListener) { mShakeListener = shakeListener; } @Override public void onSensorChanged(SensorEvent event) { // This method will be called when the accelerometer detects a change. // Call a helper method that wraps code from the Android developer site setCurrentAcceleration(event); // Get the max linear acceleration in any direction float maxLinearAcceleration = getMaxCurrentLinearAcceleration(); // Check if the acceleration is greater than our minimum threshold if (maxLinearAcceleration > MIN_SHAKE_ACCELERATION) { long now = System.currentTimeMillis(); // Set the startTime if it was reset to zero if (startTime == 0) { startTime = now; } long elapsedTime = now - startTime; // Check if we're still in the shake window we defined if (elapsedTime > MAX_SHAKE_DURATION) { // Too much time has passed. Start over! resetShakeDetection(); } else { // Keep track of all the movements moveCount++; // Check if enough movements have been made to qualify as a shake if (moveCount > MIN_MOVEMENTS) { // It's a shake! Notify the listener. mShakeListener.onShake(); // Reset for the next one! resetShakeDetection(); } } } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // Intentionally blank } private void setCurrentAcceleration(SensorEvent event) { /* * BEGIN SECTION from Android developer site. This code accounts for * gravity using a high-pass filter */ // alpha is calculated as t / (t + dT) // with t, the low-pass filter's time-constant // and dT, the event delivery rate final float alpha = 0.8f; // Gravity components of x, y, and z acceleration mGravity[X] = alpha * mGravity[X] + (1 - alpha) * event.values[X]; mGravity[Y] = alpha * mGravity[Y] + (1 - alpha) * event.values[Y]; mGravity[Z] = alpha * mGravity[Z] + (1 - alpha) * event.values[Z]; // Linear acceleration along the x, y, and z axes (gravity effects removed) mLinearAcceleration[X] = event.values[X] - mGravity[X]; mLinearAcceleration[Y] = event.values[Y] - mGravity[Y]; mLinearAcceleration[Z] = event.values[Z] - mGravity[Z]; /* * END SECTION from Android developer site */ } private float getMaxCurrentLinearAcceleration() { // Start by setting the value to the x value float maxLinearAcceleration = mLinearAcceleration[X]; // Check if the y value is greater if (mLinearAcceleration[Y] > maxLinearAcceleration) { maxLinearAcceleration = mLinearAcceleration[Y]; } // Check if the z value is greater if (mLinearAcceleration[Z] > maxLinearAcceleration) { maxLinearAcceleration = mLinearAcceleration[Z]; } // Return the greatest value return maxLinearAcceleration; } private void resetShakeDetection() { startTime = 0; moveCount = 0; } // (I'd normally put this definition in it's own .java file) public interface OnShakeListener { public void onShake(); } } 

我真的很喜欢Peterdk的回答。 我自己花了一些时间来修改代码。

文件: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); 

我正在为我的大学项目开发​​一个运动检测和抖动检测应用程序。

除了应用程序的原始目标之外,我还将应用程序的库部分(负责运动和抖动检测)分开。 该代码是免费的,可以在SourceForge上使用项目名称“BenderCatch”。 我正在制作的文档将在9月中旬左右准备好。 http://sf.net/projects/bendercatch

它使用更精确的方式来检测摇动:当执行摇动时,观察SensorEvents与X和Y轴上存在的振动之间的差异。 它甚至可以在振动的每个振动上发出声音(或振动)。

请随时通过电子邮件询问我在raffaele [at] terzigno [dot] com

我已经写了一个小例子来检测垂直和水平的抖动,并显示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(); } } } } 

我已经尝试了几个实现,但想分享我自己的。 它使用G-force作为阈值计算的单位。 这使得了解发生的事情变得容易一些,并且设定了一个好的门槛。

它只是记录G力的增加,并且如果它超过阈值则触发听众。 它不使用任何方向的阈值,因为如果你只是想注册一个良好的震动,你并不需要。

当然,您需要在活动中进行标准的注册和联合注册。

此外,要检查您需要什么阈值,我推荐以下应用程序 (我不以任何方式连接到该应用程序)

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

这是另一个代码:

 import java.util.List; import java.util.Timer; import java.util.TimerTask; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Handler; public class AccelerometerListener implements SensorEventListener { private SensorManager sensorManager; private List<Sensor> sensors; private Sensor sensor; private long lastUpdate = -1; private long currentTime = -1; private Main parent; private Timer timer; private int shakes; private static final Handler mHandler = new Handler(); private float last_x, last_y, last_z; private float current_x, current_y, current_z, currenForce; private static final int FORCE_THRESHOLD = 500; private final int DATA_X = SensorManager.DATA_X; private final int DATA_Y = SensorManager.DATA_Y; private final int DATA_Z = SensorManager.DATA_Z; public AccelerometerListener(Main parent) { SensorManager sensorService = (SensorManager) parent .getSystemService(Context.SENSOR_SERVICE); this.sensorManager = sensorService; if (sensorService == null) return; this.sensors = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER); if (sensors.size() > 0) { sensor = sensors.get(0); } this.parent = parent; } public void start() { if (sensor == null) return; sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME); } public void stop() { if (sensorManager == null) return; sensorManager.unregisterListener(this); } public void onAccuracyChanged(Sensor s, int valu) { } public void onSensorChanged(SensorEvent event) { if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) return; currentTime = System.currentTimeMillis(); if ((currentTime - lastUpdate) > 50) { long diffTime = (currentTime - lastUpdate); lastUpdate = currentTime; current_x = event.values[DATA_X]; current_y = event.values[DATA_Y]; current_z = event.values[DATA_Z]; currenForce = Math.abs(current_x + current_y + current_z - last_x - last_y - last_z) / diffTime * 10000; if (currenForce > FORCE_THRESHOLD) { shakeDetected(); } last_x = current_x; last_y = current_y; last_z = current_z; } } private void shakeDetected() { shakes++; if (shakes == 1) { if (timer != null) { timer.cancel(); } timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { if (shakes > 3) { mHandler.post(new Runnable() { public void run() { // shake } }); } shakes = 0; } }, 500); } } } 

你可以使用地震 。 一个例子可以在这里找到。

 package anywheresoftware.b4a.student; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.util.FloatMath; public class ShakeEventListener implements SensorEventListener { /* * The gForce that is necessary to register as shake. * Must be greater than 1G (one earth gravity unit). * You can install "G-Force", by Blake La Pierre * from the Google Play Store and run it to see how * many G's it takes to register a shake */ private static final float SHAKE_THRESHOLD_GRAVITY = 2.7F; private static int SHAKE_SLOP_TIME_MS = 500; private static final int SHAKE_COUNT_RESET_TIME_MS = 1000; 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 + getSHAKE_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); } } } private long getSHAKE_SLOP_TIME_MS() { // TODO Auto-generated method stub return SHAKE_SLOP_TIME_MS; } public void setSHAKE_SLOP_TIME_MS(int sHAKE_SLOP_TIME_MS) { SHAKE_SLOP_TIME_MS = sHAKE_SLOP_TIME_MS; } } 
  package com.example.shakingapp; import android.app.Activity; import android.graphics.Color; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Bundle; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.Toast; public class MainActivity extends Activity implements SensorEventListener { private SensorManager sensorManager; private boolean color = false; private View view; private long lastUpdate; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); view = findViewById(R.id.textView); view.setBackgroundColor(Color.GREEN); sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); lastUpdate = System.currentTimeMillis(); } @Override public void onSensorChanged(SensorEvent event) { if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { getAccelerometer(event); } } private void getAccelerometer(SensorEvent event) { float[] values = event.values; // Movement float x = values[0]; float y = values[1]; float z = values[2]; System.out.println(x); System.out.println(y); System.out.println(z); System.out.println(SensorManager.GRAVITY_EARTH ); float accelationSquareRoot = (x * x + y * y + z * z) / (SensorManager.GRAVITY_EARTH * SensorManager.GRAVITY_EARTH); long actualTime = System.currentTimeMillis(); if (accelationSquareRoot >= 2) // { if (actualTime - lastUpdate < 200) { return; } lastUpdate = actualTime; Toast.makeText(this, "Device was shuffed "+accelationSquareRoot, Toast.LENGTH_SHORT) .show(); if (color) { view.setBackgroundColor(Color.GREEN); } else { view.setBackgroundColor(Color.RED); } color = !color; } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @Override protected void onResume() { super.onResume(); // register this class as a listener for the orientation and // accelerometer sensors sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL); } @Override protected void onPause() { // unregister listener super.onPause(); sensorManager.unregisterListener(this); } } 

Shaker.java

  import java.util.ArrayList; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; public class Shaker implements SensorEventListener{ private static final String SENSOR_SERVICE = Context.SENSOR_SERVICE; private SensorManager sensorMgr; private Sensor mAccelerometer; private boolean accelSupported; private long timeInMillis; private long threshold; private OnShakerTreshold listener; ArrayList<Float> valueStack; public Shaker(Context context, OnShakerTreshold listener, long timeInMillis, long threshold) { try { this.timeInMillis = timeInMillis; this.threshold = threshold; this.listener = listener; if (timeInMillis<100){ throw new Exception("timeInMillis < 100ms"); } valueStack = new ArrayList<Float>((int)(timeInMillis/100)); sensorMgr = (SensorManager) context.getSystemService(SENSOR_SERVICE); mAccelerometer = sensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); } catch (Exception e){ e.printStackTrace(); } } public void start() { try { accelSupported = sensorMgr.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); if (!accelSupported) { stop(); throw new Exception("Sensor is not supported"); } } catch (Exception e){ e.printStackTrace(); } } public void stop(){ try { sensorMgr.unregisterListener(this, mAccelerometer); } catch (Exception e){ e.printStackTrace(); } } @Override protected void finalize() throws Throwable { try { stop(); } catch (Exception e){ e.printStackTrace(); } super.finalize(); } long lastUpdate = 0; private float last_x; private float last_y; private float last_z; public void onSensorChanged(SensorEvent event) { try { if (event.sensor == mAccelerometer) { long curTime = System.currentTimeMillis(); if ((curTime-lastUpdate)>getNumberOfMeasures()){ lastUpdate = System.currentTimeMillis(); float[] values = event.values; if (valueStack.size()>(int)getNumberOfMeasures()) valueStack.remove(0); float x = (int)(values[SensorManager.DATA_X]); float y = (int)(values[SensorManager.DATA_Y]); float z = (int)(values[SensorManager.DATA_Z]); float speed = Math.abs((x+y+z) - (last_x + last_y + last_z)); valueStack.add(speed); String posText = String.format("X:%4.0f Y:%4.0f Z:%4.0f", (x-last_x), (y-last_y), (z-last_z)); last_x = (x); last_y = (y); last_z = (z); float sumOfValues = 0; float avgOfValues = 0; for (float f : valueStack){ sumOfValues = (sumOfValues+f); } avgOfValues = sumOfValues/(int)getNumberOfMeasures(); if (avgOfValues>=threshold){ listener.onTreshold(); valueStack.clear(); } System.out.println(String.format("M: %+4d A: %5.0f V: %4.0f %s", valueStack.size(),avgOfValues,speed,posText)); } } } catch (Exception e){ e.printStackTrace(); } } private long getNumberOfMeasures() { return timeInMillis/100; } public void onAccuracyChanged(Sensor sensor, int accuracy) {} public interface OnShakerTreshold { public void onTreshold(); } } 

MainActivity.java

 public class MainActivity extends Activity implements OnShakerTreshold{ private Shaker s; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); s = new Shaker(getApplicationContext(), this, 5000, 20); // 5000 = 5 second of shaking // 20 = minimal threshold (very angry shaking :D) // beware screen rotation reset counter } @Override protected void onResume() { s.start(); super.onResume(); } @Override protected void onPause() { s.stop(); super.onPause(); } public void onTreshold() { System.out.println("FIRE LISTENER"); RingtoneManager.getRingtone(getApplicationContext(), RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)).play(); } } 

玩的开心。

 // Need to implement SensorListener public class ShakeActivity extends Activity implements SensorListener { // For shake motion detection. private SensorManager sensorMgr; private long lastUpdate = -1; private float x, y, z; private float last_x, last_y, last_z; private static final int SHAKE_THRESHOLD = 800; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // start motion detection sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE); boolean accelSupported = sensorMgr.registerListener(this, SensorManager.SENSOR_ACCELEROMETER, SensorManager.SENSOR_DELAY_GAME); if (!accelSupported) { // on accelerometer on this device sensorMgr.unregisterListener(this, SensorManager.SENSOR_ACCELEROMETER); } } protected void onPause() { if (sensorMgr != null) { sensorMgr.unregisterListener(this, SensorManager.SENSOR_ACCELEROMETER); sensorMgr = null; } super.onPause(); } public void onAccuracyChanged(int arg0, int arg1) { // TODO Auto-generated method stub } public void onSensorChanged(int sensor, float[] values) { if (sensor == SensorManager.SENSOR_ACCELEROMETER) { long curTime = System.currentTimeMillis(); // only allow one update every 100ms. if ((curTime - lastUpdate)> 100) { long diffTime = (curTime - lastUpdate); lastUpdate = curTime; x = values[SensorManager.DATA_X]; y = values[SensorManager.DATA_Y]; z = values[SensorManager.DATA_Z]; float speed = Math.abs(x+y+z - last_x - last_y - last_z) / diffTime * 10000; if (speed > SHAKE_THRESHOLD) { // yes, this is a shake action! Do something about it! } last_x = x; last_y = y; last_z = z; } } } } 

您应该订阅SensorEventListene r,并获取accelerometer数据。 一旦你有了它,你应该监视某个轴上加速度方向(符号)的突然变化。 这将是'shake'运动的一个很好的指示。

与我合作v.good 参考

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

You might want to try open source tinybus . With it shake detection is as easy as this.

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

It uses seismic for shake detection.