Click here to Skip to main content
Click here to Skip to main content

Detect Shaking Motion on Windows Phone 7

By , 2 Aug 2010
 

The other day on the MSDN forums, someone asked about how to detect a shaking motion on Windows Phone 7. I've been playing with the accelerometer lately so I took great joy in answering this along with providing a working implementation. The question was asking about shaking motion in a left-right direction. I made a class that detects left-right and up-down motion (totally ignoring the Z-axis all together for now). Though extending it to consider the Z-axis wouldn't be hard.

The code for detecting the motion has been abstracted in a class called ShakeDetector. The algorithm used has a few variables/constants defined that can be modified to tune the behaviour of the class. The classes constructor accepts an [optional] parameter of how many times the phone should be shaken before the motion is considered acceptable. <codeminimumaccelerationmagnitude> can be raised or lowered to control how hard the device needs to be shaken to be considered acceptable. And MinimumShakeTime takes a time span that defines the maximum length of time over which a shake sequence must occur to be considered acceptable. Once the user moves the phone in a way that meets the requirements for the type of shake we wanted to detect a ShakeDetected event is raised.

I've reduced the direction in which the device is moving to one of 8 directions (North, East, South, West, and the directions in between those). I could have kept the direction as an angle and just ensured that there was atleast a minimum difference between the angles but I thought using the directions on a map would make it easier for someone else to understand.

void</span /> _accelerometer_ReadingChanged(object</span /> sender, AccelerometerReadingEventArgs e)
{
    //</span />Does the current acceleration vector meet the minimum magnitude that we
</span />    //</span />care about?
</span />    if</span /> ((e.X*e.X + e.Y*e.Y) > MinimumAccelerationMagnitudeSquared)
    {
        //</span />I prefer to work in radians. For the sake of those reading this code
</span />        //</span />I will work in degrees. In the following direction will contain the direction
</span />        //</span /> in which the device was accelerating in degrees. 
</span />        double</span /> degrees = 180</span />.0*Math.Atan2(e.Y, e.X)/Math.PI;
        Direction direction = DegreesToDirection(degrees);

        //</span />If the shake detected is in the same direction as the last one then ignore it
</span />        if</span /> ((direction & _shakeRecordList[_shakeRecordIndex].ShakeDirection) 
		!= Direction.None)
            return</span />;
        //</span />This is a shake we care about. save in in our list
</span />        ShakeRecord record = new</span /> ShakeRecord();
        record.EventTime = DateTime.Now;
        record.ShakeDirection = direction;
        _shakeRecordIndex = (_shakeRecordIndex + 1</span />)%_minimumShakes;
        _shakeRecordList[_shakeRecordIndex] = record;

            CheckForShakes();
    }
}
void</span /> CheckForShakes()
{
    int</span /> startIndex = (_shakeRecordIndex - 1</span />);
    if</span /> (startIndex < 0</span />) startIndex = _minimumShakes - 1</span />;
    int</span /> endIndex = _shakeRecordIndex;

    if</span /> ((_shakeRecordList[endIndex].EventTime.Subtract
	(_shakeRecordList[startIndex].EventTime)) <= MinimumShakeTime)
    {
        OnShakeEvent();
    }
}

The example code can be found in my SkyDrive account here. If you want to see the program in action, there is a video on YouTube.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Joel Ivory Johnson
Software Developer
United States United States
Member
I attended Southern Polytechnic State University and earned a Bachelors of Science in Computer Science and later returned to earn a Masters of Science in Software Engineering.
 
For the past few years I've been providing solutions to clients using Microsoft technologies for web and Windows applications.
 
While most of my CodeProject.com articles are centered around Windows Phone it is only one of the areas in which I work and one of my interests. I also have interest in mobile development on Android and iPhone. Professionally I work with several Microsoft technologies including SQL Server technologies, Silverlight/WPF, ASP.Net and others. My recreational development interest are centered around Artificial Inteligence especially in the area of machine vision.
 

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionHow do I prevent it from firing multiple events in single shake guesture?memberPrasadGVL5 Apr '12 - 0:38 
Thanks for the simple yet functional code. Could you please tell how not to fire multiple shake events one after the other (user frantically shaking the phone). I just want to fire the event once, no matter how long user shakes the phone in one go. Appreciate your help!
Prasad

QuestionMinor fix - there should be a call to Dispose() on accelerometer object after calling Stop()memberVlad P.9 Oct '11 - 12:58 
Minor fix - there should be a call to Dispose() on accelerometer object after calling Stop()
BugMissing reinitializationmemberNiko Bertele19 Sep '11 - 6:54 
Hi Joel,
 
First of all I want to thank you for sharing this code. It helped me a lot.
 
But I also stumbled across a small bug in your code regarding the reinitialization of the Array containing the minimumShakes.
 

You call
_shakeRecordList = new ShakeRecord[minShakes];
in the constructor, but you should also call it after stopping the shake. Otherwise you will get some inconsistency when there are a lot shake events in a short time and you try to update some UI after every shake event.
 
At least this is the behaviour i had in my app.
 
I fixed this problem by changing:
 public void Start()
        {
            lock(SyncRoot)
            {
                if(_accelerometer==null)
                {
                    _accelerometer = new Accelerometer();
                    _accelerometer.ReadingChanged += new EventHandler<AccelerometerReadingEventArgs>(_accelerometer_ReadingChanged);
                     _accelerometer.Start();
                }                
            }
        }
 
to:
 
 public void Start()
        {
            lock(SyncRoot)
            {
                if(_accelerometer==null)
                {
                    _accelerometer = new Accelerometer();
                    _accelerometer.ReadingChanged += new EventHandler<AccelerometerReadingEventArgs>(_accelerometer_ReadingChanged);
                     _accelerometer.Start();
                }
                _shakeRecordList = new ShakeRecord[_minimumShakes];
            }
        }
 
Greetings,
 
So now everytime a Shake starts again the is empty again. Smile | :)
 
Niko
GeneralMy vote of 5memberNiko Bertele19 Sep '11 - 6:45 
Thx a lot. This article saved me hours. Smile | :)
GeneralFormatting issue with blog entrymemberdaveauld2 Aug '10 - 9:11 
There are some formatting issues in your blog entry.
 
The Pre block hasn't terminated resulting in it containing some narrative at the end, and also your embedded youtube clip will not display as a result of this, just shows the code required to embedd it.
 
Cheers
Dave
 
Don't forget to rate messages!
Find Me On: Web|Facebook|Twitter|LinkedIn
Waving? dave.m.auld[at]googlewave.com


GeneralRe: Formatting issue with blog entrymemberJoel Ivory Johnson2 Aug '10 - 9:27 
Thanks for the heads up. For some reason when I viewed the original entry the missing tag didn't have an impact. Also looks that CodeProject.com is stripping the object tag from the entry, but at least there's a direct link to the video.


Joel Ivory Johnson
J2i.net | @J2iNet | Mobile Device Development MVP

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 2 Aug 2010
Article Copyright 2010 by Joel Ivory Johnson
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid