In our series on plugins, today we’re going to cover plugin which can help us to work with Accelerometer sensor. This sensor is responsible to detect X, Y, Z co-ordinates of the devices. Using data received from this sensor, you can build games like TempleRun, where users can collect the coins by tilting the device.
There are different APIs for different platform and their usage is different too. First, lets see how we can use this sensor in different platform and then we’ll use plugin in Xamarin.Forms application.
Being Windows Runtime API, the API and its usage is same in Windows and Windows Phone. Here, you create object of the sensor and register for ‘ReadingChanged’ event. Whenever device position is changed, it is reported through that event and UI can be updated using Dispatcher.
public sealed partial class MainPage : Page | |
{ | |
private Accelerometer _accelerometer; | |
public MainPage() | |
{ | |
this.InitializeComponent(); | |
this.NavigationCacheMode = NavigationCacheMode.Required; | |
} | |
/// <summary> | |
/// Invoked when this page is about to be displayed in a Frame. | |
/// </summary> | |
/// <param name="e">Event data that describes how this page was reached. | |
/// This parameter is typically used to configure the page.</param> | |
protected override void OnNavigatedTo(NavigationEventArgs e) | |
{ | |
_accelerometer = Accelerometer.GetDefault(); | |
if (_accelerometer != null) | |
{ | |
// Establish the report interval | |
uint minReportInterval = _accelerometer.MinimumReportInterval; | |
var desiredReportInterval = minReportInterval > 16 ? minReportInterval : 16; | |
_accelerometer.ReportInterval = desiredReportInterval; | |
try | |
{ | |
_accelerometer.ReadingChanged += async (a, b) => | |
{ | |
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => | |
{ | |
txtXAxis.Text = "X axis: " + b.Reading.AccelerationX.ToString("F"); | |
txtYAxis.Text = "Y axis: " + b.Reading.AccelerationY.ToString("F"); | |
txtZAxis.Text = "Z axis: " + b.Reading.AccelerationZ.ToString("F"); | |
}); | |
}; | |
} | |
catch (Exception ex) | |
{ | |
throw; | |
} | |
} | |
else | |
{ | |
new Windows.UI.Popups.MessageDialog("Accelerometer not found", "Error:").ShowAsync(); | |
} | |
} | |
} |
In case of Android, it is again similar to Windows platform. Create object of SensorManager and register for SensorChanged event.
[Activity(Label = "Accelerometer_Droid", MainLauncher = true, Icon = "@drawable/icon")] | |
public class MainActivity : Activity, ISensorEventListener | |
{ | |
private SensorManager _sensorManager; | |
private static readonly object _syncLock = new object(); | |
private TextView x_axis; private TextView y_axis; private TextView z_axis; | |
protected override void OnCreate(Bundle bundle) | |
{ | |
base.OnCreate(bundle); | |
// Set our view from the "main" layout resource | |
SetContentView(Resource.Layout.Main); | |
_sensorManager = (SensorManager)GetSystemService(Context.SensorService); | |
x_axis = FindViewById<TextView>(Resource.Id.lblXAxis); | |
y_axis = FindViewById<TextView>(Resource.Id.lblYAxis); | |
z_axis = FindViewById<TextView>(Resource.Id.lblZAxis); | |
} | |
public void OnAccuracyChanged(Sensor sensor, SensorStatus accuracy) | |
{ | |
//Doing nothing. Just implementing interface. | |
} | |
public void OnSensorChanged(SensorEvent e) | |
{ | |
lock (_syncLock) | |
{ | |
x_axis.Text = e.Values[0].ToString("F"); | |
y_axis.Text = e.Values[1].ToString("F"); | |
z_axis.Text = e.Values[2].ToString("F"); | |
} | |
} | |
protected override void OnResume() | |
{ | |
base.OnResume(); | |
_sensorManager.RegisterListener(this, _sensorManager.GetDefaultSensor(SensorType.Accelerometer), SensorDelay.Ui); | |
} | |
protected override void OnPause() | |
{ | |
base.OnPause(); | |
_sensorManager.UnregisterListener(this); | |
} | |
} |
iOS is not any different. You create object of CMMotionManager and then listen to sensor for changes.
public override void ViewDidLoad() | |
{ | |
base.ViewDidLoad(); | |
_motionManager = new CMMotionManager(); | |
_motionManager.StartAccelerometerUpdates(NSOperationQueue.CurrentQueue, (data, error) => | |
{ | |
lblXAxis.Text = data.Acceleration.X.ToString("F"); | |
lblYAxis.Text = data.Acceleration.Y.ToString("F"); | |
lblZAxis.Text = data.Acceleration.Z.ToString("F"); | |
}); | |
// Perform any additional setup after loading the view, typically from a nib. | |
} |
As you can see, for three different platforms the APIs are totally different. But with Plugins for Xamarin.Forms it becomes easy. You can use DeviceMotion plugin which can work across all these platforms. And the code for same looks like:
private void BtnStart_OnClicked(object sender, EventArgs e) | |
{ | |
CrossDeviceMotion.Current.Start(MotionSensorType.Accelerometer, MotionSensorDelay.Ui); | |
CrossDeviceMotion.Current.SensorValueChanged += (s, a) => | |
{ | |
switch (a.SensorType) | |
{ | |
case MotionSensorType.Accelerometer: | |
lblXAxis.Text = ((MotionVector)a.Value).X.ToString("F"); | |
lblYAxis.Text = ((MotionVector)a.Value).Y.ToString("F"); | |
lblZAxis.Text = ((MotionVector)a.Value).Z.ToString("F"); | |
break; | |
} | |
}; | |
} | |
private void BtnStop_OnClicked(object sender, EventArgs e) | |
{ | |
CrossDeviceMotion.Current.Stop(MotionSensorType.Accelerometer); | |
} |
In this series on plugin we’ve seen how particular concept can be implemented in all the three platforms and how we can use plugin to make life easier. This will be be last post in this series, but there are many plugins available which you can explore and use in your projects. Do let me know if you want to cover any specific plugin. We’ll start with a new series in couple of weeks. Till then… happy coding :)
Namaste
Mayur Tendulkar