Bienvenidos sean a este post, hoy hablaremos sobre los sensores disponibles en nuestros dispositivos los cuales nos permitiran conocer a nuestro mundo exterior, estos no incluyen el microfono, camara y GPS. Los sensores son manipulados por medio del paquete android.hardware y a traves de las clases Sensor, SensorEvent y SensorManager, la interfaz para utilizarla es SensorEventListener, veamos la siguiente tabla con algunos de los sensores disponibles:
Tipo | Constantes | Funcion | Dim. | Unid. |
Acelerometro | TYPE_ACCELEROMETER | Mide aceleraciones por gravedad y cambio de movimiento | 3 | m/s |
Gravedad | TYPE_GRAVITY | Mide la aceleracion debida a la gravedad | 3 | m/s |
Acelerometro lineal | TYPE_LINEAR_ACCELERATION | Mide las aceleraciones sin tener en cuenta la gravedad | 3 | m/s |
Giroscopio | TYPE_GYROSCOPE | Mide los cambios de rotacion | 3 | rad/s |
Vector de rotacion | TYPE_ROTATION_VECTOR | Es para detectar rotaciones | 3 | a dimen sional |
Orientacion | TYPE_ORIENTATION | Direccion a la que apunta el dispositivo (obsoleto) | 3 | grado |
Campo magnetico | TYPE_MAGNETIC_FIELD | Brujula, detectar campos magneticos | 3 | uT |
Luz ambiental | TYPE_LIGHT | Luz ambiental, ideal para ajustar el brillo de pantalla | 1 | lx |
Proximidad | TYPE_PROXIMITY | Distancia a un objeto, ideal para saber si esta cerca de la oreja | 1 | cm |
Presion atmosferica | TYPE_PRESSURE | Barometro, se puede crear un altimero con el | 1 | hPa |
Temperatura ambiental | TYPE_AMBIENT_TEMPERATURE | Mide la temperatura del aire | 1 | °C |
Temperatura interna | TYPE_TEMPERATURE | Para evitar sobrecalentamientos (Obsoleta) | 1 | °C |
Humedad relativa | TYPE_RELATIVE_HUMIDITY | Mide el punto de rocio, humedad absoluta y relativa | 1 | % |
Movimiento significativo | TYPE_SIGNIFICANT_MOTION | Detecta si el dispositivo ha sido movido | trig ger | — |
Detector de pasos | TYPE_STEP_DETECTOR | Detecta cuando el usuario da un paso | tri ger | — |
Contador de pasos | TYPE_STEP_COUNTER | Cuenta la cantidad de pasos realizados desde el ultimo reinicio | 1 | paso |
Frecuencia cardiaca | TYPE_HEART_RATE | Monitorea el ritmo cardiaco en pulsos por minuto | 1 | rpm |
Como pueden ver nuestros dispositivos pueden obtener bastante informacion desde los sensores pero algunos son mas nuevos que otros, aca les paso el detalle desde que version de API se implementaron las constantes anteriores, esto es fundamental a la hora de crear nuestro proyecto porque necesitaran estar como minimo con esa version para poder trabajar con ella, pasemos al detalle:
- API 3:
TYPE_ACCELEROMETER, TYPE_GYROSCOPE, TYPE_ORIENTATION, TYPE_MAGNETIC_FIELD, TYPE_PROXIMITY, TYPE_PRESSURE, TYPE_TEMPERATURE - API 9:
TYPE_GRAVITY, TYPE_LINEAR_ACCELERATION, TYPE_ROTATION_VECTOR - API 14:
TYPE_AMBIENT_TEMPERATURE, TYPE_RELATIVE_HUMIDITY - API 18:
TYPE_SIGNIFICANT_MOTION - API 19:
TYPE_STEP_DETECTOR, TYPE_STEP_COUNTER - API 20:
TYPE_HEART_RATE
Como pueden ver a medida que se fueron mejorando los dispositivos se nos permitio obtener mejores datos, y tambien nos permitio dejar de utilizar algunos, en esta tabla tenemos dos casos, el primero es TYPE_ORIENTATION si bien este se puede seguir utilizando no se utiliza porque no detecta correctamente el cambio horizontal/vertical para ello se utiliza una funcion entre el acelerometro y el campo magnetico, nuestro segundo caso es TYPE_TEMPERATURE el cual a partir de la API 14 se empezo a utilizar TYPE_AMBIENT_TEMPERATURE, si bien estos dos tipos de sensores son obsoletos todavia se pueden seguir utilizando pero no es aconsejable.
Para entender un poco mejor el concepto de sensores procedamos a hacer un ejemplo, para ello abramos Android Studio y elijamos Start a new Android Studio project, nos aparecera un cuadro donde modificaremos el campo Application name por Sensores, y en Company domain usemos example.org, el resto queda como aparece, pulsamos Next para pasar al siguiente cuadro, en el elegiremos Phone And Tablet y no les recomiendo la version mas baja de API, en este caso elijan una entre 14 y 19 (en mi caso elegi la API 19), como para tener mas posibilidades de detectar otros sensores, una vez seleccionado pulsen Next, en el siguiente cuadro elijan Empty Activity y pulsen Next para pasar al ultimo cuadro donde dejaremos todo por defecto y pulsamos Finish para crear nuestra app, una vez creada vamos a ir a nuestro layout llamado activity_main.xml donde modificaremos al TextView para agregarle la siguiente linea:
android:id="@+id/salida"
Y modificaremos la linea de texto de la siguiente forma:
android:text=""
Con esta linea agregada y la otra modificada el elemento TextView debera quedar asi:
<TextView
android:id="@+id/salida"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Con esta modificacion realizada procederemos a modificar nuestra clase MainActivity con el siguiente codigo:
package org.example.sensores;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private TextView salida;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
salida = (TextView) findViewById(R.id.salida);
SensorManager sensorAdmin = (SensorManager)
getSystemService(SENSOR_SERVICE);
List listaSensores = sensorAdmin.
getSensorList(Sensor.TYPE_ALL);
for(Sensor sensor: listaSensores){
log(sensor.getName());
}
}
private void log(String cadena){
salida.append(cadena + "\n");
}
}
Este codigo se encargara de mostrarnos todos los sensores, primero crearemos un enlace a nuestro TextView y lo llamaremos salida, luego en el metodo onCreate() por medio del metodo findViewById() lo vincularemos al elemento del layout, nuestro siguiente paso sera crear un objeto llamado sensorAdmin de la clase SensorManager y en este caso utilizaremos el metodo getSystemService() a asociarlo al sistema servicios, este metodo pertenece a la clase Context, luego crearemos un List (Array) de la clsae Sensor llamado ListaSensores el cual almacenara todos los tipos de sensores disponibles en nuestro equipo, luego tendremos un bucle for encargado de tomar el nombre de cada uno de los sensores y mandarlos al metodo log(), este metodo es el encargado de agregar cada atributo recibido en nuestro TextView por medio del enlace salida, si lo probamos con nuestro emulador obtendremos una salida similar a esta:

