如何检测Android设备的移动?

Sur*_*dhi 32 android sensor motion

我需要有关如何检测Android设备的移动量的建议.假设我已将手机放在桌子或床上,然后如果有人敲击桌子或坐在或躺在床上,那么我想检测Android设备的移动.

实际上我知道android有运动传感器API但是我不知道使用哪种传感器以及哪种传感器类型最适合这种类型的运动检测.

如果有人可以分享一些基本的演示代码,我会很高兴.

ant*_*omo 55

绝对适用于加速度计:

// 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
}
Run Code Online (Sandbox Code Playgroud)

  • @BornToWin这个特殊的代码片段用于检测"摇动",因此是一个相对较大/快速的运动.看一下`if(mAccel> 3)`这一行.如果将该数字减少到1或0.5或0.25或更低,您可以在较低的阈值"做某事".如果你想检测倾斜,谷歌"Android检测倾斜".它是相关的,但不同. (7认同)
  • 当我顺利移动时,这不起作用.它只有在我摇动时才有效.如何做到平稳运动?当手机向左或向右倾斜时,它也无法正常工作 (3认同)
  • 请记住,对于 API > 23,您必须使用 ```(float)Math.sqrt(x*x + y*y + z*z);``` 来计算加速度。 (2认同)
  • 您能解释一下公式mAccel = mAccel * 0.9f +增量吗?``if(mAccel> 3)''中的3对应什么单位?对不起,我刚接触加速度计 (2认同)

Asa*_*ssi 17

我使用了以下课程:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

关于我的活动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);
            }

        }
    });
Run Code Online (Sandbox Code Playgroud)

关于我的活动onResume():

MovementDetector.getInstance().start();
Run Code Online (Sandbox Code Playgroud)

关于我的活动onPause():

MovementDetector.getInstance().stop();
Run Code Online (Sandbox Code Playgroud)


P.Z*_*ous 5

此代码用于步行检测(从@anthropomo 代码修改)

以获得更平滑的值。

// 初始化

private SensorManager sensorMan;
private Sensor accelerometer;

private float[] mGravity;
private double mAccel;
private double mAccelCurrent;
private double mAccelLast;

private boolean sensorRegistered = false;
Run Code Online (Sandbox Code Playgroud)

// 创建

    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;
Run Code Online (Sandbox Code Playgroud)

// 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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我不明白为什么要乘以 0.9:mAccel = mAccel * 0.9f + delta。mAccel有什么用? (3认同)