How to detect movement of an android device?

我怕爱的太早我们不能终老 提交于 2019-11-26 22:33:29

问题


I need suggestion about how to detect the amount of movement of an android device. Suppose I have put the phone on a table or bed and then if somebody taps the table or sits or laydown on the bed then I want to detect the movement of the android device.

Actually I know that android has motion sensors APIs but I don't know which sensor to use and what sensor type is best for this type of movement detection.

I would be glad if someone can share some basic demo code.


回答1:


Definitely work with the accelerometer:

// 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:


I used the following class:

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);
    }
}

Usage:

On my activity 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);
            }

        }
    });

On my activity onResume():

MovementDetector.getInstance().start();

On my activity onPause():

MovementDetector.getInstance().stop();



回答3:


This code is for walking detection (Modified from @anthropomo code)

to get smoother value.

// 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;
        }
    }
}



回答4:


While I don't have demo code (since you aren't specific enough), a good start is here: http://developer.android.com/guide/topics/sensors/sensors_motion.html (and other items on the left).




回答5:


if you are trying to find the displacement of your phone, you need to find the Linear acceleration acting on your phone rather than the acceleration due to gravity

android has a built in converter to find the LINEAR ACCELERATION acting on your mobile phone

https://github.com/yuvaramsingh94/AndroidSensorTestCode/tree/master

this is a code where you can see how to get the raw value of LINEAR ACCELERATION




回答6:


I have been working with a similar idea to measure the displacement of the phone. I have found that the LINEAR ACCELERATION (and ACCELERATION) are not accurate enough to correctly measure the displacement.

This code should work a little better:

(ititialize)

private SensorManager sensorManager;
private Sensor accelerometer;
double[] maxAccelerations = new double[3];
double[] position = new double[3];
long[] times = new long[3];
// time combined with maxAcceleration can approximate the change in position,
// with the formula Δpos = (maxAcceleration * time ^ 2) / 6
long currentTime;

(onCreate)

sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION) != null) {
    accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
        sensorManager.registerListener(this, accelerometer, sensorManager.SENSOR_DELAY_FASTEST);
}
currentTime = System.currentTimeMillis();
for(int i=0;i<3;i++){
    times[i]=currentTime;
}
else{
    throw "Error";
    //Which will throw an error, if not the error that is expected. 😉
}

(onSensorChanged and onAccuracyChanged)

@Override
public void onAccuracyChanged(Sensor ignore, int thisFunction) {
}

@Override
public void onSensorChanged(SensorEvent event) {
    if (event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION) {
        for(int i=0;i<3;i++){
            if(Math.abs(event.values[i])<0.01){
                // Note: this is to try to prevent accelerating time from being counted when the phone is stationary. 0.01 should be
                // changed to an appropriate sensitivity level that can be calculated by finding an average noise level when the phone is stationary.
                times[i]=System.currentTimeMillis();
            }
            if(event.values[i]>maxAccelerations[i] && maxAccelerations[i]>=0){
                maxAccelerations[i]=event.values[i];
            }
            else if(event.values[i]<maxAccelerations[i] && maxAccelerations[i]<=0){
                maxAccelerations[i]=event.values[i];
            }
            else if(event.values[i]>0 && maxAccelerations[i]<0){
                currentTime = System.currentTimeMillis();
                position[i]+=maxAccelerations[i] * (times[i]-currentTime)*(times[i]-currentTime) / 6;
                times[i]=currentTime;
                maxAccelerations[i]=event.values[i];
            }
            else if(event.values[i]<0 && maxAccelerations[i]>0){
                currentTime = System.currentTimeMillis();
                position[i]+=maxAccelerations[i] * (times[i]-currentTime)*(times[i]-currentTime) / 6;
                times[i]=currentTime;
                maxAccelerations[i]=event.values[i];
            }
        }
    }
}


来源:https://stackoverflow.com/questions/14574879/how-to-detect-movement-of-an-android-device

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!