| page.title=Position Sensors |
| page.tags=sensorevent,orientation,proximity |
| @jd:body |
| |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| <h2>In this document</h2> |
| <ol> |
| <li><a href="#sensors-pos-gamerot">Using the Game Rotation Vector Sensor</a></li> |
| <li><a href="#sensors-pos-geomrot">Using the Geomagnetic Rotation Vector Sensor</a></li> |
| <li><a href="#sensors-pos-orient">Computing the Device's Orientation</a></li> |
| <li><a href="#sensors-pos-mag">Using the Geomagnetic Field Sensor</a></li> |
| <li><a href="#sensors-pos-prox">Using the Proximity Sensor</a></li> |
| </ol> |
| <h2>Key classes and interfaces</h2> |
| <ol> |
| <li>{@link android.hardware.Sensor}</li> |
| <li>{@link android.hardware.SensorEvent}</li> |
| <li>{@link android.hardware.SensorManager}</li> |
| <li>{@link android.hardware.SensorEventListener}</li> |
| </ol> |
| <h2>Related samples</h2> |
| <ol> |
| <li><a href="{@docRoot}resources/samples/AccelerometerPlay/index.html">Accelerometer |
| Play</a></li> |
| <li><a |
| href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/os/RotationVectorDemo.html"> |
| API Demos (OS - RotationVectorDemo)</a></li> |
| <li><a |
| href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/os/Sensors.html">API Demos |
| (OS - Sensors)</a></li> |
| </ol> |
| <h2>See also</h2> |
| <ol> |
| <li><a href="{@docRoot}guide/topics/sensors/index.html">Sensors</a></li> |
| <li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li> |
| <li><a href="{@docRoot}guide/topics/sensors/sensors_motion.html">Motion |
| Sensors</a></li> |
| <li><a href="{@docRoot}guide/topics/sensors/sensors_environment.html">Environment |
| Sensors</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p> |
| The Android platform provides two sensors that let you determine the position |
| of a device: the geomagnetic field sensor and the accelerometer. The Android |
| platform also provides a sensor that lets you determine how close the face of |
| a device is to an object (known as the <em>proximity sensor</em>). The |
| geomagnetic field sensor and the proximity sensor are hardware-based. Most |
| handset and tablet manufacturers include a geomagnetic field sensor. Likewise, |
| handset manufacturers usually include a proximity sensor to determine when a |
| handset is being held close to a user's face (for example, during a phone |
| call). For determining a device's orientation, you can use the readings from |
| the device's accelerometer and the geomagnetic field sensor. |
| </p> |
| |
| <p class="note"> |
| <strong>Note:</strong> The orientation sensor was deprecated in Android 2.2 |
| (API level 8), and the orientation sensor type was deprecated in Android 4.4W |
| (API level 20). |
| </p> |
| |
| <p> |
| Position sensors are useful for determining a device's physical position in |
| the world's frame of reference. For example, you can use the geomagnetic field |
| sensor in combination with the accelerometer to determine a device's position |
| relative to the magnetic north pole. You can also use these sensors to |
| determine a device's orientation in your application's frame of reference. |
| Position sensors are not typically used to monitor device movement or motion, |
| such as shake, tilt, or thrust (for more information, see <a |
| href="{@docRoot}guide/topics/sensors/sensors_motion.html">Motion Sensors</a>). |
| </p> |
| |
| <p> |
| The geomagnetic field sensor and accelerometer return multi-dimensional arrays |
| of sensor values for each {@link android.hardware.SensorEvent}. For example, |
| the geomagnetic field sensor provides geomagnetic field strength values for |
| each of the three coordinate axes during a single sensor event. Likewise, the |
| accelerometer sensor measures the acceleration applied to the device during a |
| sensor event. For more information about the coordinate systems that are used |
| by sensors, see <a |
| href="{@docRoot}guide/topics/sensors/sensors_overview.html#sensors-coords"> |
| Sensor Coordinate Systems</a>. The proximity sensor provides a single value |
| for each sensor event. Table 1 summarizes the position sensors that are |
| supported on the Android platform. |
| </p> |
| |
| <p class="table-caption" id="table1"> |
| <strong>Table 1.</strong> Position sensors that are supported on the Android platform.</p> |
| <table> |
| <tr> |
| <th scope="col" style="white-space:nowrap">Sensor</th> |
| <th scope="col" style="white-space:nowrap">Sensor event data</th> |
| <th scope="col" style="white-space:nowrap">Description</th> |
| <th scope="col" style="white-space:nowrap">Units of measure</th> |
| </tr> |
| <tr> |
| <td rowspan="3">{@link android.hardware.Sensor#TYPE_GAME_ROTATION_VECTOR}</td> |
| <td><code>SensorEvent.values[0]</code></td> |
| <td>Rotation vector component along the x axis (x * sin(θ/2)).</td> |
| <td rowspan="3">Unitless</td> |
| </tr> |
| <tr> |
| <td><code>SensorEvent.values[1]</code></td> |
| <td>Rotation vector component along the y axis (y * sin(θ/2)).</td> |
| </tr> |
| <tr> |
| <td><code>SensorEvent.values[2]</code></td> |
| <td>Rotation vector component along the z axis (z * sin(θ/2)).</td> |
| </tr> |
| <tr> |
| <td rowspan="3">{@link android.hardware.Sensor#TYPE_GEOMAGNETIC_ROTATION_VECTOR}</td> |
| <td><code>SensorEvent.values[0]</code></td> |
| <td>Rotation vector component along the x axis (x * sin(θ/2)).</td> |
| <td rowspan="3">Unitless</td> |
| </tr> |
| <tr> |
| <td><code>SensorEvent.values[1]</code></td> |
| <td>Rotation vector component along the y axis (y * sin(θ/2)).</td> |
| </tr> |
| <tr> |
| <td><code>SensorEvent.values[2]</code></td> |
| <td>Rotation vector component along the z axis (z * sin(θ/2)).</td> |
| </tr> |
| <tr> |
| <td rowspan="3">{@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD}</td> |
| <td><code>SensorEvent.values[0]</code></td> |
| <td>Geomagnetic field strength along the x axis.</td> |
| <td rowspan="3">μT</td> |
| </tr> |
| <tr> |
| <td><code>SensorEvent.values[1]</code></td> |
| <td>Geomagnetic field strength along the y axis.</td> |
| </tr> |
| <tr> |
| <td><code>SensorEvent.values[2]</code></td> |
| <td>Geomagnetic field strength along the z axis.</td> |
| </tr> |
| <tr> |
| <td rowspan="6">{@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD_UNCALIBRATED}</td> |
| <td><code>SensorEvent.values[0]</code></td> |
| <td>Geomagnetic field strength (without hard iron calibration) along the x axis.</td> |
| <td rowspan="6">μT</td> |
| </tr> |
| <tr> |
| <td><code>SensorEvent.values[1]</code></td> |
| <td>Geomagnetic field strength (without hard iron calibration) along the y axis.</td> |
| </tr> |
| <tr> |
| <td><code>SensorEvent.values[2]</code></td> |
| <td>Geomagnetic field strength (without hard iron calibration) along the z axis.</td> |
| </tr> |
| <tr> |
| <td><code>SensorEvent.values[3]</code></td> |
| <td>Iron bias estimation along the x axis.</td> |
| </tr> |
| <tr> |
| <td><code>SensorEvent.values[4]</code></td> |
| <td>Iron bias estimation along the y axis.</td> |
| </tr> |
| <tr> |
| <td><code>SensorEvent.values[5]</code></td> |
| <td>Iron bias estimation along the z axis.</td> |
| </tr> |
| <tr> |
| <td rowspan="3">{@link android.hardware.Sensor#TYPE_ORIENTATION}<sup>1</sup></td> |
| <td><code>SensorEvent.values[0]</code></td> |
| <td>Azimuth (angle around the z-axis).</td> |
| <td rowspan="3">Degrees</td> |
| </tr> |
| <tr> |
| <td><code>SensorEvent.values[1]</code></td> |
| <td>Pitch (angle around the x-axis).</td> |
| </tr> |
| <tr> |
| <td><code>SensorEvent.values[2]</code></td> |
| <td>Roll (angle around the y-axis).</td> |
| </tr> |
| <tr> |
| <td>{@link android.hardware.Sensor#TYPE_PROXIMITY}</td> |
| <td><code>SensorEvent.values[0]</code></td> |
| <td>Distance from object.<sup>2</sup></td> |
| <td>cm</td> |
| </tr> |
| </table> |
| |
| <p class="note"> |
| <sup><strong>1</strong></sup>This sensor was deprecated in Android 2.2 (API |
| level 8), and this sensor type was deprecated in Android 4.4W (API level 20). |
| The sensor framework provides alternate methods for acquiring device |
| orientation, which are discussed in <a href="#sensors-pos-orient">Computing |
| the Device's Orientation</a>. |
| </p> |
| |
| <p class="note"><sup><strong>2</strong></sup> Some proximity sensors provide only binary values |
| representing near and far.</p> |
| |
| <h2 id="sensors-pos-gamerot">Using the Game Rotation Vector Sensor</h2> |
| |
| <p>The game rotation vector sensor is identical to the |
| <a href="{@docRoot}guide/topics/sensors/sensors_motion.html#sensors-motion-rotate">Rotation |
| Vector Sensor</a>, except it does not use the geomagnetic field. Therefore the Y axis does not |
| point north but instead to some other reference. That reference is allowed to drift by the |
| same order of magnitude as the gyroscope drifts around the Z axis.</p> |
| |
| <p>Because the game rotation vector sensor does not use the magnetic field, relative rotations |
| are more accurate, and not impacted by magnetic field changes. Use this sensor in a game if |
| you do not care about where north is, and the normal rotation vector does not fit your needs |
| because of its reliance on the magnetic field.</p> |
| |
| <p>The following code shows you how to get an instance of the default game rotation vector |
| sensor:</p> |
| |
| <pre> |
| private SensorManager mSensorManager; |
| private Sensor mSensor; |
| ... |
| mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); |
| mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR); |
| </pre> |
| |
| |
| <h2 id="sensors-pos-geomrot">Using the Geomagnetic Rotation Vector Sensor</h2> |
| |
| <p>The geomagnetic rotation vector sensor is similar to the |
| <a href="{@docRoot}guide/topics/sensors/sensors_motion.html#sensors-motion-rotate">Rotation |
| Vector Sensor</a>, but it uses a magnetometer instead of a gyroscope. The accuracy of this |
| sensor is lower than the normal rotation vector sensor, but the power consumption is reduced. |
| Only use this sensor if you want to collect some rotation information in the background without |
| draining too much battery. This sensor is most useful when used in conjunction with batching.</p> |
| |
| <p>The following code shows you how to get an instance of the default geomagnetic rotation |
| vector sensor:</p> |
| |
| <pre> |
| private SensorManager mSensorManager; |
| private Sensor mSensor; |
| ... |
| mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); |
| mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR); |
| </pre> |
| |
| |
| <h2 id="sensors-pos-orient">Computing the Device's Orientation</h2> |
| |
| <p>By computing a device's orientation, you can monitor the position of the |
| device relative to the earth's frame of reference (specifically, the magnetic |
| north pole). The following code shows you how to compute a device's |
| orientation: |
| </p> |
| <pre> |
| private SensorManager mSensorManager; |
| ... |
| // Rotation matrix based on current readings from accelerometer and magnetometer. |
| final float[] rotationMatrix = new float[9]; |
| mSensorManager.getRotationMatrix(rotationMatrix, null, |
| accelerometerReading, magnetometerReading); |
| |
| // Express the updated rotation matrix as three orientation angles. |
| final float[] orientationAngles = new float[3]; |
| mSensorManager.getOrientation(rotationMatrix, orientationAngles); |
| </pre> |
| <p>The system computes the orientation angles by using a device's geomagnetic |
| field sensor in combination with the device's accelerometer. Using these two |
| hardware sensors, the system provides data for the following three |
| orientation angles: |
| </p> |
| <ul> |
| <li> |
| <strong>Azimuth (degrees of rotation about the -z axis).</strong> This is |
| the angle between the device's current compass direction and magnetic north. |
| If the top edge of the device faces magnetic north, the azimuth is 0 |
| degrees; if the top edge faces south, the azimuth is 180 degrees. Similarly, |
| if the top edge faces east, the azimuth is 90 degrees, and if the top edge |
| faces west, the azimuth is 270 degrees. |
| </li> |
| <li> |
| <strong>Pitch (degrees of rotation about the x axis).</strong> This is the |
| angle between a plane parallel to the device's screen and a plane parallel |
| to the ground. If you hold the device parallel to the ground with the bottom |
| edge closest to you and tilt the top edge of the device toward the ground, |
| the pitch angle becomes positive. Tilting in the opposite direction— |
| moving the top edge of the device away from the ground—causes |
| the pitch angle to become negative. The range of values is -180 degrees to |
| 180 degrees. |
| </li> |
| <li> |
| <strong>Roll (degrees of rotation about the y axis).</strong> This is the |
| angle between a plane perpendicular to the device's screen and a plane |
| perpendicular to the ground. If you hold the device parallel to the ground |
| with the bottom edge closest to you and tilt the left edge of the device |
| toward the ground, the roll angle becomes positive. Tilting in the opposite |
| direction—moving the right edge of the device toward the ground— |
| causes the roll angle to become negative. The range of values is -90 degrees |
| to 90 degrees. |
| </li> |
| </ul> |
| |
| <p class="note"> |
| <strong>Note:</strong>The sensor's roll definition has changed to reflect the |
| vast majority of implementations in the geosensor ecosystem. |
| </p> |
| |
| <p> |
| Note that these angles work off of a different coordinate system than the |
| one used in aviation (for yaw, pitch, and roll). In the aviation system, the |
| x axis is along the long side of the plane, from tail to nose. |
| </p> |
| |
| <p> |
| The orientation sensor derives its data by processing the raw sensor data |
| from the accelerometer and the geomagnetic field sensor. Because of the heavy |
| processing that is involved, the accuracy and precision of the orientation |
| sensor is diminished. Specifically, this sensor is reliable only when the roll |
| angle is 0. As a result, the orientation sensor was deprecated in Android |
| 2.2 (API level 8), and the orientation sensor type was deprecated in Android |
| 4.4W (API level 20). |
| |
| Instead of using raw data from the orientation sensor, we recommend that you |
| use the {@link android.hardware.SensorManager#getRotationMatrix getRotationMatrix()} |
| method in conjunction with the |
| {@link android.hardware.SensorManager#getOrientation getOrientation()} method |
| to compute orientation values, as shown in the following code sample. As part |
| of this process, you can use the |
| {@link android.hardware.SensorManager#remapCoordinateSystem remapCoordinateSystem()} |
| method to translate the orientation values to your application's frame of |
| reference. |
| </p> |
| <pre> |
| public class SensorActivity extends Activity implements SensorEventListener { |
| |
| private SensorManager mSensorManager; |
| private final float[] mAccelerometerReading = new float[3]; |
| private final float[] mMagnetometerReading = new float[3]; |
| |
| private final float[] mRotationMatrix = new float[9]; |
| private final float[] mOrientationAngles = new float[3]; |
| |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| setContentView(R.layout.main); |
| mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); |
| } |
| |
| @Override |
| public void onAccuracyChanged(Sensor sensor, int accuracy) { |
| // Do something here if sensor accuracy changes. |
| // You must implement this callback in your code. |
| } |
| |
| @Override |
| protected void onResume() { |
| super.onResume(); |
| |
| // Get updates from the accelerometer and magnetometer at a constant rate. |
| // To make batch operations more efficient and reduce power consumption, |
| // provide support for delaying updates to the application. |
| // |
| // In this example, the sensor reporting delay is small enough such that |
| // the application receives an update before the system checks the sensor |
| // readings again. |
| mSensorManager.registerListener(this, Sensor.TYPE_ACCELEROMETER, |
| SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI); |
| mSensorManager.registerListener(this, Sensor.TYPE_MAGNETIC_FIELD, |
| SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI); |
| } |
| |
| @Override |
| protected void onPause() { |
| super.onPause(); |
| |
| // Don't receive any more updates from either sensor. |
| mSensorManager.unregisterListener(this); |
| } |
| |
| // Get readings from accelerometer and magnetometer. To simplify calculations, |
| // consider storing these readings as unit vectors. |
| @Override |
| public void onSensorChanged(SensorEvent event) { |
| if (event.sensor == Sensor.TYPE_ACCELEROMETER) { |
| System.arraycopy(event.values, 0, mAccelerometerReading, |
| 0, mAccelerometerReading.length); |
| } |
| else if (event.sensor == Sensor.TYPE_MAGNETIC_FIELD) { |
| System.arraycopy(event.values, 0, mMagnetometerReading, |
| 0, mMagnetometerReading.length); |
| } |
| } |
| |
| // Compute the three orientation angles based on the most recent readings from |
| // the device's accelerometer and magnetometer. |
| public void updateOrientationAngles() { |
| // Update rotation matrix, which is needed to update orientation angles. |
| mSensorManager.getRotationMatrix(mRotationMatrix, null, |
| mAccelerometerReading, mMagnetometerReading); |
| |
| // "mRotationMatrix" now has up-to-date information. |
| |
| mSensorManager.getOrientation(mRotationMatrix, mOrientationAngles); |
| |
| // "mOrientationAngles" now has up-to-date information. |
| } |
| } |
| </pre> |
| |
| <p> |
| You don't usually need to perform any data processing or filtering of the |
| device's raw orientation angles other than translating the sensor's |
| coordinate system to your application's frame of reference. |
| </p> |
| |
| <h2 id="sensors-pos-mag">Using the Geomagnetic Field Sensor</h2> |
| |
| <p>The geomagnetic field sensor lets you monitor changes in the earth's magnetic field. The |
| following code shows you how to get an instance of the default geomagnetic field sensor:</p> |
| |
| <pre> |
| private SensorManager mSensorManager; |
| private Sensor mSensor; |
| ... |
| mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); |
| mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); |
| </pre> |
| |
| <p>This sensor provides raw field strength data (in μT) for each of the three coordinate axes. |
| Usually, you do not need to use this sensor directly. Instead, you can use the rotation vector |
| sensor to determine raw rotational movement or you can use the accelerometer and geomagnetic field |
| sensor in conjunction with the {@link android.hardware.SensorManager#getRotationMatrix |
| getRotationMatrix()} method to obtain the rotation matrix and the inclination matrix. You can then |
| use these matrices with the {@link android.hardware.SensorManager#getOrientation getOrientation()} |
| and {@link android.hardware.SensorManager#getInclination getInclination()} methods to obtain azimuth |
| and geomagnetic inclination data.</p> |
| |
| <h2 id="sensors-pos-magunc">Using the Uncalibrated Magnetometer</h2> |
| |
| <p>The uncalibrated magnetometer is similar to the <a href="#sensors-pos-mag">geomagnetic field |
| sensor</a>, except that no hard iron calibration is applied to the magnetic field. Factory calibration |
| and temperature compensation are still applied to the magnetic field. The uncalibrated magnetometer |
| is useful to handle bad hard iron estimations. In general, <code>geomagneticsensor_event.values[0]</code> |
| will be close to <code>uncalibrated_magnetometer_event.values[0] - |
| uncalibrated_magnetometer_event.values[3]</code>. That is,</p> |
| |
| <p><code>calibrated_x ~= uncalibrated_x - bias_estimate_x</code></p></p> |
| |
| <p class="note"><strong>Note:</strong> Uncalibrated sensors provide more raw results and may |
| include some bias, but their measurements contain fewer jumps from corrections applied through |
| calibration. Some applications may prefer these uncalibrated results as smoother and more |
| reliable. For instance, if an application is attempting to conduct its own sensor fusion, |
| introducing calibrations can actually distort results.</p> |
| |
| <p>In addition to the magnetic field, the uncalibrated magnetometer also provides the |
| estimated hard iron bias in each axis. The following code shows you how to get an instance of the |
| default uncalibrated magnetometer:</p> |
| |
| <pre> |
| private SensorManager mSensorManager; |
| private Sensor mSensor; |
| ... |
| mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); |
| mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED); |
| </pre> |
| |
| <h2 id="sensors-pos-prox">Using the Proximity Sensor</h2> |
| <p>The proximity sensor lets you determine how far away an object is from a device. The following |
| code shows you how to get an instance of the default proximity sensor:</p> |
| |
| <pre> |
| private SensorManager mSensorManager; |
| private Sensor mSensor; |
| ... |
| mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); |
| mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); |
| </pre> |
| |
| <p>The proximity sensor is usually used to determine how far away a person's head is from the face |
| of a handset device (for example, when a user is making or receiving a phone call). Most |
| proximity sensors return the absolute distance, in cm, but some return only near and |
| far values. The following code shows you how to use the proximity sensor:</p> |
| |
| <pre> |
| public class SensorActivity extends Activity implements SensorEventListener { |
| private SensorManager mSensorManager; |
| private Sensor mProximity; |
| |
| @Override |
| public final void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| setContentView(R.layout.main); |
| |
| // Get an instance of the sensor service, and use that to get an instance of |
| // a particular sensor. |
| mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); |
| mProximity = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); |
| } |
| |
| @Override |
| public final void onAccuracyChanged(Sensor sensor, int accuracy) { |
| // Do something here if sensor accuracy changes. |
| } |
| |
| @Override |
| public final void onSensorChanged(SensorEvent event) { |
| float distance = event.values[0]; |
| // Do something with this sensor data. |
| } |
| |
| @Override |
| protected void onResume() { |
| // Register a listener for the sensor. |
| super.onResume(); |
| mSensorManager.registerListener(this, mProximity, SensorManager.SENSOR_DELAY_NORMAL); |
| } |
| |
| @Override |
| protected void onPause() { |
| // Be sure to unregister the sensor when the activity pauses. |
| super.onPause(); |
| mSensorManager.unregisterListener(this); |
| } |
| } |
| </pre> |
| |
| <p class="note"><strong>Note:</strong> Some proximity sensors return binary values that represent |
| "near" or "far." In this case, the sensor usually reports its maximum range value in the far state |
| and a lesser value in the near state. Typically, the far value is a value > 5 cm, but this can vary |
| from sensor to sensor. You can determine a sensor's maximum range by using the {@link |
| android.hardware.Sensor#getMaximumRange} method.</p> |