Android摇晃检测ShakeDetector

做游戏的时候,一般都要使用到多种多样的传感器,以实现比较丰富的UI 互动,比如检测手机的晃动。

如何检测手机的摇晃和摇晃程度呢?

找了些资料,并加以改进,将此功能封装成类(ShakeDetector),方便今后使用。

 

http://blog.csdn.net/ZhengZhiRen/archive/2010/10/09/5930451.aspx

摇晃检测基于加速传感器(Sensor.TYPE_ACCELEROMETER)。

由于重力的存在,当手机静止放于桌面时,加速传感器也是有加速度的。

所以,仅通过是否有加速度来判断摇晃是不行的。

那么,判断加速度的变化吧。。。

在一个较短的时间间隔求出加速度的差值,跟一个指定的阈值比较,如果差值大于阈值,则认为是摇晃发生了。

ClingMarks的方法将x、y、z方向的加速度差值简单的加起来,我认为不是很准确。

加速度是向量,求差应该是各方向的差值平方后相加,再开方。(数学忘光了,没记错吧。。。)

 

代码

  1. package zhengzhiren.android.hardware;  
  2. import java.util.ArrayList;  
  3. import android.content.Context;  
  4. import android.hardware.Sensor;  
  5. import android.hardware.SensorEvent;  
  6. import android.hardware.SensorEventListener;  
  7. import android.hardware.SensorManager;  
  8. import android.util.FloatMath;  
  9. /** 
  10.  * 用于检测手机摇晃 
  11.  *  
  12.  * @author 郑智仁 
  13.  * @see <a href="http://blog.csdn.net/zhengzhiren" mce_href="http://blog.csdn.net/zhengzhiren">Blog</a> 
  14.  */  
  15. public class ShakeDetector implements SensorEventListener {  
  16.     /** 
  17.      * 检测的时间间隔 
  18.      */  
  19.     static final int UPDATE_INTERVAL = 100;  
  20.     /** 
  21.      * 上一次检测的时间 
  22.      */  
  23.     long mLastUpdateTime;  
  24.     /** 
  25.      * 上一次检测时,加速度在x、y、z方向上的分量,用于和当前加速度比较求差。 
  26.      */  
  27.     float mLastX, mLastY, mLastZ;  
  28.     Context mContext;  
  29.     SensorManager mSensorManager;  
  30.     ArrayList<OnShakeListener> mListeners;  
  31.     /** 
  32.      * 摇晃检测阈值,决定了对摇晃的敏感程度,越小越敏感。 
  33.      */  
  34.     public int shakeThreshold = 5000;  
  35.     public ShakeDetector(Context context) {  
  36.         mContext = context;  
  37.         mSensorManager = (SensorManager) context  
  38.                 .getSystemService(Context.SENSOR_SERVICE);  
  39.         mListeners = new ArrayList<OnShakeListener>();  
  40.     }  
  41.     /** 
  42.      * 当摇晃事件发生时,接收通知 
  43.      */  
  44.     public interface OnShakeListener {  
  45.         /** 
  46.          * 当手机摇晃时被调用 
  47.          */  
  48.         void onShake();  
  49.     }  
  50.     /** 
  51.      * 注册OnShakeListener,当摇晃时接收通知 
  52.      *  
  53.      * @param listener 
  54.      */  
  55.     public void registerOnShakeListener(OnShakeListener listener) {  
  56.         if (mListeners.contains(listener))  
  57.             return;  
  58.         mListeners.add(listener);  
  59.     }  
  60.     /** 
  61.      * 移除已经注册的OnShakeListener 
  62.      *  
  63.      * @param listener 
  64.      */  
  65.     public void unregisterOnShakeListener(OnShakeListener listener) {  
  66.         mListeners.remove(listener);  
  67.     }  
  68.     /** 
  69.      * 启动摇晃检测 
  70.      */  
  71.     public void start() {  
  72.         if (mSensorManager == null) {  
  73.             throw new UnsupportedOperationException();  
  74.         }  
  75.         Sensor sensor = mSensorManager  
  76.                 .getDefaultSensor(Sensor.TYPE_ACCELEROMETER);  
  77.         if (sensor == null) {  
  78.             throw new UnsupportedOperationException();  
  79.         }  
  80.         boolean success = mSensorManager.registerListener(this, sensor,  
  81.                 SensorManager.SENSOR_DELAY_GAME);  
  82.         if (!success) {  
  83.             throw new UnsupportedOperationException();  
  84.         }  
  85.     }  
  86.     /** 
  87.      * 停止摇晃检测 
  88.      */  
  89.     public void stop() {  
  90.         if (mSensorManager != null)  
  91.             mSensorManager.unregisterListener(this);  
  92.     }  
  93.     @Override  
  94.     public void onAccuracyChanged(Sensor sensor, int accuracy) {  
  95.         // TODO Auto-generated method stub  
  96.     }  
  97.     @Override  
  98.     public void onSensorChanged(SensorEvent event) {  
  99.         long currentTime = System.currentTimeMillis();  
  100.         long diffTime = currentTime - mLastUpdateTime;  
  101.         if (diffTime < UPDATE_INTERVAL)  
  102.             return;  
  103.         mLastUpdateTime = currentTime;  
  104.         float x = event.values[0];  
  105.         float y = event.values[1];  
  106.         float z = event.values[2];  
  107.         float deltaX = x - mLastX;  
  108.         float deltaY = y - mLastY;  
  109.         float deltaZ = z - mLastZ;  
  110.         mLastX = x;  
  111.         mLastY = y;  
  112.         mLastZ = z;  
  113.         float delta = FloatMath.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ  
  114.                 * deltaZ)  
  115.                 / diffTime * 10000;  
  116.         if (delta > shakeThreshold) { // 当加速度的差值大于指定的阈值,认为这是一个摇晃  
  117.             this.notifyListeners();  
  118.         }  
  119.     }  
  120.     /** 
  121.      * 当摇晃事件发生时,通知所有的listener 
  122.      */  
  123.     private void notifyListeners() {  
  124.         for (OnShakeListener listener : mListeners) {  
  125.             listener.onShake();  
  126.         }  
  127.     }  


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值