PhoneGap Sample - Shake to Roll

This post is more than 2 years old.

Sorry for being so quiet lately. I've got three presentations this week and two brand new ones in two weeks. Mentally - it has been killing me. As with all things - it will pass. (And I think I'm building some good new presentations as well!) In the meantime, I thought I'd share a simple PhoneGap application I built for my four-hour lab in Ohio a few days back.

The idea behind the application was to demonstrate the Accelerometer API. This returns movement information along three different axes.

By itself, the API is easy enough to use. What I was having difficulty with was coming up with a practical example of it. I thought I'd create a simple application that mimicked rolling a die. I'd start off by selecting a random number between one and six. I'd display this on the screen like so.

(What you're seeing here is the Ripple emulator. I plan on talking about this in a few days.)

The code for picking and displaying a random number was trivial.

What was more difficult was figuring out how to respond to a shake. I mean, seriously, what is a shake, in code terms?

I did some Googling and discovered that most people simply tracked the X/Y/Z values and then compared them to historical values. I came up with this solution (which is based on what I saw so this isn't some brilliant discovery of mine).

I then used the Ripple emulator to test, and slowly tweaked the numbers until it "felt" right to me. You can see the result below.

For the full source code (there really isn't much to it), you can see the code in the GitHub repo for the presentation: DevelopingMobileAppsWithPhoneGap/tree/master/labs/6_accelerometer

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA

Archived Comments

Comment 1 by Rodney posted on 6/2/2013 at 10:51 AM

Thanks - I do find that if I use a frequency of 200 then the shake event fires multiple times - e.g. 3 times on Ripple Emulator and on my Android S4. I set it to 500 and it seems to only fire once. Is it possible to adapt the code to only fire once and then not fire again if it is within a small period of time (after a few seconds it should keep listening)

Comment 2 by Raymond Camden posted on 6/2/2013 at 5:24 PM

It is kind of cheesy, but use a global var: paused

When you begin the shake do:

window.setTimeout(clearPause, 2000);

clearPause will set paused to false. And before you do your shake. check if paused is true.

Comment 3 by Rodney posted on 7/6/2013 at 11:25 AM

Thanks, that worked. It is very sensitive!

Comment 4 by Ross Rawlins posted on 1/18/2015 at 3:56 PM

have you got a version of this with angular and ngcordova working?

Comment 5 (In reply to #4) by Raymond Camden posted on 1/18/2015 at 4:16 PM

No, but honestly, it's one event handler and a func to determine if it was a shake. Fairly trivial, right?

Comment 6 (In reply to #5) by Ross Rawlins posted on 1/18/2015 at 4:20 PM

I havent been able to understand how ngCordova plugin works so I know if seems easy for you but I havent grasped this on yet.

Comment 7 (In reply to #6) by Raymond Camden posted on 1/18/2015 at 4:22 PM

How ngCordova works in general? It's mainly a Angular-friendly promisey- version of Cordova stuff. If you don't understand ngCordova in general, I'd suggest their docs of course.

Comment 8 (In reply to #7) by Ross Rawlins posted on 1/18/2015 at 4:24 PM

I know how to implement all their plugins. Its just the device motion I cant seem to get anything to fire with it.

Comment 9 (In reply to #8) by Raymond Camden posted on 1/18/2015 at 4:30 PM

Well when you tried, what error did you get?

Comment 10 (In reply to #9) by Ross Rawlins posted on 1/18/2015 at 4:33 PM

thats the thing in ripple it tells me it detect device motion of undefined because ngCordova plugins dont work in ripple. and when I run it on a device I cant see anything that is going on no alerts are firing at all.

Comment 11 (In reply to #10) by Raymond Camden posted on 1/18/2015 at 4:35 PM

Ok, well first off, I'd remove Ripple from the picture as it is quite old. If you don't know how to debug, you need to learn about remote debugging. Chrome and Safari make this easy and powerful. If you go to the About Me page on this blog, look at my list of articles, and I've got two covering these features. It will help quite a bit.

Comment 12 (In reply to #11) by Ross Rawlins posted on 1/18/2015 at 4:38 PM

thanks I will try; I have used the adobe debugger but that doesnt work becuase of angular.

Comment 13 (In reply to #12) by Raymond Camden posted on 1/18/2015 at 4:38 PM

What Adobe debugger?

Comment 14 (In reply to #13) by Ross Rawlins posted on 1/18/2015 at 4:42 PM

with phonegap you can build your app through adobe build and there you can select to allow debugging then when you deploy the app and you can debug it on your computer while it is on the device. But this isnt working with angular yet. its called weinre I think.

I also looked at your about me page and I know of edge, and I dont have a make. I will have to look at the code again and try see how I can get a response of some sorts.

thats the example code that I cant get to fire off any time let alone after a shake.

Comment 15 (In reply to #14) by Raymond Camden posted on 1/18/2015 at 4:43 PM

Oh wow, you mean Adobe PhoneGap Builder. Ok. "Adobe Debugger" didn't mean anything to me. So yes, it uses Weinre, and that was made *before* remote debugging was an option. You only use it if you are using a device not supported by remote debugging. Trust me - check out my articles. :)

Comment 16 by Aaron Mason posted on 11/3/2015 at 11:27 PM

I see a potential issue with your code:

if(deltaX + deltaY + deltaZ > 3) {

That probably won't add deltaX, deltaY and deltaZ and then see if the value is greater than 3 - it most likely adds deltaX, deltaY and "deltaZ > 3", which may be 1 or 0 depending on whether or not deltaZ is greater than three.

The code below will produce the desired result:

if((deltaX + deltaY + deltaZ) > 3) {

As a programming lecturer once told me, parentheses are free, never rely on order of operations.

Comment 17 (In reply to #16) by Raymond Camden posted on 11/4/2015 at 3:04 AM

From what I see here, https://developer.mozilla.o..., it looks like addition takes priority. Did you test? You are right though that parenthesis wouldn't hurt.

Comment 18 (In reply to #17) by Aaron Mason posted on 11/4/2015 at 10:08 PM

I stand corrected. Even in C it seems addition takes priority. Thanks, I learned something new today.