Windows Phone 7

Shake detection using accelerometer on Windows Phone 7.1

I needed some shake detection on Windows Phone 7.1 only finding some examples using some deprecated events. So I have updated the sample found on Mark Monster's blog so that it works with Windows Phone 7.1.

To use this you need to add the references:
Microsoft.Devices.Sensors
Microsoft.Xna.Framework

Helper class:

using System;
using Microsoft.Devices.Sensors;

namespace Ostebaronen.ShakeShakeShake
{
    public class AccelerometerSensorShakeDetector : IDisposable
    {
        private const double ShakeThreshold = 0.7;
        private readonly Accelerometer _sensor = new Accelerometer();
        private AccelerometerReading _lastReading;
        private int _shakeCount;
        private bool _shaking;

        public AccelerometerSensorShakeDetector()
        {
            var sensor = new Accelerometer();
            if (sensor.State == SensorState.NotSupported)
                throw new NotSupportedException("Accelerometer not supported on this device");
            _sensor = sensor;
        }

        public SensorState State
        {
            get { return _sensor.State; }
        }

        #region IDisposable Members

        public void Dispose()
        {
            if (_sensor != null)
                _sensor.Dispose();
        }

        #endregion

        private event EventHandler ShakeDetectedHandler;

        public event EventHandler ShakeDetected
        {
            add
            {
                ShakeDetectedHandler += value;
                _sensor.CurrentValueChanged += ReadingChanged;
            }
            remove
            {
                ShakeDetectedHandler -= value;
                _sensor.CurrentValueChanged -= ReadingChanged;
            }
        }

        public void Start()
        {
            if (_sensor != null)
                _sensor.Start();
        }

        public void Stop()
        {
            if (_sensor != null)
                _sensor.Stop();
        }

        private void ReadingChanged(object sender, SensorReadingEventArgs<AccelerometerReading> e)
        {
            //Code for checking shake detection
            if (_sensor.State == SensorState.Ready)
            {
                AccelerometerReading reading = e.SensorReading;
                try
                {
                    if (!_lastReading.Equals(null))
                    {
                        if (!_shaking && CheckForShake(_lastReading, reading, ShakeThreshold) && _shakeCount >= 1)
                        {
                            //We are shaking
                            _shaking = true;
                            _shakeCount = 0;
                            OnShakeDetected();
                        }
                        else if (CheckForShake(_lastReading, reading, ShakeThreshold))
                        {
                            _shakeCount++;
                        }
                        else if (!CheckForShake(_lastReading, reading, 0.2))
                        {
                            _shakeCount = 0;
                            _shaking = false;
                        }
                    }
                    _lastReading = reading;
                }
                catch
                {
                    /* ignore errors */
                }
            }
        }

        private void OnShakeDetected()
        {
            if (ShakeDetectedHandler != null)
                ShakeDetectedHandler(this, EventArgs.Empty);
        }

        private static bool CheckForShake(AccelerometerReading last, AccelerometerReading current,
                                            double threshold)
        {
            double deltaX = Math.Abs((last.Acceleration.X - current.Acceleration.X));
            double deltaY = Math.Abs((last.Acceleration.Y - current.Acceleration.Y));
            double deltaZ = Math.Abs((last.Acceleration.Z - current.Acceleration.Z));

            return (deltaX > threshold && deltaY > threshold) ||
                    (deltaX > threshold && deltaZ > threshold) ||
                    (deltaY > threshold && deltaZ > threshold);
        }
    }
}

Using the class add this to the place you want to detect shakes:

            AccelerometerSensorShakeDetector shakeSensor = new AccelerometerSensorShakeDetector();
            Loaded += (sender, args) =>
            {
                shakeSensor.ShakeDetected += shakeSensor_ShakeDetected;
                shakeSensor.Start();
            };
            Unloaded += (sender, args) =>
            {
                shakeSensor.ShakeDetected -= shakeSensor_ShakeDetected;
                shakeSensor.Stop();
            };

        void shakeSensor_ShakeDetected(object sender, EventArgs e)
        {
                //Shake detected
                //Use Dispatcher.BeginInvoke() to run on UI thread.
        }

If you want to update UI elements remember to do it on the UI thread as this one returns on another one.