Android ShakeDetector 摇晃持续检测

晃动检测网上有很多资料了,不过我没找到持续检测的。献丑了呵呵呵。
下文中通过加速度检测和是距离检测结合来判定晃动。加入距离检测是为了避免在只有加速度检测时可能出现一次摇晃中多次满足条件的情况。
下文中摇晃检测参数都是适应我实际要求的,当然具体需要怎样的灵敏度可以自己设置参数来调试啦。
上代码:

/**
*
* ShakeDetector
*
* @author : BlueEyes
* @date : 2013-5-4
*
*/

package com.lzr.shakealarm.detector;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.FloatMath;
import android.util.Log;

public class ShakeDetector implements SensorEventListener {

final String TAG = this.getClass().getName();// Log Tag

private SensorManager sensorManager;

private boolean loop = false;
private boolean unCheck = true;// Uncheck
private int shakeTimes = 1;// Times
private int updateInterval = 100;// Interval
private int accuracyThreshold = 1000;// Accuracy threshold
private float totalThreshold = 40.0f;// Displacement threshold
ShakeDetector_Interface shakeDetector_Interface;// call back

private float lastX, lastY, lastZ;
private float totalX, totalY, totalZ;
private long lastUpdateTime;
private int count = 0;// shake count

/**
* ShakeDetector constructor
*/
public ShakeDetector() {

reset(1, null);
};

/**
* ShakeDetector constructor
*
* @param shakeTimes
* Maximum of shake count
* @param shakeDetector_Interface
* Call back
*/
public ShakeDetector(Integer shakeTimes,
ShakeDetector_Interface shakeDetector_Interface) {

reset(shakeTimes, shakeDetector_Interface);
}

/**
* Reset
*
* @param shakeTimes
* Maximum of shake count
* @param shakeDetector_Interface
* call back
*/
public void reset(Integer shakeTimes,
ShakeDetector_Interface shakeDetector_Interface) {

if (!unCheck) {

Log.e(TAG, "Detector is runing can't be reset");
return;
}

if (shakeTimes != null && shakeTimes > 0) {

this.shakeTimes = shakeTimes;
this.loop = false;
} else{

this.loop = true;
this.shakeTimes=-1;
}

if (shakeDetector_Interface != null)
this.shakeDetector_Interface = shakeDetector_Interface;

lastX = 0;
lastY = 0;
lastZ = 0;
lastUpdateTime = 0;
count = 0;

unCheck = false;
}

/**
* Register callback
*
* @param shakeInterface
* Call back
*/
public void setCallBackListener(ShakeDetector_Interface shakeInterface) {
shakeDetector_Interface = shakeInterface;
}

/**
*
* Regiset detector
*
* @param context
*/
public void registerDetector(Context context) {

Sensor sensor = null;
if (sensorManager == null) {

// Create Manager
sensorManager = (SensorManager) context
.getSystemService(Context.SENSOR_SERVICE);

sensor = sensorManager
.getDefaultSensor(Context.CONTEXT_INCLUDE_CODE);
}

// regist Sensor Listener
sensorManager.registerListener(this, sensor,
SensorManager.SENSOR_DELAY_GAME);
}

/**
* unregister Detector
*/
public void unregisterDetector() {

if (sensorManager != null) {

sensorManager.unregisterListener(this);
}
}

/**
* Set parameters
*
* @param updateInterval
* @param accuracyThreshold
* @param totalThreshold
*/
public void setDetectorParameters(Integer updateInterval,
Integer accuracyThreshold, Float totalThreshold) {

if (!unCheck)
Log.w(TAG, "Change parameter when detector is running");

if (updateInterval != null && updateInterval > 0)
this.updateInterval = updateInterval;

if (accuracyThreshold != null && accuracyThreshold > 0)
this.accuracyThreshold = accuracyThreshold;

if (totalThreshold != null && totalThreshold > 0)
this.totalThreshold = totalThreshold;
}

@Override
public void onSensorChanged(SensorEvent event) {

//
if (unCheck)
return;

// initialize
if (0 == lastUpdateTime) {

// set initial
lastUpdateTime = System.currentTimeMillis();
lastX = event.values[0];
lastY = event.values[1];
lastZ = event.values[2];
}

// Get currentTime
long currentTime = System.currentTimeMillis();

// Calculate interval from last updatetime
long diffTime = currentTime - lastUpdateTime;

// Check Interval
if (diffTime < updateInterval)
return;

// set last update time
lastUpdateTime = currentTime;

// get sensor value
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];

float displacementX = Math.abs(x - lastX);
float displacementY = Math.abs(y - lastY);
float displacementZ = Math.abs(z - lastZ);

lastX = x;
lastY = y;
lastZ = z;

// Accelerate
float accuracy = FloatMath
.sqrt(displacementX * displacementX + displacementY
* displacementY + displacementZ * displacementZ)
/ diffTime * 10000;

// Check Acceleration
if (accuracy > accuracyThreshold) {

this.totalX = (displacementZ + this.totalX);
this.totalY = (displacementZ + this.totalY);
this.totalZ = (displacementZ + this.totalZ);

if ((this.totalX > totalThreshold)
|| (this.totalY > totalThreshold)
|| (this.totalZ > totalThreshold)) {

// Times
if (!loop)
count++;

// doShake
if (shakeDetector_Interface != null) {

shakeDetector_Interface.doShake(count, shakeTimes);
}

// Check Times
if (!loop && count >= shakeTimes) {

// doFinish
if (shakeDetector_Interface != null)
shakeDetector_Interface
.doFinishCount(count, shakeTimes);

unCheck = true;
}

this.totalX = 0.0F;
this.totalY = 0.0F;
this.totalZ = 0.0F;
}
}
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
Log.i(TAG, "Sensor Type:" + sensor.getType() + ";Accuracy:" + accuracy);
}

/**
* Interface for call Back
*
* @author : BlueEyes
* @date : 2013-5-4
*
*/
public interface ShakeDetector_Interface {

/**
* Call it when shaken
*
* @param count
* Shake count
* @param maximum
* Maximum of shake count
*/
public void doShake(int count, int maximum);

/**
* Call it when detect finished
*
* @param count
* Shake count
* @param maximum
* Maximum of shake count
*/
public void doFinishCount(int count, int maximum);
}
}


使用:
setDetectorParameters 设定自己需要的参数。
registerDetector 开始
unregisterDetector 注销检测(在不使用时记得调用此方法,避免不必要的资源浪费)
接口:
doShake 每次检测到晃动都会回调。
doFinishCount 晃动次数达到设定的检测次数时被调用。(shakeTimes设置为null或者0时判定检测器一直检测晃动,直到检测器被注销,期间doFinishCount不会被调用)

PS:shakeTimes设置为NULL或者0时没有经过测试。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值