Android - Acceleration down (smash)


Video explaining for those who does not understand


THIS ANSWER IS NOT CORRECTLY ANSWERED PLEASE TRY TO ANSWER IT WITH ANOTHER SOLUTION (100 Bounty is out of date)

Same question but better explained

This questions was accepted as a correct but it is not at all, I tried it with my old device ZTE and it worked most of time, but now I have a Samsung Galazy A5 2016 and it doesn't work, neither on a LG G3.

The thing is trying using Accelerometer and some Sensors I have to be able to detect any of those two moviments that I made on the Video.

There are two moviments :

  • Smashing it (with a little bit of velocity)
  • Free fall

I let you to decide and convince me what's the better option and EASIER one to do, with better I mean that works on most of devices.


A stationary device will have an gravity value of +9.81, which corresponds to the acceleration of the device (0 m/s2 minus the force of gravity, which is -9.81 m/s2). Thus if the device is moving downward from stationary then the gravity will be less than 9.81. A free fall device will have gravity equals 0.

Below is how to determine if the device starts moving downward. It will not be able to determine whether the device is moving downward if the device is already moving downward with constant speed, since in this case there is no acceleration downward and the gravity norm should be around 9.81.

You need to use TYPE_GRAVITY. If the device does not have TYPE_GRAVITY, then low pass filter TYPE_ACCELEROMETER to get the gravity vector.

As above a stationary device will have a gravity vector with norm equal 9.81. However, this value will vary slightly with devices. Thus you need first to determine this stationary gravity norm. You can do this by register for TYPE_GRAVITY or TYPE_ACCELEROMETER and ask the user to lay the device flat and then press a button. Once the button is pressed the app will calculate the norm of the gravity in onSensorChanged.

private float mStationaryGravityNorm;
private float mDeviation = 0.01;
private float mCount;
private boolean mIsCalculatingStationGravityNorm = true;

Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener( {
    @Override
    public void onClick(View v) {
        // register sensor
    }
    });

@Override
public void onSensorChanged(SensorEvent event) {
// Will average out 100 gravity values.
if (mIsCalculatingStationGravityNorm) {
    if (mCount++ < 100) {
        mStationaryGravityNorm += Math.sqrt(event.values[0] * event.values[0] + event.values[1] * event.values[1] + event.values[2] * event.values[2]);
    } else {
        mStationaryGravityNorm /= 100;
        mIsCalculatingStationGravityNorm = false;
} else {
    float gravityNorm = Math.sqrt(event.values[0] * event.values[0] + event.values[1] * event.values[1] + event.values[2] * event.values[2]);
    if (gravityNorm < mStationaryGravityNorm - mDeviation) {
    // moving down
    }
}

PS For moving up an down you do want to calculate gravity. When the device is stationary, the gravity norm is approximately 9.81 (depending on device). Now if the device is moving down, there is an acceleration downward, thus the gravity norm will be less than 9.81 and if the device is moving up the gravity norm will be more than 9.81. So by comparing the gravity norm against this stationary gravity norm, you will know if the device moving up or down. This is independent of the device orientation. TYPE_GRAVITY will give better accuracy but if the device does not have this type then low pass filter TYPE_ACCELERATOR will give you the gravity vector.