我正在尝试开发一个检测到跌倒的应用程序,到目前为止,跌倒的准确性在可接受的范围内,但是问题是“OnSensorChanged”的调用方式过于频繁,导致吐司不断出现在我的屏幕上。
我认为问题在于,在自由落体期间,“OnSensorChanged”在落体持续时间内不断被调用(因为值对应于落体),这是导致我的屏幕上出现烤面包垃圾邮件的原因。
我尝试的解决方案是在跌倒后注销监听器,以便它仅出现一次,但是问题是除非我重新启动应用程序,否则它将不会再次检测到跌落(因为显然监听器已停止工作)。
这个问题有解决方案吗?
谢谢
private void checkFall(SensorEvent xyzValues) {
float[] values = xyzValues.values;
double rootSquare = Math.sqrt(Math.pow(values[0],2)+Math.pow(values[1],2)+Math.pow(values[2],2));
if (rootSquare < 1.5){
Toast toast = Toast.makeText(this, "The Phone Fell!", Toast.LENGTH_LONG);
toast.show();
sensorManager.unregisterListener(this);
sensorManager = null;
}
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
checkFall(event);
}
}
最佳答案
您可以使用成员布尔变量mFallen
来跟踪何时发生跌倒。您可能还需要定义一些阈值,以指示电话何时返回正常的“站立”状态。请尝试以下操作:
if (rootSquare < 1.5 && !mFallen){
Toast toast = Toast.makeText(this, "The Phone Fell!", Toast.LENGTH_LONG);
toast.show();
mFallen = true;
} else if (rootSquare > STANDING_THRESHOLD) {
mFallen = false;
}
更好的站立检测算法
一旦mFallen的状态从false变为true,设备的加速度矢量的大小(如您所计算并存储在
rootSquare
中)应非常接近0。这是因为当设备处于自由落体状态(下降)时全部靠它本身),其加速度将是来自站立者参考系的重力加速度。但是从理论上讲,加速度计仅用于测量相对于自由落体的值,因此它将恰好为0。由于重力加速度约为9.81 m / s ^ 2,因此要检测设备何时不再移动,您需要检查加速度的大小何时接近。这是因为在静止时,传感器将检测阻止其坠落的力(由于重力而取消加速度),这些力是保持静止的力。在这种情况下,由这些力引起的加速度的总大小必须精确地归因于由重力引起的加速度的大小。
您可以将常量
GRAVITY
定义为9.81
,并将GRAVITY_THRESHOLD
定义为容差值,您可以尝试将其设置为0.1
,然后稍后进行优化。尝试用以下代码替换您的代码:if (rootSquare < 1.5 && !mFallen){
Toast toast = Toast.makeText(this, "The Phone Fell!", Toast.LENGTH_LONG);
toast.show();
mFallen = true;
} else if (Math.abs(rootSquare - GRAVITY) < GRAVITY_THRESHOLD) {
mFallen = false;
}
为了强调,仅当设备停止移动时,此处的站立状态才定义为,因此它将无法检测到手机相对于地面的高度。
请参阅https://developer.android.com/reference/android/hardware/SensorEvent.html#values,因为它可以帮助您更好地理解问题。