Uso del acelerómetro en Android

En este tutorial, vamos a explorar cómo usar el acelerómetro, uno de los muchos sensores de hardware de los teléfonos inteligentes modernos, en una aplicación de Android. Explicaré qué es un acelerómetro y por qué puede ser algo que quiera aprovechar en sus aplicaciones de Android.

Introducción

Antes del amanecer de los teléfonos inteligentes, uno de los pocos componentes de hardware con los que las aplicaciones podían interactuar era el teclado. Pero los tiempos han cambiado y la interacción con los componentes de hardware es cada vez más común..

El uso de gestos a menudo resulta más natural que interactuar con una interfaz de usuario a través del mouse y el teclado. Esto es especialmente cierto para dispositivos táctiles, como teléfonos inteligentes y tabletas. Me parece que el uso de gestos puede dar vida a una aplicación de Android, lo que la hace más interesante y emocionante para el usuario.

Un buen número de aplicaciones están haciendo uso del acelerómetro. Por ejemplo, eche un vistazo a estas plantillas de aplicaciones en Envato Market, que incluyen un juego de carreras de velocidad y un agitador de números aleatorios.

En este tutorial, usaremos un gesto que encontrará en bastantes aplicaciones móviles, el gesto de agitar. Usaremos el gesto de agitar para generar aleatoriamente seis números de Lotería y mostrarlos en la pantalla con una bonita animación..

1. Empezando

Paso 1: Configuración del proyecto

Comience un nuevo proyecto de Android en su IDE (entorno de desarrollo integrado) favorito para el desarrollo de Android. Para este tutorial, estaré usando IntelliJ IDEA.

Si su IDE es compatible con el desarrollo de Android, habrá creado un Principal clase para ti El nombre de esta clase puede variar según el IDE que esté utilizando. los Principal La clase juega un papel clave cuando se inicia su aplicación. Su IDE también debería haber creado un archivo de diseño principal que Principal La clase utiliza para crear la interfaz de usuario de la aplicación..

Dado que vamos a utilizar un gesto de sacudir, es una buena idea bloquear la orientación del dispositivo. Esto asegurará que la interfaz de usuario de la aplicación no cambie constantemente entre vertical y horizontal. Abra el archivo de manifiesto del proyecto y establezca la orientación de la pantalla opción a retrato.

     

Paso 2: Configuración del sensor

Con nuestro proyecto configurado, es hora de ensuciarnos las manos y escribir un código. Por el momento, la clase de actividad principal tiene una onCreate Método en el que configuramos el diseño principal invocando. setContentView Como se muestra abajo.

clase pública principal extiende la actividad / ** llamada cuando la actividad se crea por primera vez. * / @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main); 

Dependiendo del IDE que esté utilizando, es posible que deba agregar algunas declaraciones de importación a Main.java, el archivo en el que tu Principal vida de clase La mayoría de los IDE insertarán estas declaraciones de importación para usted, pero quiero asegurarme de que estemos en la misma página antes de continuar. La primera declaración de importación, Importar android.app.Actividad, importa el Actividad clase mientras que la segunda declaración de importación, import android.os.Bundle, importa el Haz clase. La tercera declaración de importación, com.example.R, Contiene las definiciones de los recursos de la aplicación. Esta declaración de importación será diferente de la que se ve a continuación, ya que depende del nombre de su paquete..

importar android.app.Activity; importar android.os.Bundle; import com.example.R;

En el siguiente paso, aprovecharemos la SensorEventListener interfaz, que se declara en el SDK de Android. Usar el SensorEventListener interfaz, la Principal la clase de actividad necesita implementarla como se muestra en el fragmento de código a continuación. Si echas un vistazo a la actualización. Principal clase de actividad, encontrarás que uso el implementos palabra clave para decirle al compilador que el Principal clase implementa el SensorEventListener interfaz.

público clase Principal extiende Actividad implementa SensorEventListener / ** Llamado cuando la actividad se crea por primera vez. * / @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main); 

Usar el SensorEventListener interfaz, debe agregar otra declaración de importación como se muestra a continuación. La mayoría de los IDE agregarán inteligentemente la declaración de importación por lo que probablemente no tendrá que preocuparse por esto.

importar android.hardware.SensorEventListener;

Desde el momento, actualizas el Principal implementación de la clase como se muestra arriba, verá algunos errores emergentes. Esto no es sorprendente ya que necesitamos dos métodos para implementar dos métodos requeridos de SensorEventListener interfaz.

