Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Xamarin handle shake accelerometer on Android?

I see that Xamarin has docs for Creating a Gesture Listener but nothing about 'shaking' the device only 'fling' on the screen. I'm wondering if Xamarin for Android is able to listen for shake gestures? Does any one know or has anyone tried? Thank you in advance.

like image 554
jast_meg Avatar asked Apr 16 '14 21:04

jast_meg


1 Answers

Here is a complete example that uses Android.Hardware.ISensorEventListener to detect a shake gesture. You should be able to drop this into your own project(s) without any hassle.

[Activity (Label = "ShakeDetection", MainLauncher = true)]
public class MainActivity : Activity, Android.Hardware.ISensorEventListener
{
    bool hasUpdated = false;
    DateTime lastUpdate;
    float last_x = 0.0f;
    float last_y = 0.0f;
    float last_z = 0.0f;

    const int ShakeDetectionTimeLapse = 250;
    const double ShakeThreshold = 800;

    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);

        SetContentView (Resource.Layout.Main);

        // Register this as a listener with the underlying service.
        var sensorManager = GetSystemService (SensorService) as Android.Hardware.SensorManager;
        var sensor = sensorManager.GetDefaultSensor (Android.Hardware.SensorType.Accelerometer);
        sensorManager.RegisterListener(this, sensor, Android.Hardware.SensorDelay.Game);
    }

    #region Android.Hardware.ISensorEventListener implementation

    public void OnAccuracyChanged (Android.Hardware.Sensor sensor, Android.Hardware.SensorStatus accuracy)
    {
    }

    public void OnSensorChanged (Android.Hardware.SensorEvent e)
    {
        if (e.Sensor.Type == Android.Hardware.SensorType.Accelerometer)
        {
            float x = e.Values[0];
            float y = e.Values[1];
            float z = e.Values[2];

            DateTime curTime = System.DateTime.Now;
            if (hasUpdated == false)
            {
                hasUpdated = true;
                lastUpdate = curTime;
                last_x = x;
                last_y = y;
                last_z = z;
            }
            else
            {
                if ((curTime - lastUpdate).TotalMilliseconds > ShakeDetectionTimeLapse) {
                    float diffTime = (float)(curTime - lastUpdate).TotalMilliseconds;
                    lastUpdate = curTime;
                    float total = x + y + z - last_x - last_y - last_z;
                    float speed = Math.Abs(total) / diffTime * 10000;

                    if (speed > ShakeThreshold) {
                        Toast.MakeText(this, "shake detected w/ speed: " + speed, ToastLength.Short).Show();
                    }

                    last_x = x;
                    last_y = y;
                    last_z = z;
                }
            }
        }
    }
    #endregion
}

The above activity implements the Android.Hardware.ISensorEventListener interface and then registers it through the SensorManager. The actual sensor events (shake etc) are piped into OnSensorChanged; this is where we hold the logic for our shake detection code.

I've based this answer on this one but have made a few modifications to it. Firstly, this answer uses ISensorEventListener rather than ISensorListener (which was deprecated in API level 3). And you'll find start gesture detection included (through hasUpdated) and some variables to control the sensitivity of the shake. By playing around with ShakeDetectionTimeLapse and ShakeDetectionThreshold you should be able to fine tune it to your needs.

See:

  1. How to detect shake event with android?
  2. android SensorEventListener problem
like image 99
matthewrdev Avatar answered Oct 24 '22 04:10

matthewrdev