简体   繁体   English

如何检测Android设备的移动?

[英]How to detect movement of an android device?

I need suggestion about how to detect the amount of movement of an android device. 我需要有关如何检测Android设备的移动量的建议。 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. 假设我已将手机放在桌子或床上,然后如果有人敲击桌子或坐在或躺在床上,那么我想检测Android设备的移动。

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. 实际上我知道android有运动传感器API,但我不知道使用哪种传感器以及哪种传感器类型最适合这种类型的运动检测。

I would be glad if someone can share some basic demo code. 如果有人可以分享一些基本的演示代码,我会很高兴。

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
}

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() : 在我的活动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() : 在我的活动onResume()

MovementDetector.getInstance().start();

On my activity onPause() : 在我的活动onPause()

MovementDetector.getInstance().stop();

This code is for walking detection (Modified from @anthropomo code) 此代码用于步行检测(从@anthropomo代码修改)

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

虽然我没有演示代码(因为你不够具体),但是这里有一个好的开头: http//developer.android.com/guide/topics/sensors/sensors_motion.html (和左边的其他项目) )。

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 android有一个内置转换器,可以在你的手机上找到LINEAR ACCELERATION

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

this is a code where you can see how to get the raw value of LINEAR ACCELERATION 这是一个代码,您可以在其中查看如何获取LINEAR ACCELERATION的原始值

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. 我发现LINEAR ACCELERATION (和ACCELERATION )不够准确,不能正确测量位移。

This code should work a little better: 这段代码应该更好一点:

(ititialize) (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) (的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) (onSensorChanged和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];
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM