1page.title=Position Sensors 2page.tags=sensorevent,orientation,proximity 3@jd:body 4 5<div id="qv-wrapper"> 6 <div id="qv"> 7 <h2>In this document</h2> 8 <ol> 9 <li><a href="#sensors-pos-gamerot">Using the Game Rotation Vector Sensor</a></li> 10 <li><a href="#sensors-pos-geomrot">Using the Geomagnetic Rotation Vector Sensor</a></li> 11 <li><a href="#sensors-pos-orient">Computing the Device's Orientation</a></li> 12 <li><a href="#sensors-pos-mag">Using the Geomagnetic Field Sensor</a></li> 13 <li><a href="#sensors-pos-prox">Using the Proximity Sensor</a></li> 14 </ol> 15 <h2>Key classes and interfaces</h2> 16 <ol> 17 <li>{@link android.hardware.Sensor}</li> 18 <li>{@link android.hardware.SensorEvent}</li> 19 <li>{@link android.hardware.SensorManager}</li> 20 <li>{@link android.hardware.SensorEventListener}</li> 21 </ol> 22 <h2>Related samples</h2> 23 <ol> 24 <li><a href="{@docRoot}resources/samples/AccelerometerPlay/index.html">Accelerometer 25 Play</a></li> 26 <li><a 27href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/os/RotationVectorDemo.html"> 28API Demos (OS - RotationVectorDemo)</a></li> 29 <li><a 30href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/os/Sensors.html">API Demos 31(OS - Sensors)</a></li> 32 </ol> 33 <h2>See also</h2> 34 <ol> 35 <li><a href="{@docRoot}guide/topics/sensors/index.html">Sensors</a></li> 36 <li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li> 37 <li><a href="{@docRoot}guide/topics/sensors/sensors_motion.html">Motion 38 Sensors</a></li> 39 <li><a href="{@docRoot}guide/topics/sensors/sensors_environment.html">Environment 40 Sensors</a></li> 41 </ol> 42 </div> 43</div> 44 45<p> 46 The Android platform provides two sensors that let you determine the position 47 of a device: the geomagnetic field sensor and the accelerometer. The Android 48 platform also provides a sensor that lets you determine how close the face of 49 a device is to an object (known as the <em>proximity sensor</em>). The 50 geomagnetic field sensor and the proximity sensor are hardware-based. Most 51 handset and tablet manufacturers include a geomagnetic field sensor. Likewise, 52 handset manufacturers usually include a proximity sensor to determine when a 53 handset is being held close to a user's face (for example, during a phone 54 call). For determining a device's orientation, you can use the readings from 55 the device's accelerometer and the geomagnetic field sensor. 56</p> 57 58<p class="note"> 59 <strong>Note:</strong> The orientation sensor was deprecated in Android 2.2 60 (API level 8), and the orientation sensor type was deprecated in Android 4.4W 61 (API level 20). 62</p> 63 64<p> 65 Position sensors are useful for determining a device's physical position in 66 the world's frame of reference. For example, you can use the geomagnetic field 67 sensor in combination with the accelerometer to determine a device's position 68 relative to the magnetic north pole. You can also use these sensors to 69 determine a device's orientation in your application's frame of reference. 70 Position sensors are not typically used to monitor device movement or motion, 71 such as shake, tilt, or thrust (for more information, see <a 72 href="{@docRoot}guide/topics/sensors/sensors_motion.html">Motion Sensors</a>). 73</p> 74 75<p> 76 The geomagnetic field sensor and accelerometer return multi-dimensional arrays 77 of sensor values for each {@link android.hardware.SensorEvent}. For example, 78 the geomagnetic field sensor provides geomagnetic field strength values for 79 each of the three coordinate axes during a single sensor event. Likewise, the 80 accelerometer sensor measures the acceleration applied to the device during a 81 sensor event. For more information about the coordinate systems that are used 82 by sensors, see <a 83 href="{@docRoot}guide/topics/sensors/sensors_overview.html#sensors-coords"> 84 Sensor Coordinate Systems</a>. The proximity sensor provides a single value 85 for each sensor event. Table 1 summarizes the position sensors that are 86 supported on the Android platform. 87</p> 88 89<p class="table-caption" id="table1"> 90 <strong>Table 1.</strong> Position sensors that are supported on the Android platform.</p> 91<table> 92 <tr> 93 <th scope="col" style="white-space:nowrap">Sensor</th> 94 <th scope="col" style="white-space:nowrap">Sensor event data</th> 95 <th scope="col" style="white-space:nowrap">Description</th> 96 <th scope="col" style="white-space:nowrap">Units of measure</th> 97 </tr> 98 <tr> 99 <td rowspan="3">{@link android.hardware.Sensor#TYPE_GAME_ROTATION_VECTOR}</td> 100 <td><code>SensorEvent.values[0]</code></td> 101 <td>Rotation vector component along the x axis (x * sin(θ/2)).</td> 102 <td rowspan="3">Unitless</td> 103 </tr> 104 <tr> 105 <td><code>SensorEvent.values[1]</code></td> 106 <td>Rotation vector component along the y axis (y * sin(θ/2)).</td> 107 </tr> 108 <tr> 109 <td><code>SensorEvent.values[2]</code></td> 110 <td>Rotation vector component along the z axis (z * sin(θ/2)).</td> 111 </tr> 112 <tr> 113 <td rowspan="3">{@link android.hardware.Sensor#TYPE_GEOMAGNETIC_ROTATION_VECTOR}</td> 114 <td><code>SensorEvent.values[0]</code></td> 115 <td>Rotation vector component along the x axis (x * sin(θ/2)).</td> 116 <td rowspan="3">Unitless</td> 117 </tr> 118 <tr> 119 <td><code>SensorEvent.values[1]</code></td> 120 <td>Rotation vector component along the y axis (y * sin(θ/2)).</td> 121 </tr> 122 <tr> 123 <td><code>SensorEvent.values[2]</code></td> 124 <td>Rotation vector component along the z axis (z * sin(θ/2)).</td> 125 </tr> 126 <tr> 127 <td rowspan="3">{@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD}</td> 128 <td><code>SensorEvent.values[0]</code></td> 129 <td>Geomagnetic field strength along the x axis.</td> 130 <td rowspan="3">μT</td> 131 </tr> 132 <tr> 133 <td><code>SensorEvent.values[1]</code></td> 134 <td>Geomagnetic field strength along the y axis.</td> 135 </tr> 136 <tr> 137 <td><code>SensorEvent.values[2]</code></td> 138 <td>Geomagnetic field strength along the z axis.</td> 139 </tr> 140 <tr> 141 <td rowspan="6">{@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD_UNCALIBRATED}</td> 142 <td><code>SensorEvent.values[0]</code></td> 143 <td>Geomagnetic field strength (without hard iron calibration) along the x axis.</td> 144 <td rowspan="6">μT</td> 145 </tr> 146 <tr> 147 <td><code>SensorEvent.values[1]</code></td> 148 <td>Geomagnetic field strength (without hard iron calibration) along the y axis.</td> 149 </tr> 150 <tr> 151 <td><code>SensorEvent.values[2]</code></td> 152 <td>Geomagnetic field strength (without hard iron calibration) along the z axis.</td> 153 </tr> 154 <tr> 155 <td><code>SensorEvent.values[3]</code></td> 156 <td>Iron bias estimation along the x axis.</td> 157 </tr> 158 <tr> 159 <td><code>SensorEvent.values[4]</code></td> 160 <td>Iron bias estimation along the y axis.</td> 161 </tr> 162 <tr> 163 <td><code>SensorEvent.values[5]</code></td> 164 <td>Iron bias estimation along the z axis.</td> 165 </tr> 166 <tr> 167 <td rowspan="3">{@link android.hardware.Sensor#TYPE_ORIENTATION}<sup>1</sup></td> 168 <td><code>SensorEvent.values[0]</code></td> 169 <td>Azimuth (angle around the z-axis).</td> 170 <td rowspan="3">Degrees</td> 171 </tr> 172 <tr> 173 <td><code>SensorEvent.values[1]</code></td> 174 <td>Pitch (angle around the x-axis).</td> 175 </tr> 176 <tr> 177 <td><code>SensorEvent.values[2]</code></td> 178 <td>Roll (angle around the y-axis).</td> 179 </tr> 180 <tr> 181 <td>{@link android.hardware.Sensor#TYPE_PROXIMITY}</td> 182 <td><code>SensorEvent.values[0]</code></td> 183 <td>Distance from object.<sup>2</sup></td> 184 <td>cm</td> 185 </tr> 186</table> 187 188<p class="note"> 189 <sup><strong>1</strong></sup>This sensor was deprecated in Android 2.2 (API 190 level 8), and this sensor type was deprecated in Android 4.4W (API level 20). 191 The sensor framework provides alternate methods for acquiring device 192 orientation, which are discussed in <a href="#sensors-pos-orient">Computing 193 the Device's Orientation</a>. 194</p> 195 196<p class="note"><sup><strong>2</strong></sup> Some proximity sensors provide only binary values 197representing near and far.</p> 198 199<h2 id="sensors-pos-gamerot">Using the Game Rotation Vector Sensor</h2> 200 201<p>The game rotation vector sensor is identical to the 202<a href="{@docRoot}guide/topics/sensors/sensors_motion.html#sensors-motion-rotate">Rotation 203Vector Sensor</a>, except it does not use the geomagnetic field. Therefore the Y axis does not 204point north but instead to some other reference. That reference is allowed to drift by the 205same order of magnitude as the gyroscope drifts around the Z axis.</p> 206 207<p>Because the game rotation vector sensor does not use the magnetic field, relative rotations 208are more accurate, and not impacted by magnetic field changes. Use this sensor in a game if 209you do not care about where north is, and the normal rotation vector does not fit your needs 210because of its reliance on the magnetic field.</p> 211 212<p>The following code shows you how to get an instance of the default game rotation vector 213sensor:</p> 214 215<pre> 216private SensorManager mSensorManager; 217private Sensor mSensor; 218... 219mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 220mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR); 221</pre> 222 223 224<h2 id="sensors-pos-geomrot">Using the Geomagnetic Rotation Vector Sensor</h2> 225 226<p>The geomagnetic rotation vector sensor is similar to the 227<a href="{@docRoot}guide/topics/sensors/sensors_motion.html#sensors-motion-rotate">Rotation 228Vector Sensor</a>, but it uses a magnetometer instead of a gyroscope. The accuracy of this 229sensor is lower than the normal rotation vector sensor, but the power consumption is reduced. 230Only use this sensor if you want to collect some rotation information in the background without 231draining too much battery. This sensor is most useful when used in conjunction with batching.</p> 232 233<p>The following code shows you how to get an instance of the default geomagnetic rotation 234vector sensor:</p> 235 236<pre> 237private SensorManager mSensorManager; 238private Sensor mSensor; 239... 240mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 241mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR); 242</pre> 243 244 245<h2 id="sensors-pos-orient">Computing the Device's Orientation</h2> 246 247<p>By computing a device's orientation, you can monitor the position of the 248 device relative to the earth's frame of reference (specifically, the magnetic 249 north pole). The following code shows you how to compute a device's 250 orientation: 251</p> 252<pre> 253private SensorManager mSensorManager; 254... 255// Rotation matrix based on current readings from accelerometer and magnetometer. 256final float[] rotationMatrix = new float[9]; 257mSensorManager.getRotationMatrix(rotationMatrix, null, 258 accelerometerReading, magnetometerReading); 259 260// Express the updated rotation matrix as three orientation angles. 261final float[] orientationAngles = new float[3]; 262mSensorManager.getOrientation(rotationMatrix, orientationAngles); 263</pre> 264<p>The system computes the orientation angles by using a device's geomagnetic 265 field sensor in combination with the device's accelerometer. Using these two 266 hardware sensors, the system provides data for the following three 267 orientation angles: 268</p> 269<ul> 270 <li> 271 <strong>Azimuth (degrees of rotation about the -z axis).</strong> This is 272 the angle between the device's current compass direction and magnetic north. 273 If the top edge of the device faces magnetic north, the azimuth is 0 274 degrees; if the top edge faces south, the azimuth is 180 degrees. Similarly, 275 if the top edge faces east, the azimuth is 90 degrees, and if the top edge 276 faces west, the azimuth is 270 degrees. 277 </li> 278 <li> 279 <strong>Pitch (degrees of rotation about the x axis).</strong> This is the 280 angle between a plane parallel to the device's screen and a plane parallel 281 to the ground. If you hold the device parallel to the ground with the bottom 282 edge closest to you and tilt the top edge of the device toward the ground, 283 the pitch angle becomes positive. Tilting in the opposite direction— 284 moving the top edge of the device away from the ground—causes 285 the pitch angle to become negative. The range of values is -180 degrees to 286 180 degrees. 287 </li> 288 <li> 289 <strong>Roll (degrees of rotation about the y axis).</strong> This is the 290 angle between a plane perpendicular to the device's screen and a plane 291 perpendicular to the ground. If you hold the device parallel to the ground 292 with the bottom edge closest to you and tilt the left edge of the device 293 toward the ground, the roll angle becomes positive. Tilting in the opposite 294 direction—moving the right edge of the device toward the ground— 295 causes the roll angle to become negative. The range of values is -90 degrees 296 to 90 degrees. 297 </li> 298</ul> 299 300<p class="note"> 301 <strong>Note:</strong>The sensor's roll definition has changed to reflect the 302 vast majority of implementations in the geosensor ecosystem. 303</p> 304 305<p> 306 Note that these angles work off of a different coordinate system than the 307 one used in aviation (for yaw, pitch, and roll). In the aviation system, the 308 x axis is along the long side of the plane, from tail to nose. 309</p> 310 311<p> 312 The orientation sensor derives its data by processing the raw sensor data 313 from the accelerometer and the geomagnetic field sensor. Because of the heavy 314 processing that is involved, the accuracy and precision of the orientation 315 sensor is diminished. Specifically, this sensor is reliable only when the roll 316 angle is 0. As a result, the orientation sensor was deprecated in Android 317 2.2 (API level 8), and the orientation sensor type was deprecated in Android 318 4.4W (API level 20). 319 320 Instead of using raw data from the orientation sensor, we recommend that you 321 use the {@link android.hardware.SensorManager#getRotationMatrix getRotationMatrix()} 322 method in conjunction with the 323 {@link android.hardware.SensorManager#getOrientation getOrientation()} method 324 to compute orientation values, as shown in the following code sample. As part 325 of this process, you can use the 326 {@link android.hardware.SensorManager#remapCoordinateSystem remapCoordinateSystem()} 327 method to translate the orientation values to your application's frame of 328 reference. 329</p> 330<pre> 331public class SensorActivity extends Activity implements SensorEventListener { 332 333 private SensorManager mSensorManager; 334 private final float[] mAccelerometerReading = new float[3]; 335 private final float[] mMagnetometerReading = new float[3]; 336 337 private final float[] mRotationMatrix = new float[9]; 338 private final float[] mOrientationAngles = new float[3]; 339 340 @Override 341 public void onCreate(Bundle savedInstanceState) { 342 super.onCreate(savedInstanceState); 343 setContentView(R.layout.main); 344 mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 345 } 346 347 @Override 348 public void onAccuracyChanged(Sensor sensor, int accuracy) { 349 // Do something here if sensor accuracy changes. 350 // You must implement this callback in your code. 351 } 352 353 @Override 354 protected void onResume() { 355 super.onResume(); 356 357 // Get updates from the accelerometer and magnetometer at a constant rate. 358 // To make batch operations more efficient and reduce power consumption, 359 // provide support for delaying updates to the application. 360 // 361 // In this example, the sensor reporting delay is small enough such that 362 // the application receives an update before the system checks the sensor 363 // readings again. 364 mSensorManager.registerListener(this, Sensor.TYPE_ACCELEROMETER, 365 SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI); 366 mSensorManager.registerListener(this, Sensor.TYPE_MAGNETIC_FIELD, 367 SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI); 368 } 369 370 @Override 371 protected void onPause() { 372 super.onPause(); 373 374 // Don't receive any more updates from either sensor. 375 mSensorManager.unregisterListener(this); 376 } 377 378 // Get readings from accelerometer and magnetometer. To simplify calculations, 379 // consider storing these readings as unit vectors. 380 @Override 381 public void onSensorChanged(SensorEvent event) { 382 if (event.sensor == Sensor.TYPE_ACCELEROMETER) { 383 System.arraycopy(event.values, 0, mAccelerometerReading, 384 0, mAccelerometerReading.length); 385 } 386 else if (event.sensor == Sensor.TYPE_MAGNETIC_FIELD) { 387 System.arraycopy(event.values, 0, mMagnetometerReading, 388 0, mMagnetometerReading.length); 389 } 390 } 391 392 // Compute the three orientation angles based on the most recent readings from 393 // the device's accelerometer and magnetometer. 394 public void updateOrientationAngles() { 395 // Update rotation matrix, which is needed to update orientation angles. 396 mSensorManager.getRotationMatrix(mRotationMatrix, null, 397 mAccelerometerReading, mMagnetometerReading); 398 399 // "mRotationMatrix" now has up-to-date information. 400 401 mSensorManager.getOrientation(mRotationMatrix, mOrientationAngles); 402 403 // "mOrientationAngles" now has up-to-date information. 404 } 405} 406</pre> 407 408<p> 409 You don't usually need to perform any data processing or filtering of the 410 device's raw orientation angles other than translating the sensor's 411 coordinate system to your application's frame of reference. 412</p> 413 414<h2 id="sensors-pos-mag">Using the Geomagnetic Field Sensor</h2> 415 416<p>The geomagnetic field sensor lets you monitor changes in the earth's magnetic field. The 417following code shows you how to get an instance of the default geomagnetic field sensor:</p> 418 419<pre> 420private SensorManager mSensorManager; 421private Sensor mSensor; 422... 423mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 424mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); 425</pre> 426 427<p>This sensor provides raw field strength data (in μT) for each of the three coordinate axes. 428Usually, you do not need to use this sensor directly. Instead, you can use the rotation vector 429sensor to determine raw rotational movement or you can use the accelerometer and geomagnetic field 430sensor in conjunction with the {@link android.hardware.SensorManager#getRotationMatrix 431getRotationMatrix()} method to obtain the rotation matrix and the inclination matrix. You can then 432use these matrices with the {@link android.hardware.SensorManager#getOrientation getOrientation()} 433and {@link android.hardware.SensorManager#getInclination getInclination()} methods to obtain azimuth 434and geomagnetic inclination data.</p> 435 436<h2 id="sensors-pos-magunc">Using the Uncalibrated Magnetometer</h2> 437 438<p>The uncalibrated magnetometer is similar to the <a href="#sensors-pos-mag">geomagnetic field 439sensor</a>, except that no hard iron calibration is applied to the magnetic field. Factory calibration 440and temperature compensation are still applied to the magnetic field. The uncalibrated magnetometer 441is useful to handle bad hard iron estimations. In general, <code>geomagneticsensor_event.values[0]</code> 442will be close to <code>uncalibrated_magnetometer_event.values[0] - 443uncalibrated_magnetometer_event.values[3]</code>. That is,</p> 444 445<p><code>calibrated_x ~= uncalibrated_x - bias_estimate_x</code></p></p> 446 447<p class="note"><strong>Note:</strong> Uncalibrated sensors provide more raw results and may 448include some bias, but their measurements contain fewer jumps from corrections applied through 449calibration. Some applications may prefer these uncalibrated results as smoother and more 450reliable. For instance, if an application is attempting to conduct its own sensor fusion, 451introducing calibrations can actually distort results.</p> 452 453<p>In addition to the magnetic field, the uncalibrated magnetometer also provides the 454estimated hard iron bias in each axis. The following code shows you how to get an instance of the 455default uncalibrated magnetometer:</p> 456 457<pre> 458private SensorManager mSensorManager; 459private Sensor mSensor; 460... 461mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 462mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED); 463</pre> 464 465<h2 id="sensors-pos-prox">Using the Proximity Sensor</h2> 466<p>The proximity sensor lets you determine how far away an object is from a device. The following 467code shows you how to get an instance of the default proximity sensor:</p> 468 469<pre> 470private SensorManager mSensorManager; 471private Sensor mSensor; 472... 473mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 474mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); 475</pre> 476 477<p>The proximity sensor is usually used to determine how far away a person's head is from the face 478of a handset device (for example, when a user is making or receiving a phone call). Most 479proximity sensors return the absolute distance, in cm, but some return only near and 480far values. The following code shows you how to use the proximity sensor:</p> 481 482<pre> 483public class SensorActivity extends Activity implements SensorEventListener { 484 private SensorManager mSensorManager; 485 private Sensor mProximity; 486 487 @Override 488 public final void onCreate(Bundle savedInstanceState) { 489 super.onCreate(savedInstanceState); 490 setContentView(R.layout.main); 491 492 // Get an instance of the sensor service, and use that to get an instance of 493 // a particular sensor. 494 mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 495 mProximity = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); 496 } 497 498 @Override 499 public final void onAccuracyChanged(Sensor sensor, int accuracy) { 500 // Do something here if sensor accuracy changes. 501 } 502 503 @Override 504 public final void onSensorChanged(SensorEvent event) { 505 float distance = event.values[0]; 506 // Do something with this sensor data. 507 } 508 509 @Override 510 protected void onResume() { 511 // Register a listener for the sensor. 512 super.onResume(); 513 mSensorManager.registerListener(this, mProximity, SensorManager.SENSOR_DELAY_NORMAL); 514 } 515 516 @Override 517 protected void onPause() { 518 // Be sure to unregister the sensor when the activity pauses. 519 super.onPause(); 520 mSensorManager.unregisterListener(this); 521 } 522} 523</pre> 524 525<p class="note"><strong>Note:</strong> Some proximity sensors return binary values that represent 526"near" or "far." In this case, the sensor usually reports its maximum range value in the far state 527and a lesser value in the near state. Typically, the far value is a value > 5 cm, but this can vary 528from sensor to sensor. You can determine a sensor's maximum range by using the {@link 529android.hardware.Sensor#getMaximumRange} method.</p> 530