Como pueden ver nos devolvio todos los sensores disponibles sobre nuestro equipo emulado o virtual, como quieran llamarlo, pero que sucederia si lo probamos sobre un equipo verdadero, obtendremos el siguiente resultado

Como pueden ver cambiaron los sensores, les recomiendo este post donde explico como probar nuestras apps con dispositivos reales porque obviamente en estos casos es mejor poder trabajar con ellos, veamos algunos de los metodos publicos disponibles de la clase Sensor en la siguiente tabla:
Metodo | Descripcion |
public float getMaximumRange() | Rango maximo de unidades del sensor |
public float getMinDelay() | Tiempo minimo entre dos eventos (en microsegundos) |
public string getName() | Nombre del sensor |
public float getPower() | Potencia del sensor mientras esta siendo usada en mA |
public float getResolution() | Resolucion en las unidades del sensor |
public int getType() | Tipo generico del sensor |
public String getVendor() | Devuelve el fabricante del sensor |
public int getVersion() | Devuelve la version del sensor |
Con esto visto vamos a hacer una pequeña modificacion para poder obtener los datos de nuestros sensores, primero vayamos a nuestra clase MainActivity y agreguemos las siguientes lineas en el metodo onCreate():
listaSensores = sensorAdmin.getSensorList(Sensor.TYPE_ORIENTATION);
if(!listaSensores.isEmpty()){
Sensor orientationSensor = listaSensores.get(0);
sensorAdmin.registerListener(this,orientationSensor,
SensorManager.SENSOR_DELAY_UI);
}
listaSensores = sensorAdmin.getSensorList(Sensor.TYPE_ACCELEROMETER);
if(!listaSensores.isEmpty()){
Sensor acelerometroSensor = listaSensores.get(0);
sensorAdmin.registerListener(this,acelerometroSensor,
SensorManager.SENSOR_DELAY_UI);
}
listaSensores = sensorAdmin.getSensorList(Sensor.TYPE_MAGNETIC_FIELD);
if(!listaSensores.isEmpty()) {
Sensor magneticSensor = listaSensores.get(0);
sensorAdmin.registerListener(this, magneticSensor,
SensorManager.SENSOR_DELAY_UI);
}
listaSensores = sensorAdmin.getSensorList(Sensor.TYPE_PROXIMITY);
if(!listaSensores.isEmpty()) {
Sensor proximidadSensor = listaSensores.get(0);
sensorAdmin.registerListener(this, proximidadSensor,
SensorManager.SENSOR_DELAY_UI);
}
En este caso vamos a utilizar cuatro sensores: orientacion, acelerometro, campo magnetico y proximidad. Cada bloque es similar pero cada uno esta para cada sensor, en listaSensores conseguiremos el tipo de sensor, despues tendremos un condicional donde chequeara que listaSensores no este vacio, si es verdad creara un objeto de la clase Sensor para asignar el sensor, luego utilizara el metodo registerListener() para registrar el sensor pero en este momento no funcionara para poder implementarlo deberemos hacer la siguiente modificacion de la declaracion de la clase:
public class MainActivity extends AppCompatActivity implements SensorEventListener {
Con esta implementacion podrems utilizar el registerListener(), ahora solo nos resta implementar dos metodos para poder recibir los datos, los metodos son los siguientes:
@Override
public void onAccuracyChanged(Sensor sensor, int precision){}
@Override
public void onSensorChanged(SensorEvent evento){
switch(evento.sensor.getType()){
case Sensor.TYPE_ORIENTATION:
for(int i = 0; i < 3; i++)
log("Orientacion "+i+": "+evento.values[i]);
break;
case Sensor.TYPE_ACCELEROMETER:
for(int i = 0; i < 3; i++)
log("Acelerometro "+i+": "+evento.values[i]);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
for(int i = 0; i < 3; i++)
log("Magnetico "+i+": "+evento.values[i]);
break;
default:
for(int i = 0; i < evento.values.length; i++)
log("Proximidad "+i+": "+evento.values[i]);
break;
}
}
Estos dos metodos deben estar como minimo para poder trabajar con los sensores en el primer metodo, onAccuracyChanged(), no necesitamos ejecutar ninguna instruccion sino simplemente que este entre las definiciones y por este motivo lo dejamos en blanco, es decir simplemente con las dos llaves ({}), el otro metodo (onSensorChanged()) por medio de un switch detectaremos el tipo de sensor y por medio de los cases le diremos que nos muestre los valores del mismo, en los tres primeros cases veremos los sensores de orientacion, acelerometro y campo magnetico y el default se encargara de proximidad, si compilamos nuestra app y la probamos obtendremos los siguientes valores

Probemos de dar vuelta nuestro equipo para ver el resultado

Y por ultimo probaremos nuestra app en un equipo real

Como pueden ver en el equipo real van a aparecer mas y mejores datos pero el equipo virtual en general tendra lo minimo para probar nuestras apps.
En resumen, hoy nos hemos introducido en el mundo de los sensores, de como podemos obtener datos de nuestro entorno y como podemos lograr tener una mejor ubicacion de nosotros y nuestro equipo, como en estos casos es mas recomendable verificarlo en los equipos reales, espero te haya sido util sigueme en Twitter, Facebook o Google+ para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Tambien podes donar
Es para mantenimiento del sitio, gracias!
$1.50