Si está utilizando IntelliJ IDEA, se le pedirá que agregue estos métodos necesarios cuando haga clic en el error. Si está utilizando un IDE diferente, este comportamiento puede ser diferente. Agreguemos los dos métodos requeridos a mano como se muestra en el fragmento de código a continuación. Asegúrese de agregar estos métodos en el Principal clase y fuera de la onCreate método.

@Override public void onSensorChanged (evento SensorEvent)  @Override public void onAccuracyChanged (Sensor sensor, int exactitud) 

Echemos un vistazo a la onSensorChanged método. Usaremos este método para detectar el gesto de agitar. los onSensorChanged El método se invoca cada vez que el sensor incorporado detecta un cambio. Este método se invoca repetidamente cuando el dispositivo está en movimiento. Usar el Sensor y SensorEvent clases, agregamos dos declaraciones de importación adicionales como se muestra a continuación.

importar android.hardware.Sensor; importar android.hardware.SensorEvent;

Antes de implementar onSensorChanged, Necesitamos declarar dos variables privadas en el Principal clase, senSensorManager de tipo SensorManager y senAccelerómetro de tipo Sensor.

privado SensorManager senSensorManager; Sensor senAccelerómetro privado;

los SensorManager clase se declara en android.hardware.SensorManager. Si está viendo algún error emergente, verifique que el SensorManager la clase es importada tambien.

importar android.hardware.SensorManager;

En el onCreate Método, inicializamos las variables que acabamos de declarar y registramos un oyente. Eche un vistazo a la implementación actualizada del onCreate método.

@Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); senSensorManager = (SensorManager) getSystemService (Context.SENSOR_SERVICE); senAccelerometer = senSensorManager.getDefaultSensor (Sensor.TYPE_ACCELEROMETER); senSensorManager.registerListener (este, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); 

Para inicializar el SensorManager instancia, invocamos getSystemService para buscar el sistema SensorManager instancia, que a su vez utilizamos para acceder a los sensores del sistema. los getSystemService El método se utiliza para obtener una referencia a un servicio del sistema al pasar el nombre del servicio. Con el administrador de sensores a nuestra disposición, obtenemos una referencia al acelerómetro del sistema invocando getDefaultSensor en el administrador de sensores y pasando el tipo de sensor que nos interesa. Luego registramos el sensor usando uno de los SensorManagerlos métodos públicos, registroListener. Este método acepta tres argumentos, el contexto de la actividad, un sensor y la velocidad a la que nos envían los eventos del sensor.

