Background

Historically, interacting with device sensors, such as a gyroscope, accelerometer, or proximity sensors, varied according to the platform. Building a contextually aware Windows Phone App meant that you were developing against a different set of APIs than if you were building a similar Windows Store App. Windows 8.1 and Windows Phone 8.1 unified the API, allowing developers to use similar code when developing against each platform; however, the experience was still disjointed and subject to slight variations between different sensors.

The Universal Windows Platform and the Sensor API

At the 2015 Microsoft Build Conference, I attended a session on "Building Rich, Contextually Aware Universal Windows Apps Using Sensors." Among other topics, the session highlighted how the promise of Windows 10 and Universal Windows Platform (UWP) means that we, as developers, can take advantage of sensors running on everything from desktops to phones—and even Raspberry Pis, Surface Hubs, and HoloLens—with a single set of consistent APIs. So how do we do that?

API Usage and Examples

Working with the sensor API is very straightforward. In the following example we are retrieving the device's accelerometer, instructing the sensor to report its current reading every second, and logging the device's acceleration along the z-axis (i.e. movement perpendicular to the force of gravity).

 private void SetupAccelerometer()
 {
 var accelerometer = Windows.Devices.Sensors.Accelerometer.GetDefault();
 accelerometer.ReportInterval = 1000;
 if (accelerometer != null)
 {
 accelerometer.ReadingChanged += Accelerometer_ReadingChanged;
 }
 }
 private void Accelerometer_ReadingChanged(Accelerometer sender, AccelerometerReadingChangedEventArgs args)
 {
 Debug.WriteLine(String.Format("Accelerometer Reading:\t{0}\t{1}", args.Reading.Timestamp.ToString(), args.Reading.AccelerationZ.ToString()));
 }

Here is the output with the device at rest, indicating the force of gravity on the machine:

 Accelerometer Reading: 5/6/2015 3:35:57 PM -04:00 -0.589000046253204
 Accelerometer Reading: 5/6/2015 3:35:58 PM -04:00 -0.578000009059906
 Accelerometer Reading: 5/6/2015 3:35:59 PM -04:00 -0.578000009059906
 Accelerometer Reading: 5/6/2015 3:36:00 PM -04:00 -0.585000038146973

It's important to note that the previous output is from an app running on a laptop with Windows 10, but the output would have been the same if the same app were running on any Windows 10 device, assuming it has an accelerometer.

The null check in the previous example is important because we cannot guarantee that the devices running our apps have the requisite hardware to support what we are trying to accomplish. When calling into the sensor API from a Universal App, the proper precautions must be taken to ensure the app responds gracefully when the hardware it expects is not present. The following example is similar to the last, except that we are attempting to use the light sensor.

 private void SetupLightSensor()
 {
 var lightSensor = Windows.Devices.Sensors.LightSensor.GetDefault();
 if (lightSensor != null)
 {
 lightSensor.ReadingChanged += LightSensor_ReadingChanged;
 }
 } 
 private void LightSensor_ReadingChanged(LightSensor sender, LightSensorReadingChangedEventArgs args)
 {
 Debug.WriteLine(String.Format("Light Sensor Reading:\t{0}\t{1}", args.Reading.Timestamp.ToString(), args.Reading.IlluminanceInLux.ToString()));
 }

When I run this app on my desktop running Windows 10, I do not receive any output because my machine does not have a light sensor. However, the same code running on my Windows Phone produces the measurements and output I would expect.

Conclusion

The sensor API is not new to Windows 10 app development, but UWP should change the way we consider leveraging sensors from our apps. We can utilize sensors on a variety of devices to build apps that are aware of the user's environment, and use that information to tailor the user's experience regardless of the portability of the device or the size of the screen they are interacting with.