{"id":388,"date":"2013-01-30T15:39:11","date_gmt":"2013-01-30T23:39:11","guid":{"rendered":"http:\/\/jasonmcreynolds.com\/?p=388"},"modified":"2015-10-16T11:50:39","modified_gmt":"2015-10-16T19:50:39","slug":"android-tutorial-implement-a-shake-listener","status":"publish","type":"post","link":"https:\/\/jasonmcreynolds.com\/?p=388","title":{"rendered":"Android Tutorial: Implement A Shake Listener"},"content":{"rendered":"<p>So I&#8217;ve been playing around with Android and have a little app that I wanted the user to be able to shake the phone and have something happen. I did some digging and the following is a tutorial on how to setup a shake listener to capture a shake and then do whatever you want.<\/p>\n<p>This is by no means something that I&#8217;ve created, I just used examples that I found on <a title=\"stackoverflow.com\" href=\"http:\/\/stackoverflow.com\">stackoverflow.com<\/a>. Also, this uses G-force to calculate the shake threshold. Many thanks to <a title=\"Peterdk\" href=\"http:\/\/stackoverflow.com\/users\/107029\/peterdk\">Peterdk<\/a> and <a title=\"Akos Cz\" href=\"http:\/\/stackoverflow.com\/users\/461237\/akos-cz\">Akos Cz<\/a> for their input and answer for this solution. Peterdk recommended using the <a title=\"G-Force by Blake La Pierre on Google Play Store\" href=\"https:\/\/play.google.com\/store\/apps\/details?id=com.example.gForce\">G-Force<\/a>\u00a0app\u00a0by Blake La Pierre on Google Play Store if you want\u00a0to get the actual G-force value on your phone and tweak it in the code below.<\/p>\n<p>Long story short, there are 5 things that need to happen to get this to work:<\/p>\n<ol>\n<li>Create a new class named ShakeDetector<\/li>\n<li>Define variables for sensor manager, shake detector and accelerometer<\/li>\n<li>Add\/register the sensor manager and listener in the onCreate() method in your activity<\/li>\n<li>Configure onResume and onPause to activate\/deactivate the accelerometer<\/li>\n<li>Edit the AndroidManifest.xml file to require the device to have an accelerometer<\/li>\n<\/ol>\n<p><!--more-->Here&#8217;s how to do it all:<\/p>\n<h1>Step 1<\/h1>\n<p>Create a new class named ShakeDetector and put the following code in it:<\/p>\n<pre class=\"toolbar:1 lang:java decode:true \" title=\"ShakeDetector.java Class\">import android.hardware.Sensor;\r\nimport android.hardware.SensorEvent;\r\nimport android.hardware.SensorEventListener;\r\nimport android.hardware.SensorManager;\r\nimport android.util.FloatMath;\r\n\r\npublic class ShakeDetector implements SensorEventListener {\r\n\r\n\t\/*\r\n\t * The gForce that is necessary to register as shake.\r\n\t * Must be greater than 1G (one earth gravity unit).\r\n\t * You can install \"G-Force\", by Blake La Pierre\r\n\t * from the Google Play Store and run it to see how\r\n\t *  many G's it takes to register a shake\r\n\t *\/\r\n\tprivate static final float SHAKE_THRESHOLD_GRAVITY = 2.7F;\r\n\tprivate static final int SHAKE_SLOP_TIME_MS = 500;\r\n\tprivate static final int SHAKE_COUNT_RESET_TIME_MS = 3000;\r\n\r\n\tprivate OnShakeListener mListener;\r\n\tprivate long mShakeTimestamp;\r\n\tprivate int mShakeCount;\r\n\r\n\tpublic void setOnShakeListener(OnShakeListener listener) {\r\n\t\tthis.mListener = listener;\r\n\t}\r\n\r\n\tpublic interface OnShakeListener {\r\n\t\tpublic void onShake(int count);\r\n\t}\r\n\r\n\t@Override\r\n\tpublic void onAccuracyChanged(Sensor sensor, int accuracy) {\r\n\t\t\/\/ ignore\r\n\t}\r\n\r\n\t@Override\r\n\tpublic void onSensorChanged(SensorEvent event) {\r\n\r\n\t\tif (mListener != null) {\r\n\t\t\tfloat x = event.values[0];\r\n\t\t\tfloat y = event.values[1];\r\n\t\t\tfloat z = event.values[2];\r\n\r\n\t\t\tfloat gX = x \/ SensorManager.GRAVITY_EARTH;\r\n\t\t\tfloat gY = y \/ SensorManager.GRAVITY_EARTH;\r\n\t\t\tfloat gZ = z \/ SensorManager.GRAVITY_EARTH;\r\n\r\n\t\t\t\/\/ gForce will be close to 1 when there is no movement.\r\n\t\t\tfloat gForce = FloatMath.sqrt(gX * gX + gY * gY + gZ * gZ);\r\n\r\n\t\t\tif (gForce &gt; SHAKE_THRESHOLD_GRAVITY) {\r\n\t\t\t\tfinal long now = System.currentTimeMillis();\r\n\t\t\t\t\/\/ ignore shake events too close to each other (500ms)\r\n\t\t\t\tif (mShakeTimestamp + SHAKE_SLOP_TIME_MS &gt; now) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t\/\/ reset the shake count after 3 seconds of no shakes\r\n\t\t\t\tif (mShakeTimestamp + SHAKE_COUNT_RESET_TIME_MS &lt; now) {\r\n\t\t\t\t\tmShakeCount = 0;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tmShakeTimestamp = now;\r\n\t\t\t\tmShakeCount++;\r\n\r\n\t\t\t\tmListener.onShake(mShakeCount);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}<\/pre>\n<p>I get a warning in Eclipse about the sqrt on line 50 of the code above saying &#8220;Use java.lang.Math#sqrt instead of android.util.FloatMath#sqrt() since it is faster as of API 8&#8221;, but I choose to ignore it.<\/p>\n<h1>Step 2<\/h1>\n<p>At the beginning of your activity, declare the following variables:<\/p>\n<pre class=\"toolbar:1 lang:java decode:true\" title=\"Variables\">\t\/\/ The following are used for the shake detection\r\n\tprivate SensorManager mSensorManager;\r\n\tprivate Sensor mAccelerometer;\r\n\tprivate ShakeDetector mShakeDetector;<\/pre>\n<h1>Step 3<\/h1>\n<p>Now, in your activity, paste the following in the onCreate() method:<\/p>\n<pre class=\"toolbar:1 lang:java decode:true\" title=\"onCreate() Method Modification\">\t\t\/\/ ShakeDetector initialization\r\n\t\tmSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);\r\n\t\tmAccelerometer = mSensorManager\r\n\t\t\t\t.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);\r\n\t\tmShakeDetector = new ShakeDetector();\r\n\t\tmShakeDetector.setOnShakeListener(new OnShakeListener() {\r\n\r\n\t\t\t@Override\r\n\t\t\tpublic void onShake(int count) {\r\n\t\t\t\t\/*\r\n\t\t\t\t * The following method, \"handleShakeEvent(count):\" is a stub \/\/\r\n\t\t\t\t * method you would use to setup whatever you want done once the\r\n\t\t\t\t * device has been shook.\r\n\t\t\t\t *\/\r\n\t\t\t\thandleShakeEvent(count);\r\n\t\t\t}\r\n\t\t});<\/pre>\n<p>Take care of any missing import statements (ctrl+shift+o in Eclipse). Create your own handleShakeEvent method to do what you want when a shake is detected. Or, remove the stub reference to handleShakeEvent(count); in the code above and create your own method or add what you want in its place.<\/p>\n<h1>Step 4<\/h1>\n<p>Modify (or add) onResume and onPause to include the following line:<\/p>\n<pre class=\"toolbar:1 lang:java decode:true\" title=\"onPause and onResume Method Modifications\">\t@Override\r\n\tpublic void onResume() {\r\n\t\tsuper.onResume();\r\n\t\t\/\/ Add the following line to register the Session Manager Listener onResume\r\n\t\tmSensorManager.registerListener(mShakeDetector, mAccelerometer,\tSensorManager.SENSOR_DELAY_UI);\r\n\t}\r\n\r\n\t@Override\r\n\tpublic void onPause() {\r\n\t\t\/\/ Add the following line to unregister the Sensor Manager onPause\r\n\t\tmSensorManager.unregisterListener(mShakeDetector);\r\n\t\tsuper.onPause();\r\n\t}<\/pre>\n<p><span style=\"font-size: 20px; font-weight: bold; line-height: 1.4em;\">Step 5<\/span><\/p>\n<p>I also added the following in my AndroidManifest.xml to make sure the phone has an accelerometer (it goes right after the &lt;uses-sdk \/&gt; section):<\/p>\n<pre class=\"toolbar:1 lang:java decode:true\" title=\"AndroidManifest.xml - Require Accelerometer\">&lt;uses-feature android:name=\"android.hardware.sensor.accelerometer\" android:required=\"true\" \/&gt;<\/pre>\n<p>There you have it. I hope this helps!<\/p>\n<p>Sources:<\/p>\n<ul>\n<li><a title=\"Implementing a shake event\" href=\"http:\/\/stackoverflow.com\/questions\/9934324\/implementing-a-shake-event\">Implementing a shake event<\/a><\/li>\n<li><a title=\"Android: I want to shake it\" href=\"http:\/\/stackoverflow.com\/questions\/2317428\/android-i-want-to-shake-it\"><span style=\"line-height: 1.625;\">Android: I want to shake it\u00a0<\/span><\/a><\/li>\n<li><a title=\"Use feature accelerometer\" href=\"http:\/\/stackoverflow.com\/questions\/3787269\/uses-feature-accelerometer-in-the-manifest\">Uses-feature accelerometer in the manifest<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>So I&#8217;ve been playing around with Android and have a little app that I wanted the user to be able to shake the phone and have something happen. I did some digging and the following is a tutorial on how to setup a shake listener to capture a shake and then do whatever you want. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":418,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_s2mail":"yes","ngg_post_thumbnail":0,"footnotes":""},"categories":[37,65,51,64],"tags":[86,99,98],"class_list":["post-388","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-android","category-code","category-featured","category-tutorial","tag-android","tag-code","tag-tutorial"],"_links":{"self":[{"href":"https:\/\/jasonmcreynolds.com\/index.php?rest_route=\/wp\/v2\/posts\/388","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jasonmcreynolds.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jasonmcreynolds.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jasonmcreynolds.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jasonmcreynolds.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=388"}],"version-history":[{"count":37,"href":"https:\/\/jasonmcreynolds.com\/index.php?rest_route=\/wp\/v2\/posts\/388\/revisions"}],"predecessor-version":[{"id":642,"href":"https:\/\/jasonmcreynolds.com\/index.php?rest_route=\/wp\/v2\/posts\/388\/revisions\/642"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/jasonmcreynolds.com\/index.php?rest_route=\/wp\/v2\/media\/418"}],"wp:attachment":[{"href":"https:\/\/jasonmcreynolds.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=388"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jasonmcreynolds.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=388"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jasonmcreynolds.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=388"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}