Listening to sensor data

Just as touching a device screen is input, so is rotating and moving the actual physical device in its environment. Most devices are built with several sensors that can be used to read the state of the device in its environment.

How to do it...

We can access all the available sensors and the sensor data on the device through the SensorManager type:

  1. The instance of the SensorManager type is obtained from the current context:
    var manager = SensorManager.FromContext(this);
  2. Once we have the manager, we check whether a particular sensor exists, and return the instance of it using the GetDefaultSensor() method:
    var type = SensorType.Accelerometer;
    var accelerometer = manager.GetDefaultSensor(type);
    if (accelerometer == null) {
      // handle no acceleromenter
    }
  3. In order to be able to receive sensor data, we must implement the ISensorEventListener interface:
    public class MyActivity : Activity, ISensorEventListener {
      public void OnAccuracyChanged(
        Sensor sensor, SensorStatus accuracy) {
      }
      public void OnSensorChanged(SensorEvent e) {
      }
    }
  4. To start receiving data from a sensor, we register it along with the listener instance and data update rate via the RegisterListener() method:
    manager.RegisterListener(
      this, accelerometer, SensorDelay.Fastest);
  5. Once we are finished with the sensor, we unregister the listener:
    manager.UnregisterListener(this);

The data from sensors can be used for many different purposes, ranging from making decisions to drawing on the screen. For example, we can make use of the accelerometer data in the OnSensorChanged() method to create a level or plumb line:

  1. First, we will need fields to hold data across events:
    private float rotationX;
    private float rotationY;
  2. Then, we will filter the raw event data to prevent rapid fluctuations of the values:
    const float Filter = 0.05f;
    var x = e.Values[0];
    var y = e.Values[1];
    rotationX = (x * Filter) + (rotationX * (1f - Filter));
    rotationY = (y * Filter) + (rotationY * (1f - Filter));
  3. Now that we have the filtered values, we can convert this into a 2D angle:
    var rotation2d = (float)Math.Atan2(rotationY, rotationX);
    var degrees = -rotation2d * (180f / (float)Math.PI);
  4. Finally, we can apply the rotation to a view:
    levelView.Rotation = degrees + 90f;

How it works...

Many devices are built with multiple sensors. This can range from accelerometers and gyroscopes to proximity sensors and step counters. All of these sensors constantly stream data of where and how the device is situated in the environment. All this data can be used to both enhance as well as provide core functionality to an app.

For example, the accelerometer and gyroscope can be used to create a game that allows the user to control a player based on how the device is rotated. Or, the step counter sensor can be used to provide data to a health or fitness app.

However, not all devices have all the sensors. Before a sensor can be used by our app, we need to ensure that it exists on the device and that we can access the data. This is done using the SensorManager instance. Once we have obtained the instance of the sensor manager, we are able to query the existence of a particular sensor using the GetDefaultSensor() method.

Note

Not all devices may have a particular sensor, thus checks need to be performed before using it.

The GetDefaultSensor() method returns either the sensor that was requested or null if the device does not support that sensor. As sensors are queried by type, there may be multiple versions of a sensor by different vendors. If this is the case, we can use the GetSensorList() method instead. This will provide a collection of sensors that match the requested sensor type.

Tip

There may be multiple versions of a sensor type on a device.

We can find out about a particular sensor using the various properties on the Sensor type. These properties include the Version and Vendor properties, as well as the characteristics of the sensor, such as Power for the power requirements.

Once we have the desired sensor, we can start reading the data stream. To do this, we need to implement the ISensorEventListener interface, and register it with the sensor manager. Registering for data requires that we provide the sensor manager with the listener, sensor, and sampling rate of the RegisterListener() method.

After the listener is registered, we will receive the sensor data in the OnSensorChanged() method. This method receives the data from the sensor, which includes the accuracy, time, and the actual data values. The values from the sensor are provided via the Values property on the SensorEvent type. This property is an array of type float, and the elements vary across sensor types.

Note

The number of values provided by the OnSensorChanged() method may vary from sensor to sensor.

For example, the accelerometer sensor has three elements, the first being the force along the x axis, the second being the force along the y axis, and the third being the force along the z axis. The step counter sensor only has one element, which is the number of steps taken since the device boot.

As the OnSensorChanged() method may be invoked at a high rate, we should avoid blocking its return. If filtering or processing of the data is required, we should move it out from the current method and into another method. Also, when registering the listener, we can possibly select a lower rate of data if a high rate is not required. This will preserve both battery and system resources.

Tip

The OnSensorChanged() method should not block its return.

As having a listener registered to a sensor consumes battery, we should unregister the sensor as soon as it is no longer needed. We do this by passing the listener to the UnregisterListener() method. If the sensor is used to update the UI, then as soon as the activity leaves the foreground, we can unregister it in the OnPause() method and reregister it in the OnResume() method.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset