使用加速傳感器判定手機搖晃代碼

做遊戲的時候,一般都要使用到多種多樣的傳感器,以實現比較豐富的UI 互動,比如檢測手機的晃動。

如何檢測手機的搖晃和搖晃程度呢?

找了些資料,並加以改進,將此功能封裝成類(ShakeDetector),方便今後使用。

 

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

搖晃檢測基於加速傳感器(Sensor.TYPE_ACCELEROMETER)。

由於重力的存在,當手機靜止放於桌面時,加速傳感器也是有加速度的。

所以,僅通過是否有加速度來判斷搖晃是不行的。

那麼,判斷加速度的變化吧。。。

在一個較短的時間間隔求出加速度的差值,跟一個指定的閾值比較,如果差值大於閾值,則認爲是搖晃發生了。

ClingMarks的方法將x、y、z方向的加速度差值簡單的加起來,我認爲不是很準確。

加速度是向量,求差應該是各方向的差值平方後相加,再開方。(數學忘光了,沒記錯吧。。。)

 

代碼

package zhengzhiren.android.hardware;  

  1. import java.util.ArrayList;  
  2. import android.content.Context;  
  3. import android.hardware.Sensor;  
  4. import android.hardware.SensorEvent;  
  5. import android.hardware.SensorEventListener;  
  6. import android.hardware.SensorManager;  
  7. import android.util.FloatMath;  
  8. /** 
  9.  * 用於檢測手機搖晃 
  10.  *  
  11.  * @author 鄭智仁 
  12.  *  
  13. */  
  14. public class ShakeDetector implements SensorEventListener {  
  15.     /** 
  16.      * 檢測的時間間隔 
  17.      */  
  18.     static final int UPDATE_INTERVAL = 100;  
  19.     /** 
  20.      * 上一次檢測的時間 
  21.      */  
  22.     long mLastUpdateTime;  
  23.     /** 
  24.      * 上一次檢測時,加速度在x、y、z方向上的分量,用於和當前加速度比較求差。 
  25.      */  
  26.     float mLastX, mLastY, mLastZ;  
  27.     Context mContext;  
  28.     SensorManager mSensorManager;  
  29.     ArrayList<OnShakeListener> mListeners;  
  30.     /** 
  31.      * 搖晃檢測閾值,決定了對搖晃的敏感程度,越小越敏感。 
  32.      */  
  33.     public int shakeThreshold = 3000;  
  34.     public ShakeDetector(Context context) {  
  35.         mContext = context;  
  36.         mSensorManager = (SensorManager) context  
  37.                 .getSystemService(Context.SENSOR_SERVICE);  
  38.         mListeners = new ArrayList<OnShakeListener>();  
  39.     }  
  40.     /** 
  41.      * 當搖晃事件發生時,接收通知 
  42.      */  
  43.     public interface OnShakeListener {  
  44.         /** 
  45.          * 當手機搖晃時被調用 
  46.          */  
  47.         void onShake();  
  48.     }  
  49.     /** 
  50.      * 註冊OnShakeListener,當搖晃時接收通知 
  51.      *  
  52.      * @param listener 
  53.      */  
  54.     public void registerOnShakeListener(OnShakeListener listener) {  
  55.         if (mListeners.contains(listener))  
  56.             return;  
  57.         mListeners.add(listener);  
  58.     }  
  59.     /** 
  60.      * 移除已經註冊的OnShakeListener 
  61.      *  
  62.      * @param listener 
  63.      */  
  64.     public void unregisterOnShakeListener(OnShakeListener listener) {  
  65.         mListeners.remove(listener);  
  66.     }  
  67.     /** 
  68.      * 啓動搖晃檢測 
  69.      */  
  70.     public void start() {  
  71.         if (mSensorManager == null) {  
  72.             throw new UnsupportedOperationException();  
  73.         }  
  74.         Sensor sensor = mSensorManager  
  75.                 .getDefaultSensor(Sensor.TYPE_ACCELEROMETER);  
  76.         if (sensor == null) {  
  77.             throw new UnsupportedOperationException();  
  78.         }  
  79.         boolean success = mSensorManager.registerListener(this, sensor,  
  80.                 SensorManager.SENSOR_DELAY_GAME);  
  81.         if (!success) {  
  82.             throw new UnsupportedOperationException();  
  83.         }  
      //          mListenters.add(XXXOnShakeListener); 如果有多個listenter則使用
  84.     }  
  85.     /** 
  86.      * 停止搖晃檢測 
  87.      */  
  88.     public void stop() {  
  89.         if (mSensorManager != null)  
  90.             mSensorManager.unregisterListener(this);  
  91.     }  
  92.     @Override  
  93.     public void onAccuracyChanged(Sensor sensor, int accuracy) {  
  94.         // TODO Auto-generated method stub   
  95.     }  
  96.     @Override  
  97.     public void onSensorChanged(SensorEvent event) {  
  98.         long currentTime = System.currentTimeMillis();  
  99.         long diffTime = currentTime - mLastUpdateTime;  
  100.         if (diffTime < UPDATE_INTERVAL)  
  101.             return;  
  102.         mLastUpdateTime = currentTime;  
  103.         float x = event.values[0];  
  104.         float y = event.values[1];  
  105.         float z = event.values[2];  
  106.         float deltaX = x - mLastX;  
  107.         float deltaY = y - mLastY;  
  108.         float deltaZ = z - mLastZ;  
  109.         mLastX = x;  
  110.         mLastY = y;  
  111.         mLastZ = z;  
  112.         float delta = FloatMath.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ  
  113.                 * deltaZ)  
  114.                 / diffTime * 10000;  
  115.         if (delta > shakeThreshold) { // 當加速度的差值大於指定的閾值,認爲這是一個搖晃   
  116.             this.notifyListeners();  //如果前面沒有加入OnShakeListener則需使直接調用自定義的方法或語句 eg: XXXXActivity.this.onShake();
  117.         }  
  118.     }  
  119.     /** 
  120.      * 當搖晃事件發生時,通知所有的listener 
  121.      */  
  122.     private void notifyListeners() {  
  123.         for (OnShakeListener listener : mListeners) {  
  124.             listener.onShake();  
  125.         }  
  126.     }  
  127. }  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章