• [Android实例] Android ShakeDetector(摇晃检测)教程详解


    最近要实现一个手机摇晃 的功能。

    想到这个功能可能应用广泛,比如摇晃手机换图片、截图、洗牌、结束当前程序等,所以找了些资料,并加以改进,将此功能封装成类(ShakeDetector),方便今后使用。
    摇晃检测基于加速传感器(Sensor.TYPE_ACCELEROMETER)。

    由于重力的存在,当手机静止放于桌面时,加速传感器也是有加速度的。所以,仅通过是否有加速度来判断摇晃是不行的。
    那么,判断加速度的变化吧。在一个较短的时间间隔求出加速度的差值,跟一个指定的阈值比较,如果差值大于阈值,则认为是摇晃发生了。ClingMarks的方法将x、y、z方向的加速度差值简单的加起来,我认为不是很准确。

    加速度是向量,求差应该是各方向的差值平方后相加,再开方。(数学忘光了,应该没记错吧。)
    所以就有了这行代码:

    1. float delta = FloatMath.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) / diffTime * 10000;
    复制代码
    功能封装成类 ShakeDetector,实现了SensorEventListener接口,用于向系统注册传感器事件的Listener。

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

    1、new一个ShakeDetector
    2、调用mShakeDetector.registerOnShakeListener()注册一个OnShakeListener
    3、在OnShakeListener的onShake函数中,处理摇晃事件
    4、调用mShakeDetector.start()启动摇晃检测
  • 相关阅读:
    6.金额中带有逗号不能直接parseFloat
    5-不要在ajax中return false不会生效的
    4.xx is not defined at HTMLAnchorElement.onclick 的问题
    3.git更新地址也更改
    2.文件上传后没有权限不够
    第三章
    oracle-sql
    华为杯 数模
    Learning Dynamic Context Graphs for Predicting Social Events
    图神经网络
  • 原文地址:https://www.cnblogs.com/jackrex/p/3001383.html
Copyright © 2020-2023  润新知