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.