[MUSIC] Handheld devices allow for context-aware computing, and that means that applications can respond or behave differently based on contextual factors such as the location at which they are being used, how they're being held by their user, how much ambient light there is, or how fast the user is traveling. To do this, applications read information from the wide range of sensors that come built in with today's handheld devices. In this lesson, I'll talk about the sensors that Android devices can support, and I'll discuss how applications can access these sensors. Next, I'll discuss sensor events, the class that Android uses to represent sensor readings, and I'll discuss sensor event listeners which are used to transfer information from a sensor to your application. After that, I'll discuss some common techniques that are used to smooth out or filter sensor values so that applications can use the values in a variety of different ways. And as we go through the lesson, I'll demonstrate several example applications that make use of common sensors. Sensors are hardware components that measure the physical environment around the device, and these sensors come in three flavors. There are sensors that measure motion, for example, how fast you're moving. There are sensors that measure the position of the device. For instance, where you are in the world, or what the orientation of the device is. And there are sensors that measure the environment, such as the amount of light, pressure, or humidity around the device. For example, my device has a 3-axis accelerometer which measures the forces exerted on the device, for example, when I shake it. It also has a 3-axis magnetic field, which can be used to measure its position or orientation relative to the Earth's magnetic field. And we'll see that in action later on in one of the example applications. And lastly, my device has a barometer that measures atmospheric pressure. In order for an application to use sensors, it first needs to get a reference to the SensorManager. The SensorManager is the system service that manages sensors. Applications get a reference to the SensorManager by calling the getSystemService method, passing in the value Context.SENSOR_SERVICE. In order to access a specific sensor, applications use the SensorManager's getDefaultSensor method, passing in a constant corresponding to the desired sensor. Some of those sensor type constants include Sensor.TYPE_ACCELEROMETER for the accelerometer. Sensor.TYPE_MAGNETIC_FIELD for the magnetic field sensor. Or Sensor.TYPE_PRESSURE for the barometer. If an application wants to receive information from a sensor, then it will have to implement a SensorEventListener. And this interface defines callback methods that are invoked when a sensor's accuracy changes and when the sensor acquires a new reading. When a sensor's accuracy changes, Android calls the onAccuracyChanged method, passing in the sensor that changed, and passing in its new accuracy. When a sensor has a new reading, the onSensorChanged method is called, passing in the SensorEvent corresponding to the new reading. Before your application can receive SensorEvents, however, it will need to register a SensorEventListener, and once it's done with the sensor, you'll also want to un-register the sensor, the SensorListener, in order to avoid wasting battery power. To register a SensorEventListener for a given sensor, you call the registerListener method, passing in the SensorEventListener that will be called back to for the sensor you want to listen to, and the rate at which you want the sensor to be polled. To unregister a listener for all sensors with which it's registered, you can, for instance, call the unregisterListener method, passing in the SensorEventListener and passing in a bitmask indicating the sensors you no longer want to listen to. Sensor readings are represented as instances of the SensorEvent class. The data this class holds will, of course, depend on the specific kind of sensor that generated the reading, but will include the sensor type, a timestamp, the accuracy of the reading, and the measurement data associated with that new reading. In order to make sense of the data, you'll need to know how measurements are interpreted for the specific sensor. For instance, many sensors use a three dimensional coordinate system. When the default orientation is portrait and when the device is lying flat, face-up on a table, the axes of the coordinate system are as shown here. The x axis runs from right to left. The y axis runs top to bottom. And the z axis runs down to up. And don't forget that the coordinate system is oriented around the device's default orientation and that doesn't change even if the device changes its current orientation. For instance, even if the device moves from portrait mode to landscape mode, the coordinate system doesn't change. Our first example for this lesson is called SensorRawAccelerometer. This application simply displays the raw values that it receives from the device's accelerometer. Let's see it in action. Now, I'll start up the SensorRawAccelerometer application. As you can see, this application displays three text views with numbers in them. And these numbers correspond to the x, y, and z values being read from this device's accelerometer. As you can see, the greatest force is now being exerted on the Y axis. While I’m doing this demonstration, I’m trying, obviously not succeeding, to hold the device perfectly straight up and down. But of course, my hand shakes a bit, and so, the numbers will dance around a bit. I'll now rotate the device counter-clockwise 90 degrees around the z-axis and you'll see that now the greatest force is being exerted on the x-axis. Let's rotate the device another 90 degrees, and now you see that, again, the greatest force is being exerted on the y-axis, but this time, that force is negative and that's because the y-axis is now upside down. And finally, I'll rotate the device another 90 degrees. And again, you'll see that the greatest force is exerted on the x-axis. And that that force is operating in the negative direction. Let's look at the source code for this application. Here's the SensorRawAccelerometer application open in the IDE. Now I'll open the main activity. Notice that this class implements the SensorEventListener interface. So we can receive callbacks from the SensorManager. Now, in onCreate, the application gets a reference to the SensorManager. Next, it gets a reference to the device's accelerometer by calling SensorManager.getDefaultSensor, passing in the type constant that corresponds to the accelerometer. In the onResume method, the application registers this class as a listener for accelerometer event by calling the registerListener method. The last parameter is SensorManager.SENSOR_DELAY_UI, and this corresponds to a relatively low frequency polling rate. Next, the onPause method unregisters this class as a listener for any and all sensors to which it may be listening. Scrolling down, we now come to the onSensorChanged method. This method first checks to make sure that this event is an accelerometer reading. Next, it checks that a certain amount of time has passed since the last reading was displayed. And if so, the code records the accelerometer's X, Y, and Z values. And then it displays those values on the screen.