¿Cómo detectar el movimiento de un dispositivo Android?
Necesito sugerencia acerca de cómo detectar la cantidad de movimiento de un dispositivo Android. Supongamos que he puesto el teléfono en una mesa o cama y luego si alguien golpea la mesa o se sienta o laydown en la cama, entonces quiero detectar el movimiento del dispositivo Android.
En realidad sé que androide tiene sensores de movimiento APIs pero no sé qué sensor utilizar y qué tipo de sensor es mejor para este tipo de detección de movimiento.
- Lectura de la temperatura a través de DHT11 usando Android Things
- ¿Cómo obtener el azimut de un teléfono con lecturas de brújula y lecturas de giroscopio?
- Sensor de gravedad de Android (TYPE_GRAVITY) para 2.1
- Obtenga múltiples datos de sensores al mismo tiempo en Android
- ¿Cómo implementar el sensor de giroscopio en android?
Me alegraría que alguien pueda compartir algún código básico de demostración.
- Remapear el sistema de coordenadas en la aplicación para Android
- Mejor manera de implementar alertas de proximidad android
- Android - Aceleración hacia abajo (smash)
- Android Solución para los sensores que no funcionan cuando la pantalla está desactivada
- Sensor Fusion en Android 4
- Appcelerator Hyperloop Android - Cómo utilizar ciertas funciones de Sensor Manager que utilizan una estructura de paso por referencia
- La orientación de la pantalla de Android difiere entre los dispositivos
- Perfiles de Acelerómetro Android
Definitivamente trabajar con el acelerómetro:
// Start with some variables private SensorManager sensorMan; private Sensor accelerometer; private float[] mGravity; private float mAccel; private float mAccelCurrent; private float mAccelLast; // In onCreate method sensorMan = (SensorManager)getSystemService(SENSOR_SERVICE); accelerometer = sensorMan.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); mAccel = 0.00f; mAccelCurrent = SensorManager.GRAVITY_EARTH; mAccelLast = SensorManager.GRAVITY_EARTH; // And these: @Override public void onResume() { super.onResume(); sensorMan.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_UI); } @Override protected void onPause() { super.onPause(); sensorMan.unregisterListener(this); } @Override public void onSensorChanged(SensorEvent event) { if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){ mGravity = event.values.clone(); // Shake detection float x = mGravity[0]; float y = mGravity[1]; float z = mGravity[2]; mAccelLast = mAccelCurrent; mAccelCurrent = FloatMath.sqrt(x*x + y*y + z*z); float delta = mAccelCurrent - mAccelLast; mAccel = mAccel * 0.9f + delta; // Make this higher or lower according to how much // motion you want to detect if(mAccel > 3){ // do something } } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // required method }
He utilizado la siguiente clase:
public class MovementDetector implements SensorEventListener { protected final String TAG = getClass().getSimpleName(); private SensorManager sensorMan; private Sensor accelerometer; private MovementDetector() { } private static MovementDetector mInstance; public static MovementDetector getInstance() { if (mInstance == null) { mInstance = new MovementDetector(); mInstance.init(); } return mInstance; } ////////////////////// private HashSet<Listener> mListeners = new HashSet<MovementDetector.Listener>(); private void init() { sensorMan = (SensorManager) GlobalData.getInstance().getContext().getSystemService(Context.SENSOR_SERVICE); accelerometer = sensorMan.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION); } public void start() { sensorMan.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL); } public void stop() { sensorMan.unregisterListener(this); } public void addListener(Listener listener) { mListeners.add(listener); } /* (non-Javadoc) * @see android.hardware.SensorEventListener#onSensorChanged(android.hardware.SensorEvent) */ @Override public void onSensorChanged(SensorEvent event) { if (event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION) { float x = event.values[0]; float y = event.values[1]; float z = event.values[2]; float diff = (float) Math.sqrt(x * x + y * y + z * z); if (diff > 0.5) // 0.5 is a threshold, you can test it and change it Log.d(TAG,"Device motion detected!!!!"); for (Listener listener : mListeners) { listener.onMotionDetected(event, diff); } } } /* (non-Javadoc) * @see android.hardware.SensorEventListener#onAccuracyChanged(android.hardware.Sensor, int) */ @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // TODO Auto-generated method stub } public interface Listener { void onMotionDetected(SensorEvent event, float acceleration); } }
Uso:
Sobre mi actividad onCrate()
:
MovementDetector.getInstance().addListener(new MovementDetector.Listener() { @Override public void onMotionDetected(SensorEvent event, float acceleration) { mMotionDetectionTextView.setText("Acceleration: ["+String.format("%.3f",event.values[0])+","+String.format("%.3f",event.values[1])+","+String.format("%.3f",event.values[2])+"] "+String.format("%.3f", acceleration)); if (acceleration > SettingsHelper.getInstance().getMotionDetectionThreshold()){ mMotionDetectionTextView.setTextColor(Color.RED); } else { mMotionDetectionTextView.setTextColor(Color.WHITE); } } });
En mi actividad onResume()
:
MovementDetector.getInstance().start();
En mi actividad onPause()
:
MovementDetector.getInstance().stop();
Este código es para la detección de caminos (Modificado desde el código @anthropomo)
Para obtener un valor más suave.
// initialize
private SensorManager sensorMan; private Sensor accelerometer; private float[] mGravity; private double mAccel; private double mAccelCurrent; private double mAccelLast; private boolean sensorRegistered = false;
// onCreate
sensorMan = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); accelerometer = sensorMan.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); mAccel = 0.00f; mAccelCurrent = SensorManager.GRAVITY_EARTH; mAccelLast = SensorManager.GRAVITY_EARTH; sensorMan.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL); sensorRegistered = true;
// onSensorChanged
private int hitCount = 0; private double hitSum = 0; private double hitResult = 0; private final int SAMPLE_SIZE = 50; // change this sample size as you want, higher is more precise but slow measure. private final double THRESHOLD = 0.2; // change this threshold as you want, higher is more spike movement @Override public void onSensorChanged(SensorEvent event) { if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { mGravity = event.values.clone(); // Shake detection double x = mGravity[0]; double y = mGravity[1]; double z = mGravity[2]; mAccelLast = mAccelCurrent; mAccelCurrent = Math.sqrt(x * x + y * y + z * z); double delta = mAccelCurrent - mAccelLast; mAccel = mAccel * 0.9f + delta; if (hitCount <= SAMPLE_SIZE) { hitCount++; hitSum += Math.abs(mAccel); } else { hitResult = hitSum / SAMPLE_SIZE; Log.d(TAG, String.valueOf(hitResult)); if (hitResult > THRESHOLD) { Log.d(TAG, "Walking"); } else { Log.d(TAG, "Stop Walking"); } hitCount = 0; hitSum = 0; hitResult = 0; } } }
Aunque no tengo código de demostración (ya que no eres lo suficientemente específico), un buen comienzo está aquí: http://developer.android.com/guide/topics/sensors/sensors_motion.html (y otros elementos a la izquierda ).
Si usted está intentando encontrar el desplazamiento de su teléfono, usted necesita encontrar la aceleración linear que actúa en su teléfono algo que la aceleración debido a la gravedad
Android tiene un convertidor incorporado para encontrar la ACELERACIÓN LINEAL actuando en tu teléfono móvil
https://github.com/yuvaramsingh94/AndroidSensorTestCode/tree/master
Este es un código donde se puede ver cómo obtener el valor bruto de la aceleración lineal