title: Android: Using the accelerometer to detect a flick
body: <p>I'm trying to develop an app where the user can hit an invisible drum using the motion of the phone. So that when the phone is flicked downwards a drum is sounded at the end of the flick.</p>
  
  <p>I have managed to get 90% of this working, by detecting when a large, quick movement suddenly stops. But although the drum is being sounded after a flick (good) it's also being sounded at the end of a pull (not desirable). </p>
  
  <p>By flick I mean the phone is being flicked forwards and downwards, as if you are striking a drum with it, and by pull I mean you are returning your arm back to the starting position.</p>
  
  <p>Does anyone know an efficient way of determining when a flick occurs but not a push?</p>
  
  <p>Any ideas will be gratefully received.</p>
  
  <p>Thanks</p>
  
  <p>EXISTING CODE:</p>
  
  <pre><code>package com.example.testaccelerometer;
  
  import android.hardware.Sensor;
  import android.hardware.SensorEvent;
  import android.hardware.SensorEventListener;
  import android.hardware.SensorListener;
  import android.hardware.SensorManager;
  import android.os.Bundle;
  import android.app.Activity;
  import android.content.Context;
  import android.view.Menu;
  import android.widget.TextView;
  
  public class MainActivity extends Activity implements SensorEventListener{
  
      public static TextView results;
  
      public static TextView clickresults;
  
      StringBuilder builder = new StringBuilder();
  
        private float mAccelNoGrav;
        private float mAccelWithGrav;
        private float mLastAccelWithGrav;
  
      public static boolean shakeIsHappening;
      public static int beatnumber = 0;
  
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
  
          results = (TextView) findViewById(R.id.results);
          clickresults = (TextView) findViewById(R.id.clickresults);
  
          SensorManager manager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
          Sensor accelerometer = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
  
          if(!manager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_FASTEST)){
              builder.append("Problem with Accelerometer - Shaking will not work");
          };
  
  
          mAccelNoGrav = 0.00f;
          mAccelWithGrav = SensorManager.GRAVITY_EARTH;
          mLastAccelWithGrav = SensorManager.GRAVITY_EARTH;
  
  
  
      }
  
      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
          // Inflate the menu; this adds items to the action bar if it is present.
          getMenuInflater().inflate(R.menu.main, menu);
          return true;
      }
  
      @Override
      public void onAccuracyChanged(Sensor sensor, int accuracy) {
          // TODO Auto-generated method stub
  
      }
  
      @Override
      public void onSensorChanged(SensorEvent event) {
          builder.setLength(0);
          builder.append("X " + event.values[0] + "\nY " + event.values[1] + "\nZ " + event.values[2]);
      results.setText(builder.toString());
  
  
          float x = event.values[0];
            float y = event.values[1];
            float z = event.values[2];
            mLastAccelWithGrav = mAccelWithGrav;
            mAccelWithGrav = android.util.FloatMath.sqrt(x*x + y*y + z*z);
            float delta = mAccelWithGrav - mLastAccelWithGrav;
            mAccelNoGrav = mAccelNoGrav * 0.9f + delta;
  
      if (mAccelNoGrav &gt;8.5) {
          shakeIsHappening = true;
          //clickresults.append(" click " + mAccel);
      }
  
      if (shakeIsHappening == true &amp;&amp; mAccelNoGrav &lt;2) {
          beatnumber++;
  clickresults.append(" click number: " + beatnumber + "\n" + "PA: " + mLastAccelWithGrav + " CA:" + mAccelNoGrav + "\n ");
  shakeIsHappening = false;
      }
  
      }
  
  
      @Override
      protected void onResume() {
        super.onResume();
      // YOU DO NEED TO TRY AND REREGISTER IT NOW
      }
  
      @Override
      protected void onPause() {
          // YOU DO NEED TO TRY AND UNREGISTER IT NOW
        super.onPause();
      }
  
  
  }
  </code></pre>