How to detect movement of an android device?

后端 未结 6 1487
日久生厌
日久生厌 2020-12-04 09:51

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

相关标签:
6条回答
  • 2020-12-04 10:29

    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.                                                                     
    0 讨论(0)
  • 2020-12-04 10:32

    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
    }
    
    0 讨论(0)
  • 2020-12-04 10:35

    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();
    
    0 讨论(0)
  • 2020-12-04 10:46

    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;
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-04 10:49

    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).

    0 讨论(0)
  • 2020-12-04 10:50

    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

    0 讨论(0)
提交回复
热议问题