público clase Principal extiende Actividad implementa SensorEventListener private SensorManager senSensorManager; Sensor senAccelerómetro privado; /** Se llama cuando se crea por primera vez la actividad. * / @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main); senSensorManager = (SensorManager) getSystemService (Context.SENSOR_SERVICE); senAccelerometer = senSensorManager.getDefaultSensor (Sensor.TYPE_ACCELEROMETER); senSensorManager.registerListener (este, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);  @Override public void onSensorChanged (SensorEvent SensorEvent)  @Override public void onAccuracyChanged (Sensor Sensor, int precision) 

Hay otros dos métodos que debemos anular, en pausa y En resumen. Estos son métodos de la Principal clase. Es una buena práctica anular el registro del sensor cuando la aplicación hiberna y volver a registrar el sensor cuando se reanude la aplicación. Eche un vistazo a los fragmentos de código a continuación para tener una idea de cómo funciona esto en la práctica..

void protegido onPause () super.onPause (); senSensorManager.unregisterListener (this); 
void protegido onResume () super.onResume (); senSensorManager.registerListener (este, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); 

Paso 3: Detectando el gesto de Shake

Ahora podemos empezar a centrarnos en la carne de la aplicación. Se requerirá un poco de matemáticas para averiguar cuándo se produce un gesto de sacudida. La mayor parte de la lógica entrará en el onSensorChanged método. Comenzamos por declarar algunas variables en nuestra Principal clase. Eche un vistazo al fragmento de código a continuación..

privado long lastUpdate = 0; flotador privado last_x, last_y, last_z; final estático privado int SHAKE_THRESHOLD = 600;

Ahora vamos a hacer un zoom sobre la implementación de la onSensorChanged método. Tomamos una referencia a la Sensor instancia utilizando el SensorEvent instancia que se nos pasa. Como puede ver en el fragmento de código a continuación, verificamos que obtengamos una referencia al tipo de sensor correcto, el acelerómetro del sistema.

public void onSensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; if (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) 

El siguiente paso es extraer la posición del dispositivo en el espacio, el X, y, y z eje. Eche un vistazo a la imagen de abajo para comprender mejor a qué me refiero. los X eje define el movimiento lateral, mientras que el y El eje define el movimiento vertical. los z El eje es un poco más complicado ya que define el movimiento dentro y fuera del plano definido por el X y y hachas.


Para obtener los valores de cada eje, le pedimos al evento del sensor sus valores como se muestra a continuación. Los eventos valores atributo es una matriz de flotadores.

public void onSensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; if (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = sensorEvent.values ​​[0]; float y = sensorEvent.values ​​[1]; float z = sensorEvent.values ​​[2]; 

Los sensores del sistema son increíblemente sensibles. Cuando sostiene un dispositivo en su mano, está constantemente en movimiento, sin importar cuán firme sea su mano. El resultado es que el onSensorChanged El método se invoca varias veces por segundo. No necesitamos todos estos datos, por lo que debemos asegurarnos de que solo muestreamos un subconjunto de los datos que obtenemos del acelerómetro del dispositivo. Almacenamos la hora actual del sistema (en milisegundos) almacenamos en tiempo de curación y verifica si hay mas de 100 milisegundos han pasado desde la última vez onSensorChanged fue invocado.

public void onSensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; if (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = sensorEvent.values ​​[0]; float y = sensorEvent.values ​​[1]; float z = sensorEvent.values ​​[2]; long curTime = System.currentTimeMillis (); if ((curTime - lastUpdate)> 100) long diffTime = (curTime - lastUpdate); lastUpdate = curTime; 

La pieza final del rompecabezas es detectar si el dispositivo ha sido sacudido o no. Usamos el Mates clase para calcular la velocidad del dispositivo como se muestra a continuación. El estáticamente declarado SHAKE_THRESHOLD La variable se usa para ver si se ha detectado o no un gesto de sacudida. Modificando SHAKE_THRESHOLD aumenta o disminuye la sensibilidad, así que siéntete libre de jugar con su valor.

public void onSensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; if (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = sensorEvent.values ​​[0]; float y = sensorEvent.values ​​[1]; float z = sensorEvent.values ​​[2]; long curTime = System.currentTimeMillis (); if ((curTime - lastUpdate)> 100) long diffTime = (curTime - lastUpdate); lastUpdate = curTime; velocidad de flotación = Math.abs (x + y + z - last_x - last_y - last_z) / diffTime * 10000; if (velocidad> SHAKE_THRESHOLD)  last_x = x; last_y = y; last_z = z; 

2. Acabado de la solicitud de lotería.

Ahora tenemos una aplicación que puede detectar un gesto de sacudida con el acelerómetro. Terminemos este proyecto usando el gesto de agitar para elegir seis números de lotería aleatorios. Te mostraré cómo generar un número aleatorio entre 1 y 49, pero tiene la libertad de modificar mi implementación para que funcione con la forma en que se juega la lotería en su país.

Comencemos configurando el archivo de diseño principal de la aplicación que usaremos para la interfaz de usuario. Como puede ver a continuación, utilizo seis diseños de marcos con un fondo de una imagen de una bola.

                        

Cada diseño de marco contiene una vista de texto que mostrará un número de lotería generado aleatoriamente. Tenga en cuenta que cada diseño de marco y vista de texto tiene un carné de identidad Para asegurarnos de que podamos consultarlos más tarde..

Con el diseño principal listo para usar, revisemos el Principal clase. Comenzamos creando getRandomNumber, Un método privado para generar seis números aleatorios entre 1 y 49.

private void getRandomNumber () ArrayList numbersGenerated = new ArrayList (); para (int i = 0; i < 6; i++)  Random randNumber = new Random(); int iNumber = randNumber.nextInt(48) + 1; if(!numbersGenerated.contains(iNumber))  numbersGenerated.add(iNumber);  else  i--;   

Primero creamos un Lista de arreglo instancia, que utilizamos para almacenar los seis números en. En cada bucle de la para Loop, aprovechamos las de Java. Aleatorio Clase para generar un número aleatorio. Para asegurarse de que obtenemos un número entre 1 y 49, añadimos 1 al resultado. El siguiente paso es verificar si el número generado ya está en la lista de matriz, porque solo queremos números únicos en la lista de matriz.

Tenga en cuenta que puede ser necesario agregar dos instrucciones de importación más para mantener contento al compilador.

import java.util.ArrayList; import java.util.Random;

El último paso es mostrar el número generado aleatoriamente en la interfaz de usuario. Obtenemos una referencia a las vistas de texto que creamos anteriormente y rellenamos cada vista de texto con un número aleatorio. También agregamos una animación ordenada a los diseños de cuadros, pero siéntase libre de omitir o modificar la animación..

private void getRandomNumber () ArrayList numbersGenerated = new ArrayList (); para (int i = 0; i < 6; i++)  Random randNumber = new Random(); int iNumber = randNumber.nextInt(48) + 1; if(!numbersGenerated.contains(iNumber))  numbersGenerated.add(iNumber);  else  i--;   TextView text = (TextView)findViewById(R.id.number_1); text.setText(""+numbersGenerated.get(0)); text = (TextView)findViewById(R.id.number_2); text.setText(""+numbersGenerated.get(1)); text = (TextView)findViewById(R.id.number_3); text.setText(""+numbersGenerated.get(2)); text = (TextView)findViewById(R.id.number_4); text.setText(""+numbersGenerated.get(3)); text = (TextView)findViewById(R.id.number_5); text.setText(""+numbersGenerated.get(4)); text = (TextView)findViewById(R.id.number_6); text.setText(""+numbersGenerated.get(5)); FrameLayout ball1 = (FrameLayout) findViewById(R.id.ball_1); ball1.setVisibility(View.INVISIBLE); FrameLayout ball2 = (FrameLayout) findViewById(R.id.ball_2); ball2.setVisibility(View.INVISIBLE); FrameLayout ball3 = (FrameLayout) findViewById(R.id.ball_3); ball3.setVisibility(View.INVISIBLE); FrameLayout ball4 = (FrameLayout) findViewById(R.id.ball_4); ball4.setVisibility(View.INVISIBLE); FrameLayout ball5 = (FrameLayout) findViewById(R.id.ball_5); ball5.setVisibility(View.INVISIBLE); FrameLayout ball6 = (FrameLayout) findViewById(R.id.ball_6); ball6.setVisibility(View.INVISIBLE); Animation a = AnimationUtils.loadAnimation(this, R.anim.move_down_ball_first); ball6.setVisibility(View.VISIBLE); ball6.clearAnimation(); ball6.startAnimation(a); ball5.setVisibility(View.VISIBLE); ball5.clearAnimation(); ball5.startAnimation(a); ball4.setVisibility(View.VISIBLE); ball4.clearAnimation(); ball4.startAnimation(a); ball3.setVisibility(View.VISIBLE); ball3.clearAnimation(); ball3.startAnimation(a); ball2.setVisibility(View.VISIBLE); ball2.clearAnimation(); ball2.startAnimation(a); ball1.setVisibility(View.VISIBLE); ball1.clearAnimation(); ball1.startAnimation(a); 

Tendremos que agregar algunas declaraciones de importación más para que todo esto funcione. Eche un vistazo al fragmento de código a continuación..

importar android.view.View; import android.view.animation.Animation; import android.view.animation.AnimationUtils; importar android.widget.FrameLayout; importar android.widget.TextView;

En cuanto a las animaciones, eche un vistazo al contenido del siguiente archivo de animación. Tenga en cuenta que necesita crear un anim Carpeta en el directorio de recursos de su proyecto y nombrela move_down_ball_first.xml. Ajustando los valores de la escala Elemento, puedes modificar la duración de la animación y la posición de cada bola..

   

Todo lo que nos queda por hacer es llamar getRandomNumber en onSensorChanged en el Principal clase. Eche un vistazo a la implementación completa de onSensorChanged mostrado a continuación.

public void onSensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; if (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = sensorEvent.values ​​[0]; float y = sensorEvent.values ​​[1]; float z = sensorEvent.values ​​[2]; long curTime = System.currentTimeMillis (); if ((curTime - lastUpdate)> 100) long diffTime = (curTime - lastUpdate); lastUpdate = curTime; velocidad de flotación = Math.abs (x + y + z - last_x - last_y - last_z) / diffTime * 10000; if (velocidad> SHAKE_THRESHOLD) getRandomNumber ();  last_x = x; last_y = y; last_z = z; 

Conclusión

En este tutorial, te he mostrado cómo funciona el acelerómetro y cómo puedes usarlo para detectar un gesto de sacudida. Por supuesto, hay muchos otros casos de uso para el acelerómetro. Con una comprensión básica de la detección de gestos con el acelerómetro, te animo a experimentar con el acelerómetro para ver qué más puedes hacer con él..

Si trabajas mucho con el desarrollo de Android, es probable que encuentres situaciones en las que necesites ayuda con un aspecto en particular que no sea tu especialidad. Si es así, intente contratar a uno de los desarrolladores de aplicaciones expertos en Envato Studio para completar el trabajo de forma rápida y confiable.