ahmad mohseni ahmad mohseni - 4 months ago 19
Android Question

Logics issue while using accelerometer

I am trying to make an app like "Heads up" just for more exercising!!

but now I faced some logical problem in using accelerometer in my app.

I want the app toast "correct" when it tilt's down (accelerometer gives -7 in this position) and toast "wrong" when tilt's up (accelerometer gives 7 or more in this position).

But the problem was that app toast many times repeatedly in each position. so I used a boolean (isToasted) to make the app toast once in each of those position. But now it doesn't toast at all!

where is my problem and what should i do?

this is a part of my codes:

Boolean isToasted = false;

@Override
public void onSensorChanged(SensorEvent event) {
int sensorValue = (int) event.values[2];

while (isToasted) {
switch (sensorValue) {
case 7: {
Toast.makeText(find_word2.this, "wrong", Toast.LENGTH_SHORT).show();
isToasted = true;
break;
}
case -7: {
Toast.makeText(find_word2.this, "correct", Toast.LENGTH_SHORT).show();
isToasted = true;
break;
}
}
}
if (sensorValue == 0) isToasted = false; //sensorValue = 0 means device is not tilted and it's in direct position.
}

Answer

The reason it would display the Toast multiple times in each position is because a SensorEvent can occur multiple times at a single position:

Note that "on changed" is somewhat of a misnomer, as this will also be called if we have a new reading from a sensor with the exact same sensor values (but a newer timestamp).

Therefore, every time there is a SensorEvent that has one of the z-values you specified in your switch statement a Toast will be displayed. You were on the right track by adding a boolean value to track if the message had already displayed, but the while loop you have will never execute because isToasted is set to false.

Actually, you don't even need a loop. All you have to do is check if the z-value is between a range of two values. If so, you set the boolean to true. If not, you check if the boolean is true and the z-value is is above or below the range. Then you can set the Toast accordingly, and set the boolean to false so that the message will not display a second time.

private boolean isReset = true;
private float mMaxValue = 7;

@Override
public void onSensorChanged(SensorEvent event) {
    float value = event.values[2];

    if(value >= mMaxValue || value <= -mMaxValue) {
        if(isReset && value <= -mMaxValue) {
            Toast.makeText(find_word2.this, "correct", Toast.LENGTH_SHORT).show();
            isReset = false;
        } else if(isReset && value >= mMaxValue) {
            Toast.makeText(find_word2.this, "wrong", Toast.LENGTH_SHORT).show();
            isReset = false;
        }
    } else {
        isReset = true;
    }
}

You could also create a "dead zone" by making the range in the outer if statement lower than the maximum value. This would ensure that the user would have to reset the device closer to zero before the Toast could be displayed again.