Как обнаружить движение устройства Android?
Мне нужно предложение о том, как определить количество движения устройства Android. Предположим, я положил телефон на стол или кровать, а затем, если кто-то постукивает по столу или сидит или укладывается на кровать, тогда я хочу обнаружить движение устройства андроида.
На самом деле я знаю, что у андроида есть API-интерфейсы датчиков движения, но я не знаю, какой датчик использовать и какой тип датчика лучше всего подходит для обнаружения такого типа.
Я был бы рад, если кто-то может поделиться базовым демо-кодом.
Ответы
Ответ 1
Определенно работать с акселерометром:
// 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
}
Ответ 2
Я использовал следующий класс:
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);
}
}
Использование:
В моей деятельности 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);
}
}
});
В моей деятельности onResume()
:
MovementDetector.getInstance().start();
В моей деятельности onPause()
:
MovementDetector.getInstance().stop();
Ответ 3
Этот код предназначен для обнаружения ходьбы (изменено с @anthropomo code)
чтобы получить более плавное значение.
//инициализировать
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;
}
}
}
Ответ 4
Пока у меня нет демо-кода (так как вы недостаточно конкретны), хороший старт здесь: http://developer.android.com/guide/topics/sensors/sensors_motion.html ( и другие предметы слева).
Ответ 5
если вы пытаетесь найти смещение вашего телефона, вам нужно найти
Линейное ускорение, действующее на ваш телефон, а не ускорение из-за силы тяжести
Android имеет встроенный конвертор, чтобы найти ЛИНЕЙНОЕ УСКОРЕНИЕ, действующее на вашем мобильном телефоне
https://github.com/yuvaramsingh94/AndroidSensorTestCode/tree/master
это код, в котором вы можете увидеть, как получить исходное значение LINEAR ACCELERATION