Accessing device sensors
Devices have all sorts of sensors that are available to you. Some sensors can detect movement, others changes in the environment, such as light. Monitoring and reacting to these sensors makes your app dynamic in adapting to how the device is being used. You can also respond to changes in the sensors and alert the user. This article gives you a brief overview of the common sensors supported by .NET Multi-platform App UI (.NET MAUI).
Device sensor-related types are available in the Microsoft.Maui.Devices.Sensors
namespace.
Sensor speed
Sensor speed sets the speed in which a sensor will return data to your app. When you start a sensor, you provide the desired sensor speed with the SensorSpeed enumeration:
Fastest
Get the sensor data as fast as possible (not guaranteed to return on UI thread).Game
Rate suitable for games (not guaranteed to return on UI thread).UI
Rate suitable for general user interface.Default
Default rate suitable for screen orientation changes.
Warning
Monitoring too many sensors at once may affect the rate sensor data is returned to your app.
In .NET 8, SensorSpeed intervals are identical across all platforms:
- Default uses an interval of 200ms.
- UI uses an interval of 60ms.
- Game uses an interval of 20ms.
- Fastest uses an interval of 5ms.
Sensor event handlers
Event handlers added to sensors with either the Game or Fastest speeds aren't guaranteed to run on the UI thread. If the event handler needs to access user-interface elements, use the MainThread.BeginInvokeOnMainThread
method to run that code on the UI thread.
Accelerometer
The accelerometer sensor measures the acceleration of the device along its three axes. The data reported by the sensor represents how the user is moving the device.
The IAccelerometer interface provides access to the sensor, and is available through the Accelerometer.Default property. Both the IAccelerometer
interface and Accelerometer
class are contained in the Microsoft.Maui.Devices.Sensors
namespace.
Get started
To access the accelerometer functionality the following platform-specific setup maybe required:
If your app targets Android 12+ (API 31+), the system places a 200 Hz limit on the refresh rate of data from this sensor. If your app needs to gather sensor data using the Fastest sensor speed, you must declare the HIGH_SAMPLING_RATE_SENSORS
permission. You can configure the permission in the following ways:
Add the assembly-based permission:
Open the Platforms/Android/MainApplication.cs file and add the following assembly attribute after
using
directives:[assembly: UsesPermission(Android.Manifest.Permission.HighSamplingRateSensors)]
- or -
Update the Android Manifest:
Open the Platforms/Android/AndroidManifest.xml file and add the following line in the
manifest
node:<uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS" />
- or -
Update the Android Manifest in the manifest editor:
In Visual Studio double-click on the Platforms/Android/AndroidManifest.xml file to open the Android manifest editor. Then, under Required permissions check the HIGH_SAMPLING_RATE_SENSORS permission. This will automatically update the AndroidManifest.xml file.
Note
If a user turns off microphone access using the device toggles, motion and position sensors are always rate-limited, regardless of whether you declare the HIGH_SAMPLING_RATE_SENSORS
permission.
Monitor the accelerometer sensor
To start monitoring the accelerometer sensor, call the IAccelerometer.Start method. .NET MAUI sends accelerometer data changes to your app by raising the IAccelerometer.ReadingChanged event. Use the IAccelerometer.Stop method to stop monitoring the sensor. You can detect the monitoring state of the accelerometer with the IAccelerometer.IsMonitoring property, which will be true
if the accelerometer was started and is currently being monitored.
The following code example demonstrates monitoring the accelerometer for changes:
public void ToggleAccelerometer()
{
if (Accelerometer.Default.IsSupported)
{
if (!Accelerometer.Default.IsMonitoring)
{
// Turn on accelerometer
Accelerometer.Default.ReadingChanged += Accelerometer_ReadingChanged;
Accelerometer.Default.Start(SensorSpeed.UI);
}
else
{
// Turn off accelerometer
Accelerometer.Default.Stop();
Accelerometer.Default.ReadingChanged -= Accelerometer_ReadingChanged;
}
}
}
private void Accelerometer_ReadingChanged(object sender, AccelerometerChangedEventArgs e)
{
// Update UI Label with accelerometer state
AccelLabel.TextColor = Colors.Green;
AccelLabel.Text = $"Accel: {e.Reading}";
}
Accelerometer readings are reported back in G. A G is a unit of gravitation force equal to the gravity exerted by the earth's gravitational field $(9.81 m/s^2)$.
The coordinate-system is defined relative to the screen of the device in its default orientation. The axes aren't swapped when the device's screen orientation changes.
The X axis is horizontal and points to the right, the Y axis is vertical and points up and the Z axis points towards the outside of the front face of the screen. In this system, coordinates behind the screen have negative Z values.
Examples:
When the device lies flat on a table and is pushed on its left side toward the right, the X acceleration value is positive.
When the device lies flat on a table, the acceleration value is +1.00 G or $(+9.81 m/s^2)$, which corresponds to the acceleration of the device $(0 m/s^2)$ minus the force of gravity $(-9.81 m/s^2)$ and normalized as in G.
When the device lies flat on a table and is pushed toward the sky with an acceleration of A $m/s^2$, the acceleration value is equal to $A+9.81$ which corresponds to the acceleration of the device $(+A m/s^2)$ minus the force of gravity $(-9.81 m/s^2)$ and normalized in G.
Platform-specific information (Accelerometer)
There is no platform-specific information related to the accelerometer sensor.
Barometer
The barometer sensor measures the ambient air pressure. The data reported by the sensor represents the current air pressure. This data is reported the first time you start monitoring the sensor and then each time the pressure changes.
The IBarometer interface provides access to the sensor, and is available through the Barometer.Default property. Both the IBarometer
interface and Barometer
class are contained in the Microsoft.Maui.Devices.Sensors
namespace.
To start monitoring the barometer sensor, call the IBarometer.Start method. .NET MAUI sends air pressure readings to your app by raising the IBarometer.ReadingChanged event. Use the IBarometer.Stop method to stop monitoring the sensor. You can detect the monitoring state of the barometer with the IBarometer.IsMonitoring property, which will be true
if the barometer is currently being monitored.
The pressure reading is represented in hectopascals.
The following code example demonstrates monitoring the barometer for changes:
public void ToggleBarometer()
{
if (Barometer.Default.IsSupported)
{
if (!Barometer.Default.IsMonitoring)
{
// Turn on barometer
Barometer.Default.ReadingChanged += Barometer_ReadingChanged;
Barometer.Default.Start(SensorSpeed.UI);
}
else
{
// Turn off barometer
Barometer.Default.Stop();
Barometer.Default.ReadingChanged -= Barometer_ReadingChanged;
}
}
}
private void Barometer_ReadingChanged(object sender, BarometerChangedEventArgs e)
{
// Update UI Label with barometer state
BarometerLabel.TextColor = Colors.Green;
BarometerLabel.Text = $"Barometer: {e.Reading}";
}
Platform-specific information (Barometer)
This section describes platform-specific implementation details related to the barometer sensor.
No platform-specific implementation details.
Compass
The compass sensor monitors the device's magnetic north heading.
The ICompass interface provides access to the sensor, and is available through the Compass.Default property. Both the ICompass
interface and Compass
class are contained in the Microsoft.Maui.Devices.Sensors
namespace.
To start monitoring the compass sensor, call the ICompass.Start method. .NET MAUI raises the ICompass.ReadingChanged event when the compass heading changes. Use the ICompass.Stop method to stop monitoring the sensor. You can detect the monitoring state of the compass with the ICompass.IsMonitoring property, which will be true
if the compass is currently being monitored.
The following code example demonstrates monitoring the compass for changes:
private void ToggleCompass()
{
if (Compass.Default.IsSupported)
{
if (!Compass.Default.IsMonitoring)
{
// Turn on compass
Compass.Default.ReadingChanged += Compass_ReadingChanged;
Compass.Default.Start(SensorSpeed.UI);
}
else
{
// Turn off compass
Compass.Default.Stop();
Compass.Default.ReadingChanged -= Compass_ReadingChanged;
}
}
}
private void Compass_ReadingChanged(object sender, CompassChangedEventArgs e)
{
// Update UI Label with compass state
CompassLabel.TextColor = Colors.Green;
CompassLabel.Text = $"Compass: {e.Reading}";
}
Platform-specific information (Compass)
This section describes platform-specific implementation details related to the compass feature.
Android doesn't provide an API for retrieving the compass heading. .NET MAUI uses the accelerometer and magnetometer sensors to calculate the magnetic north heading, which is recommended by Google.
In rare instances, you maybe see inconsistent results because the sensors need to be calibrated. Recalibrating the compass on Android varies by phone model and Android version. You'll need to search the internet on how to recalibrate the compass. Here are two links that may help in recalibrating the compass:
- Google Help Center: Find and improve your location’s accuracy
- Stack Exchange Android Enthusiasts: How can I calibrate the compass on my phone?
Running multiple sensors from your app at the same time may impair the sensor speed.
Lowpass filter
Because of how the Android compass values are updated and calculated, there may be a need to smooth out the values. A Lowpass filter can be applied that averages the sine and cosine values of the angles and can be turned on by using the Start
method overload, which accepts the bool applyLowPassFilter
parameter:
Compass.Default.Start(SensorSpeed.UI, applyLowPassFilter: true);
This is only applied on the Android platform, and the parameter is ignored on iOS and Windows. For more information, see this GitHub issue comment.
Shake
Even though this article is listing shake as a sensor, it isn't. The accelerometer is used to detect when the device is shaken.
The IAccelerometer interface provides access to the sensor, and is available through the Accelerometer.Default property. Both the IAccelerometer
interface and Accelerometer
class are contained in the Microsoft.Maui.Devices.Sensors
namespace.
Note
If your app needs to gather accelerometer sensor data using the Fastest sensor speed, you must declare the HIGH_SAMPLING_RATE_SENSORS
permission. For more information, see Accelerometer.
The detect shake API uses raw readings from the accelerometer to calculate acceleration. It uses a simple queue mechanism to detect if 3/4ths of the recent accelerometer events occurred in the last half second. Acceleration is calculated by adding the square of the X, Y, and Z ($x^2+y^2+z^2$) readings from the accelerometer and comparing it to a specific threshold.
To start monitoring the accelerometer sensor, call the IAccelerometer.Start method. When a shake is detected, the IAccelerometer.ShakeDetected event is raised. Use the IAccelerometer.Stop method to stop monitoring the sensor. You can detect the monitoring state of the accelerometer with the IAccelerometer.IsMonitoring
property, which will be true
if the accelerometer was started and is currently being monitored.
It's recommended to use Game or faster for the SensorSpeed.
The following code example demonstrates monitoring the accelerometer for the ShakeDetected
event:
private void ToggleShake()
{
if (Accelerometer.Default.IsSupported)
{
if (!Accelerometer.Default.IsMonitoring)
{
// Turn on accelerometer
Accelerometer.Default.ShakeDetected += Accelerometer_ShakeDetected;
Accelerometer.Default.Start(SensorSpeed.Game);
}
else
{
// Turn off accelerometer
Accelerometer.Default.Stop();
Accelerometer.Default.ShakeDetected -= Accelerometer_ShakeDetected;
}
}
}
private void Accelerometer_ShakeDetected(object sender, EventArgs e)
{
// Update UI Label with a "shaked detected" notice, in a randomized color
ShakeLabel.TextColor = new Color(Random.Shared.Next(256), Random.Shared.Next(256), Random.Shared.Next(256));
ShakeLabel.Text = $"Shake detected";
}
Platform-specific information (Shake)
There is no platform-specific information related to the accelerometer sensor.
Gyroscope
The gyroscope sensor measures the angular rotation speed around the device's three primary axes.
The IGyroscope interface provides access to the sensor, and is available through the Gyroscope.Default property. Both the IGyroscope
interface and Gyroscope
class are contained in the Microsoft.Maui.Devices.Sensors
namespace.
Get started
To access the gyroscope functionality the following platform-specific setup maybe required:
If your app targets Android 12+ (API 31+), the system places a 200 Hz limit on the refresh rate of data from this sensor. If your app needs to gather sensor data using the Fastest sensor speed, you must declare the HIGH_SAMPLING_RATE_SENSORS
permission. You can configure the permission in the following ways:
Add the assembly-based permission:
Open the Platforms/Android/MainApplication.cs file and add the following assembly attribute after
using
directives:[assembly: UsesPermission(Android.Manifest.Permission.HighSamplingRateSensors)]
- or -
Update the Android Manifest:
Open the Platforms/Android/AndroidManifest.xml file and add the following line in the
manifest
node:<uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS" />
- or -
Update the Android Manifest in the manifest editor:
In Visual Studio double-click on the Platforms/Android/AndroidManifest.xml file to open the Android manifest editor. Then, under Required permissions check the HIGH_SAMPLING_RATE_SENSORS permission. This will automatically update the AndroidManifest.xml file.
Note
If a user turns off microphone access using the device toggles, motion and position sensors are always rate-limited, regardless of whether you declare the HIGH_SAMPLING_RATE_SENSORS
permission.
Monitor the gyroscope sensor
To start monitoring the gyroscope sensor, call the IGyroscope.Start method. .NET MAUI sends gyroscope data changes to your app by raising the IGyroscope.ReadingChanged event. The data provided by this event is measured in rad/s (radian per second). Use the IGyroscope.Stop method to stop monitoring the sensor. You can detect the monitoring state of the gyroscope with the IGyroscope.IsMonitoring property, which will be true
if the gyroscope was started and is currently being monitored.
The following code example demonstrates monitoring the gyroscope:
private void ToggleGyroscope()
{
if (Gyroscope.Default.IsSupported)
{
if (!Gyroscope.Default.IsMonitoring)
{
// Turn on gyroscope
Gyroscope.Default.ReadingChanged += Gyroscope_ReadingChanged;
Gyroscope.Default.Start(SensorSpeed.UI);
}
else
{
// Turn off gyroscope
Gyroscope.Default.Stop();
Gyroscope.Default.ReadingChanged -= Gyroscope_ReadingChanged;
}
}
}
private void Gyroscope_ReadingChanged(object sender, GyroscopeChangedEventArgs e)
{
// Update UI Label with gyroscope state
GyroscopeLabel.TextColor = Colors.Green;
GyroscopeLabel.Text = $"Gyroscope: {e.Reading}";
}
Platform-specific information (Gyroscope)
There is no platform-specific information related to the gyroscope sensor.
Magnetometer
The magnetometer sensor indicates the device's orientation relative to Earth's magnetic field.
The IMagnetometer interface provides access to the sensor, and is available through the Magnetometer.Default property. Both the IMagnetometer
interface and Magnetometer
class are contained in the Microsoft.Maui.Devices.Sensors
namespace.
Get started
To access the magnetometer functionality the following platform-specific setup maybe required:
If your app targets Android 12+ (API 31+), the system places a 200 Hz limit on the refresh rate of data from this sensor. If your app needs to gather sensor data using the Fastest sensor speed, you must declare the HIGH_SAMPLING_RATE_SENSORS
permission. You can configure the permission in the following ways:
Add the assembly-based permission:
Open the Platforms/Android/MainApplication.cs file and add the following assembly attribute after
using
directives:[assembly: UsesPermission(Android.Manifest.Permission.HighSamplingRateSensors)]
- or -
Update the Android Manifest:
Open the Platforms/Android/AndroidManifest.xml file and add the following line in the
manifest
node:<uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS" />
- or -
Update the Android Manifest in the manifest editor:
In Visual Studio double-click on the Platforms/Android/AndroidManifest.xml file to open the Android manifest editor. Then, under Required permissions check the HIGH_SAMPLING_RATE_SENSORS permission. This will automatically update the AndroidManifest.xml file.
Note
If a user turns off microphone access using the device toggles, motion and position sensors are always rate-limited, regardless of whether you declare the HIGH_SAMPLING_RATE_SENSORS
permission.
Monitor the magnetometer sensor
To start monitoring the magnetometer sensor, call the IMagnetometer.Start method. .NET MAUI sends magnetometer data changes to your app by raising the IMagnetometer.ReadingChanged event. The data provided by this event is measured in $µT$ (microteslas). Use the IMagnetometer.Stop method to stop monitoring the sensor. You can detect the monitoring state of the magnetometer with the IMagnetometer.IsMonitoring property, which will be true
if the magnetometer was started and is currently being monitored.
The following code example demonstrates monitoring the magnetometer:
private void ToggleMagnetometer()
{
if (Magnetometer.Default.IsSupported)
{
if (!Magnetometer.Default.IsMonitoring)
{
// Turn on magnetometer
Magnetometer.Default.ReadingChanged += Magnetometer_ReadingChanged;
Magnetometer.Default.Start(SensorSpeed.UI);
}
else
{
// Turn off magnetometer
Magnetometer.Default.Stop();
Magnetometer.Default.ReadingChanged -= Magnetometer_ReadingChanged;
}
}
}
private void Magnetometer_ReadingChanged(object sender, MagnetometerChangedEventArgs e)
{
// Update UI Label with magnetometer state
MagnetometerLabel.TextColor = Colors.Green;
MagnetometerLabel.Text = $"Magnetometer: {e.Reading}";
}
Platform-specific information (Magnetometer)
There is no platform-specific information related to the magnetometer sensor.
Orientation
The orientation sensor monitors the orientation of a device in 3D space.
Note
This sensor isn't used for determining if the device's video display is in portrait or landscape mode. Use the DeviceDisplay.Current.MainDisplayInfo.Orientation
property instead. For more information, see Device display information.
The IOrientationSensor interface provides access to the sensor, and is available through the OrientationSensor.Default property. Both the IOrientationSensor
interface and OrientationSensor
class are contained in the Microsoft.Maui.Devices.Sensors
namespace.
To start monitoring the orientation sensor, call the IOrientationSensor.Start method. .NET MAUI sends orientation data changes to your app by raising the IOrientationSensor.ReadingChanged event. Use the IOrientationSensor.Stop method to stop monitoring the sensor. You can detect the monitoring state of the orientation with the IOrientationSensor.IsMonitoring property, which will be true
if the orientation was started and is currently being monitored.
The following code example demonstrates monitoring the orientation sensor:
private void ToggleOrientation()
{
if (OrientationSensor.Default.IsSupported)
{
if (!OrientationSensor.Default.IsMonitoring)
{
// Turn on orientation
OrientationSensor.Default.ReadingChanged += Orientation_ReadingChanged;
OrientationSensor.Default.Start(SensorSpeed.UI);
}
else
{
// Turn off orientation
OrientationSensor.Default.Stop();
OrientationSensor.Default.ReadingChanged -= Orientation_ReadingChanged;
}
}
}
private void Orientation_ReadingChanged(object sender, OrientationSensorChangedEventArgs e)
{
// Update UI Label with orientation state
OrientationLabel.TextColor = Colors.Green;
OrientationLabel.Text = $"Orientation: {e.Reading}";
}
IOrientationSensor
readings are reported back in the form of a Quaternion that describes the orientation of the device based on two 3D coordinate systems:
The device (generally a phone or tablet) has a 3D coordinate system with the following axes:
- The positive X-axis points to the right of the display in portrait mode.
- The positive Y-axis points to the top of the device in portrait mode.
- The positive Z-axis points out of the screen.
The 3D coordinate system of the Earth has the following axes:
- The positive X-axis is tangent to the surface of the Earth and points east.
- The positive Y-axis is also tangent to the surface of the Earth and points north.
- The positive Z-axis is perpendicular to the surface of the Earth and points up.
The Quaternion
describes the rotation of the device's coordinate system relative to the Earth's coordinate system.
A Quaternion
value is closely related to rotation around an axis. If an axis of rotation is the normalized vector ($a_x, a_y, a_z$), and the rotation angle is $\theta$, then the (X, Y, Z, W) components of the quaternion are:
$(a_x \times \sin(\theta/2), a_y \times \sin(\theta/2), a_z \times \sin(\theta/2), \cos(\theta/2))$
These are right-hand coordinate systems, so with the thumb of the right hand pointed in the positive direction of the rotation axis, the curve of the fingers indicate the direction of rotation for positive angles.
Examples:
When the device lies flat on a table with its screen facing up, with the top of the device (in portrait mode) pointing north, the two coordinate systems are aligned. The
Quaternion
value represents the identity quaternion (0, 0, 0, 1). All rotations can be analyzed relative to this position.When the device lies flat on a table with its screen facing up, and the top of the device (in portrait mode) pointing west, the
Quaternion
value is (0, 0, 0.707, 0.707). The device has been rotated 90 degrees around the Z axis of the Earth.When the device is held upright so that the top (in portrait mode) points towards the sky, and the back of the device faces north, the device has been rotated 90 degrees around the X axis. The
Quaternion
value is (0.707, 0, 0, 0.707).If the device is positioned so its left edge is on a table, and the top points north, the device has been rotated -90 degrees around the Y axis (or 90 degrees around the negative Y axis). The
Quaternion
value is (0, -0.707, 0, 0.707).
Platform-specific information (Orientation)
There is no platform-specific information related to the orientation sensor.