Desarrollo en Android: acelerómetro, magnetómetro y sensores de orientación y temperatura en el HTC Magic
Android permite acceder a los sensores internos del dispositivo a través de las clases Sensor, SensorEvent y SensorManager, y de la interfaz SensorEventListener, del paquete android.hardware.
La clase Sensor acepta ocho tipos de sensores, como se puede ver en la referencia. Los sensores disponibles varían en función del aparato utilizado.
Listar los sensores del dispositivo
Para ver de qué sensores dispone nuestro dispositivo usamos la clase SensorManager:
1: // Solicitamos al sistema el servicio que gestiona los sensores
2: SensorManager mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
3: // Peimos la lista con todos los sensores disponibles
4: List<Sensor> listSensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
5: // Iteramos y mostramos
6: for(Sensor sensor:listSensors)
7: {
8: Log.i("SENSOR", sensor.getName());
9: }
La nueva versión de la SDK marca como obsoleto (deprecated) el método getSensors de la clase SensorManager, así como la interfaz SensorListener. Aunque los métodos antiguos son necesarios para versiones anteriores de la SDK, los ejemplos de este artículos se basan en la última versión.
Los sensores del HTC Magic
Esta es una lista de los valores devueltos por el código anterior ejecutándose en el HTC Magic:
- AK8976A 3-axis Accelerometer
- AK8976A 3-axis Magnetic field sensor
- AK8976A Orientation sensor
- AK8976A Temperature sensor
El AK8976A (arriba a la izquierda en esta figura, que muestra el hardware del HTC Dream) es una combinación de acelerómetro de tres ejes y magnetómetro de tres ejes. Combinando la lectura de los campos gravitatorio y magnético terrestres proporciona también información de orientación. Incluye además un sensor interno de temperatura, útil para comprobar si el móvil se está calentado demasiado.
Acceso a los datos del sensor
Para tener acceso a los datos del sensor debemos indicárselo al SensorManager con el método registerListener:
1: public class MiActividad extends Activity {
2: MiVista mVista; // Clase que implemente SensorEventListener
3: // ...
4:
5:
6: @Override
7: protected void onCreate(Bundle savedInstanceState) {
8: super.onCreate(savedInstanceState);
9:
10: // En esta clase recibiré los eventos y usaré el resultado para lo que quiera
11: mVista = new MiVista(this);
12: SensorManager mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
13:
14: // Cada sensor se registra por separado
15: List<Sensor> listSensors = mSensorManager.getSensorList(Sensor.TYPE_MAGNETIC_FIELD);
16: Sensor orientationSensor = listSensors.get(0);
17: mSensorManager.registerListener(mTop, orientationSensor, SensorManager.SENSOR_DELAY_UI);
18:
19: listSensors = mSensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
20: Sensor acelerometerSensor = listSensors.get(0);
21: mSensorManager.registerListener(mTop, acelerometerSensor, SensorManager.SENSOR_DELAY_UI);
22:
23: listSensors = mSensorManager.getSensorList(Sensor.TYPE_MAGNETIC_FIELD);
24: Sensor magneticSensor = listSensors.get(0);
25: mSensorManager.registerListener(mTop, magneticSensor, SensorManager.SENSOR_DELAY_UI);
26:
27: listSensors = mSensorManager.getSensorList(Sensor.TYPE_TEMPERATURE);
28: Sensor temperatureSensor = listSensors.get(0);
29: mSensorManager.registerListener(mTop, temperatureSensor, SensorManager.SENSOR_DELAY_UI);
30: ...
31: }
32: ...
33: }
34:
35: class MiVista extends View implements SensorEventListener {
36: ...
37: }
Es necesario registrar cada tipo de sensor por separado para poder obtener información de todos ellos. El método registerListener toma como primer parámetro la instancia de la clase que implementa el SensorEventListener, y que veremos a continuación. El tercer parámetro acepta cuatro posibles valores, que indican al sistema con qué frecuencia nos gustaría recibir actualizaciones del sensor. Esta indicación sirve para que el sistema estime cuánta atención necesitan los sensores, pero no garantiza una frecuencia concreta.
Obtención de datos
Para recibir los datos tenemos que implementar dos métodos de SensorEventListener:
1: class MiVista extends View implements SensorEventListener {
2: private float mOrientationValues[] = new float[3];
3: private float mAccelerometerValues[] = new float[3];
4: private float mMagneticValues[] = new float[3];
5: private float mTemperatureValues;
6:
7: /*
8: * El resto del código de la clase para mostrar los datos
9: */
10:
11: // En este ejemplo no necesitamos enterarnos de las variaciones de
12: // precisión del sensor
13: @Override
14: public void onAccuracyChanged(Sensor sensor, int accuracy) {
15: // TODO Auto-generated method stub
16:
17: }
18:
19: @Override
20: public void onSensorChanged(SensorEvent event) {
21: // Cada sensor puede provocar que un thread pase por aquí, así
22: // que sincronizamos el acceso
23: synchronized (this) {
24: switch(event.sensor.getType()) {
25: case Sensor.TYPE_ORIENTATION:
26: for (int i=0 ; i<3 ; i++) {
27: mOrientationValues[i] = event.values[i];
28: }
29: break;
30: case Sensor.TYPE_ACCELEROMETER:
31: for (int i=0 ; i<3 ; i++) {
32: mAccelerometerValues[i] = event.values[i];
33: }
34: break;
35: case Sensor.TYPE_MAGNETIC_FIELD:
36: for (int i=0 ; i<3 ; i++) {
37: mMagneticValues[i] = event.values[i];
38: }
39: break;
40: default:
41: for (int i=0 ; i<event.values.length ; i++) {
42: mTemperatureValues = event.values[i];
43: }
44: }
45:
46: invalidate();
47: }
48: }
49: }
Cuando el evento se dispara en el método onSensorChanged comprobamos qué sensor lo ha causado y leemos los datos. Los posibles valores devueltos se indican en la documentación de la clase SensorEvent.
La clase SensorManager tiene además tres métodos (getInclination, getOrientation y getRotationMatrix), usados para calcular transformaciones de coordenadas. De ellos hablaremos en un próximo artículo.

[...] a los datos de los sensores, haremos que implemente también SensorEventListener (como veíamos en esta entrada), para tener los datos en la misma [...]
Realidad aumentada en Android: AR Compass – II « Bitácora de Javier Cancela
10 de agosto de 2009 a 7:06
Javier, estaba revisando tu log, ya que, ahora cambiaron las formas de obtener los valores de los sensores, me preguntaba si podrias compartir tu código para seguir estudiandolo, ya que, a simple vista y despues de algunos intentos no puedo usar el sensoreventListener
gracias
felipe
14 de octubre de 2009 a 4:16
¿Qué problema te da el sensorEventListener?
Javier Cancela
14 de octubre de 2009 a 8:01
No entiendo que es mtop es tu código, y como puedo trabajar con los sensoreventListener, ya que, no los he podido declarar, en cambio lalógica de tu código la entindoe sin problemas
felipe
14 de octubre de 2009 a 15:11